Initial boiler plate project

This commit is contained in:
2024-09-24 03:52:46 +00:00
parent 6120b2d6c3
commit 154b93e267
10034 changed files with 2079352 additions and 2 deletions

View File

@ -0,0 +1,125 @@
import { RouteKind } from "../future/route-kind";
import { Batcher } from "../../lib/batcher";
import { scheduleOnNextTick } from "../../lib/scheduler";
import { fromResponseCacheEntry, toResponseCacheEntry } from "./utils";
export * from "./types";
export default class ResponseCache {
constructor(minimalMode){
this.batcher = Batcher.create({
// Ensure on-demand revalidate doesn't block normal requests, it should be
// safe to run an on-demand revalidate for the same key as a normal request.
cacheKeyFn: ({ key, isOnDemandRevalidate })=>`${key}-${isOnDemandRevalidate ? "1" : "0"}`,
// We wait to do any async work until after we've added our promise to
// `pendingResponses` to ensure that any any other calls will reuse the
// same promise until we've fully finished our work.
schedulerFn: scheduleOnNextTick
});
// this is a hack to avoid Webpack knowing this is equal to this.minimalMode
// because we replace this.minimalMode to true in production bundles.
const minimalModeKey = "minimalMode";
this[minimalModeKey] = minimalMode;
}
async get(key, responseGenerator, context) {
// If there is no key for the cache, we can't possibly look this up in the
// cache so just return the result of the response generator.
if (!key) return responseGenerator(false, null);
const { incrementalCache, isOnDemandRevalidate = false } = context;
const response = await this.batcher.batch({
key,
isOnDemandRevalidate
}, async (cacheKey, resolve)=>{
var _this_previousCacheItem;
// We keep the previous cache entry around to leverage when the
// incremental cache is disabled in minimal mode.
if (this.minimalMode && ((_this_previousCacheItem = this.previousCacheItem) == null ? void 0 : _this_previousCacheItem.key) === cacheKey && this.previousCacheItem.expiresAt > Date.now()) {
return this.previousCacheItem.entry;
}
// Coerce the kindHint into a given kind for the incremental cache.
let kindHint;
if (context.routeKind === RouteKind.APP_PAGE || context.routeKind === RouteKind.APP_ROUTE) {
kindHint = "app";
} else if (context.routeKind === RouteKind.PAGES) {
kindHint = "pages";
}
let resolved = false;
let cachedResponse = null;
try {
cachedResponse = !this.minimalMode ? await incrementalCache.get(key, {
kindHint
}) : null;
if (cachedResponse && !isOnDemandRevalidate) {
var _cachedResponse_value;
if (((_cachedResponse_value = cachedResponse.value) == null ? void 0 : _cachedResponse_value.kind) === "FETCH") {
throw new Error(`invariant: unexpected cachedResponse of kind fetch in response cache`);
}
resolve({
...cachedResponse,
revalidate: cachedResponse.curRevalidate
});
resolved = true;
if (!cachedResponse.isStale || context.isPrefetch) {
// The cached value is still valid, so we don't need
// to update it yet.
return null;
}
}
const cacheEntry = await responseGenerator(resolved, cachedResponse, true);
// If the cache entry couldn't be generated, we don't want to cache
// the result.
if (!cacheEntry) {
// Unset the previous cache item if it was set.
if (this.minimalMode) this.previousCacheItem = undefined;
return null;
}
const resolveValue = await fromResponseCacheEntry({
...cacheEntry,
isMiss: !cachedResponse
});
if (!resolveValue) {
// Unset the previous cache item if it was set.
if (this.minimalMode) this.previousCacheItem = undefined;
return null;
}
// For on-demand revalidate wait to resolve until cache is set.
// Otherwise resolve now.
if (!isOnDemandRevalidate && !resolved) {
resolve(resolveValue);
resolved = true;
}
if (typeof resolveValue.revalidate !== "undefined") {
if (this.minimalMode) {
this.previousCacheItem = {
key: cacheKey,
entry: resolveValue,
expiresAt: Date.now() + 1000
};
} else {
await incrementalCache.set(key, resolveValue.value, {
revalidate: resolveValue.revalidate
});
}
}
return resolveValue;
} catch (err) {
// When a getStaticProps path is erroring we automatically re-set the
// existing cache under a new expiration to prevent non-stop retrying.
if (cachedResponse) {
await incrementalCache.set(key, cachedResponse.value, {
revalidate: Math.min(Math.max(cachedResponse.revalidate || 3, 3), 30)
});
}
// While revalidating in the background we can't reject as we already
// resolved the cache entry so log the error here.
if (resolved) {
console.error(err);
return null;
}
// We haven't resolved yet, so let's throw to indicate an error.
throw err;
}
});
return toResponseCacheEntry(response);
}
}
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/response-cache/index.ts"],"names":["RouteKind","Batcher","scheduleOnNextTick","fromResponseCacheEntry","toResponseCacheEntry","ResponseCache","constructor","minimalMode","batcher","create","cacheKeyFn","key","isOnDemandRevalidate","schedulerFn","minimalModeKey","get","responseGenerator","context","incrementalCache","response","batch","cacheKey","resolve","previousCacheItem","expiresAt","Date","now","entry","kindHint","routeKind","APP_PAGE","APP_ROUTE","PAGES","resolved","cachedResponse","value","kind","Error","revalidate","curRevalidate","isStale","isPrefetch","cacheEntry","undefined","resolveValue","isMiss","set","err","Math","min","max","console","error"],"mappings":"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"}

View File

@ -0,0 +1,3 @@
export { };
//# sourceMappingURL=types.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/response-cache/types.ts"],"names":[],"mappings":"AAoIA,WAgBC"}

View File

@ -0,0 +1,37 @@
import RenderResult from "../render-result";
export async function fromResponseCacheEntry(cacheEntry) {
var _cacheEntry_value;
return {
...cacheEntry,
value: ((_cacheEntry_value = cacheEntry.value) == null ? void 0 : _cacheEntry_value.kind) === "PAGE" ? {
kind: "PAGE",
html: await cacheEntry.value.html.toUnchunkedString(true),
postponed: cacheEntry.value.postponed,
pageData: cacheEntry.value.pageData,
headers: cacheEntry.value.headers,
status: cacheEntry.value.status
} : cacheEntry.value
};
}
export async function toResponseCacheEntry(response) {
var _response_value, _response_value1;
if (!response) return null;
if (((_response_value = response.value) == null ? void 0 : _response_value.kind) === "FETCH") {
throw new Error("Invariant: unexpected cachedResponse of kind fetch in response cache");
}
return {
isMiss: response.isMiss,
isStale: response.isStale,
revalidate: response.revalidate,
value: ((_response_value1 = response.value) == null ? void 0 : _response_value1.kind) === "PAGE" ? {
kind: "PAGE",
html: RenderResult.fromStatic(response.value.html),
pageData: response.value.pageData,
postponed: response.value.postponed,
headers: response.value.headers,
status: response.value.status
} : response.value
};
}
//# sourceMappingURL=utils.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/response-cache/utils.ts"],"names":["RenderResult","fromResponseCacheEntry","cacheEntry","value","kind","html","toUnchunkedString","postponed","pageData","headers","status","toResponseCacheEntry","response","Error","isMiss","isStale","revalidate","fromStatic"],"mappings":"AAEA,OAAOA,kBAAkB,mBAAkB;AAE3C,OAAO,eAAeC,uBACpBC,UAA8B;QAK1BA;IAHJ,OAAO;QACL,GAAGA,UAAU;QACbC,OACED,EAAAA,oBAAAA,WAAWC,KAAK,qBAAhBD,kBAAkBE,IAAI,MAAK,SACvB;YACEA,MAAM;YACNC,MAAM,MAAMH,WAAWC,KAAK,CAACE,IAAI,CAACC,iBAAiB,CAAC;YACpDC,WAAWL,WAAWC,KAAK,CAACI,SAAS;YACrCC,UAAUN,WAAWC,KAAK,CAACK,QAAQ;YACnCC,SAASP,WAAWC,KAAK,CAACM,OAAO;YACjCC,QAAQR,WAAWC,KAAK,CAACO,MAAM;QACjC,IACAR,WAAWC,KAAK;IACxB;AACF;AAEA,OAAO,eAAeQ,qBACpBC,QAA8B;QAI1BA,iBAWAA;IAbJ,IAAI,CAACA,UAAU,OAAO;IAEtB,IAAIA,EAAAA,kBAAAA,SAAST,KAAK,qBAAdS,gBAAgBR,IAAI,MAAK,SAAS;QACpC,MAAM,IAAIS,MACR;IAEJ;IAEA,OAAO;QACLC,QAAQF,SAASE,MAAM;QACvBC,SAASH,SAASG,OAAO;QACzBC,YAAYJ,SAASI,UAAU;QAC/Bb,OACES,EAAAA,mBAAAA,SAAST,KAAK,qBAAdS,iBAAgBR,IAAI,MAAK,SACrB;YACEA,MAAM;YACNC,MAAML,aAAaiB,UAAU,CAACL,SAAST,KAAK,CAACE,IAAI;YACjDG,UAAUI,SAAST,KAAK,CAACK,QAAQ;YACjCD,WAAWK,SAAST,KAAK,CAACI,SAAS;YACnCE,SAASG,SAAST,KAAK,CAACM,OAAO;YAC/BC,QAAQE,SAAST,KAAK,CAACO,MAAM;QAC/B,IACAE,SAAST,KAAK;IACtB;AACF"}

View File

@ -0,0 +1,85 @@
import { DetachedPromise } from "../../lib/detached-promise";
/**
* In the web server, there is currently no incremental cache provided and we
* always SSR the page.
*/ export default class WebResponseCache {
constructor(minimalMode){
this.pendingResponses = new Map();
// this is a hack to avoid Webpack knowing this is equal to this.minimalMode
// because we replace this.minimalMode to true in production bundles.
Object.assign(this, {
minimalMode
});
}
get(key, responseGenerator, context) {
var _this_previousCacheItem;
// ensure on-demand revalidate doesn't block normal requests
const pendingResponseKey = key ? `${key}-${context.isOnDemandRevalidate ? "1" : "0"}` : null;
const pendingResponse = pendingResponseKey ? this.pendingResponses.get(pendingResponseKey) : null;
if (pendingResponse) {
return pendingResponse;
}
const { promise, resolve: resolver, reject: rejecter } = new DetachedPromise();
if (pendingResponseKey) {
this.pendingResponses.set(pendingResponseKey, promise);
}
let resolved = false;
const resolve = (cacheEntry)=>{
if (pendingResponseKey) {
// Ensure all reads from the cache get the latest value.
this.pendingResponses.set(pendingResponseKey, Promise.resolve(cacheEntry));
}
if (!resolved) {
resolved = true;
resolver(cacheEntry);
}
};
// we keep the previous cache entry around to leverage
// when the incremental cache is disabled in minimal mode
if (pendingResponseKey && this.minimalMode && ((_this_previousCacheItem = this.previousCacheItem) == null ? void 0 : _this_previousCacheItem.key) === pendingResponseKey && this.previousCacheItem.expiresAt > Date.now()) {
resolve(this.previousCacheItem.entry);
this.pendingResponses.delete(pendingResponseKey);
return promise;
}
(async ()=>{
try {
const cacheEntry = await responseGenerator(resolved);
const resolveValue = cacheEntry === null ? null : {
...cacheEntry,
isMiss: true
};
// for on-demand revalidate wait to resolve until cache is set
if (!context.isOnDemandRevalidate) {
resolve(resolveValue);
}
if (key && cacheEntry && typeof cacheEntry.revalidate !== "undefined") {
this.previousCacheItem = {
key: pendingResponseKey || key,
entry: cacheEntry,
expiresAt: Date.now() + 1000
};
} else {
this.previousCacheItem = undefined;
}
if (context.isOnDemandRevalidate) {
resolve(resolveValue);
}
} catch (err) {
// while revalidating in the background we can't reject as
// we already resolved the cache entry so log the error here
if (resolved) {
console.error(err);
} else {
rejecter(err);
}
} finally{
if (pendingResponseKey) {
this.pendingResponses.delete(pendingResponseKey);
}
}
})();
return promise;
}
}
//# sourceMappingURL=web.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/response-cache/web.ts"],"names":["DetachedPromise","WebResponseCache","constructor","minimalMode","pendingResponses","Map","Object","assign","get","key","responseGenerator","context","pendingResponseKey","isOnDemandRevalidate","pendingResponse","promise","resolve","resolver","reject","rejecter","set","resolved","cacheEntry","Promise","previousCacheItem","expiresAt","Date","now","entry","delete","resolveValue","isMiss","revalidate","undefined","err","console","error"],"mappings":"AAAA,SAASA,eAAe,QAAQ,6BAA4B;AAG5D;;;CAGC,GACD,eAAe,MAAMC;IASnBC,YAAYC,WAAoB,CAAE;QAChC,IAAI,CAACC,gBAAgB,GAAG,IAAIC;QAC5B,4EAA4E;QAC5E,qEAAqE;QACrEC,OAAOC,MAAM,CAAC,IAAI,EAAE;YAAEJ;QAAY;IACpC;IAEOK,IACLC,GAAkB,EAClBC,iBAAoC,EACpCC,OAIC,EACmC;YA0ClC;QAzCF,4DAA4D;QAC5D,MAAMC,qBAAqBH,MACvB,CAAC,EAAEA,IAAI,CAAC,EAAEE,QAAQE,oBAAoB,GAAG,MAAM,IAAI,CAAC,GACpD;QAEJ,MAAMC,kBAAkBF,qBACpB,IAAI,CAACR,gBAAgB,CAACI,GAAG,CAACI,sBAC1B;QACJ,IAAIE,iBAAiB;YACnB,OAAOA;QACT;QAEA,MAAM,EACJC,OAAO,EACPC,SAASC,QAAQ,EACjBC,QAAQC,QAAQ,EACjB,GAAG,IAAInB;QACR,IAAIY,oBAAoB;YACtB,IAAI,CAACR,gBAAgB,CAACgB,GAAG,CAACR,oBAAoBG;QAChD;QAEA,IAAIM,WAAW;QACf,MAAML,UAAU,CAACM;YACf,IAAIV,oBAAoB;gBACtB,wDAAwD;gBACxD,IAAI,CAACR,gBAAgB,CAACgB,GAAG,CACvBR,oBACAW,QAAQP,OAAO,CAACM;YAEpB;YACA,IAAI,CAACD,UAAU;gBACbA,WAAW;gBACXJ,SAASK;YACX;QACF;QAEA,sDAAsD;QACtD,yDAAyD;QACzD,IACEV,sBACA,IAAI,CAACT,WAAW,IAChB,EAAA,0BAAA,IAAI,CAACqB,iBAAiB,qBAAtB,wBAAwBf,GAAG,MAAKG,sBAChC,IAAI,CAACY,iBAAiB,CAACC,SAAS,GAAGC,KAAKC,GAAG,IAC3C;YACAX,QAAQ,IAAI,CAACQ,iBAAiB,CAACI,KAAK;YACpC,IAAI,CAACxB,gBAAgB,CAACyB,MAAM,CAACjB;YAC7B,OAAOG;QACT;QAKE,CAAA;YACA,IAAI;gBACF,MAAMO,aAAa,MAAMZ,kBAAkBW;gBAC3C,MAAMS,eACJR,eAAe,OACX,OACA;oBACE,GAAGA,UAAU;oBACbS,QAAQ;gBACV;gBAEN,8DAA8D;gBAC9D,IAAI,CAACpB,QAAQE,oBAAoB,EAAE;oBACjCG,QAAQc;gBACV;gBAEA,IAAIrB,OAAOa,cAAc,OAAOA,WAAWU,UAAU,KAAK,aAAa;oBACrE,IAAI,CAACR,iBAAiB,GAAG;wBACvBf,KAAKG,sBAAsBH;wBAC3BmB,OAAON;wBACPG,WAAWC,KAAKC,GAAG,KAAK;oBAC1B;gBACF,OAAO;oBACL,IAAI,CAACH,iBAAiB,GAAGS;gBAC3B;gBAEA,IAAItB,QAAQE,oBAAoB,EAAE;oBAChCG,QAAQc;gBACV;YACF,EAAE,OAAOI,KAAK;gBACZ,0DAA0D;gBAC1D,4DAA4D;gBAC5D,IAAIb,UAAU;oBACZc,QAAQC,KAAK,CAACF;gBAChB,OAAO;oBACLf,SAASe;gBACX;YACF,SAAU;gBACR,IAAItB,oBAAoB;oBACtB,IAAI,CAACR,gBAAgB,CAACyB,MAAM,CAACjB;gBAC/B;YACF;QACF,CAAA;QACA,OAAOG;IACT;AACF"}