-
This commit is contained in:
parent
43b92408cb
commit
be1ac8e0ed
547
.open-next/.build/cache.cjs
Normal file
547
.open-next/.build/cache.cjs
Normal file
|
|
@ -0,0 +1,547 @@
|
||||||
|
globalThis.disableIncrementalCache = false;globalThis.disableDynamoDBCache = false;globalThis.isNextAfter15 = true;globalThis.openNextDebug = false;globalThis.openNextVersion = "3.9.16";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/cache.js
|
||||||
|
var cache_exports = {};
|
||||||
|
__export(cache_exports, {
|
||||||
|
SOFT_TAG_PREFIX: () => SOFT_TAG_PREFIX,
|
||||||
|
default: () => Cache
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(cache_exports);
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/error.js
|
||||||
|
function isOpenNextError(e) {
|
||||||
|
try {
|
||||||
|
return "__openNextInternal" in e;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/logger.js
|
||||||
|
function debug(...args) {
|
||||||
|
if (globalThis.openNextDebug) {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function warn(...args) {
|
||||||
|
console.warn(...args);
|
||||||
|
}
|
||||||
|
var DOWNPLAYED_ERROR_LOGS = [
|
||||||
|
{
|
||||||
|
clientName: "S3Client",
|
||||||
|
commandName: "GetObjectCommand",
|
||||||
|
errorName: "NoSuchKey"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var isDownplayedErrorLog = (errorLog) => DOWNPLAYED_ERROR_LOGS.some((downplayedInput) => downplayedInput.clientName === errorLog?.clientName && downplayedInput.commandName === errorLog?.commandName && (downplayedInput.errorName === errorLog?.error?.name || downplayedInput.errorName === errorLog?.error?.Code));
|
||||||
|
function error(...args) {
|
||||||
|
if (args.some((arg) => isDownplayedErrorLog(arg))) {
|
||||||
|
return debug(...args);
|
||||||
|
}
|
||||||
|
if (args.some((arg) => isOpenNextError(arg))) {
|
||||||
|
const error2 = args.find((arg) => isOpenNextError(arg));
|
||||||
|
if (error2.logLevel < getOpenNextErrorLogLevel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 0) {
|
||||||
|
return console.log(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 1) {
|
||||||
|
return warn(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
return console.error(...args);
|
||||||
|
}
|
||||||
|
console.error(...args);
|
||||||
|
}
|
||||||
|
function getOpenNextErrorLogLevel() {
|
||||||
|
const strLevel = process.env.OPEN_NEXT_ERROR_LOG_LEVEL ?? "1";
|
||||||
|
switch (strLevel.toLowerCase()) {
|
||||||
|
case "debug":
|
||||||
|
case "0":
|
||||||
|
return 0;
|
||||||
|
case "error":
|
||||||
|
case "2":
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/cache.js
|
||||||
|
async function hasBeenRevalidated(key, tags, cacheEntry) {
|
||||||
|
if (globalThis.openNextConfig.dangerous?.disableTagCache) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const value = cacheEntry.value;
|
||||||
|
if (!value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ("type" in cacheEntry && cacheEntry.type === "page") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const lastModified = cacheEntry.lastModified ?? Date.now();
|
||||||
|
if (globalThis.tagCache.mode === "nextMode") {
|
||||||
|
return tags.length === 0 ? false : await globalThis.tagCache.hasBeenRevalidated(tags, lastModified);
|
||||||
|
}
|
||||||
|
const _lastModified = await globalThis.tagCache.getLastModified(key, lastModified);
|
||||||
|
return _lastModified === -1;
|
||||||
|
}
|
||||||
|
function getTagsFromValue(value) {
|
||||||
|
if (!value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const cacheTags = value.meta?.headers?.["x-next-cache-tags"]?.split(",") ?? [];
|
||||||
|
delete value.meta?.headers?.["x-next-cache-tags"];
|
||||||
|
return cacheTags;
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getTagKey(tag) {
|
||||||
|
if (typeof tag === "string") {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
return JSON.stringify({
|
||||||
|
tag: tag.tag,
|
||||||
|
path: tag.path
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function writeTags(tags) {
|
||||||
|
const store = globalThis.__openNextAls.getStore();
|
||||||
|
debug("Writing tags", tags, store);
|
||||||
|
if (!store || globalThis.openNextConfig.dangerous?.disableTagCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tagsToWrite = tags.filter((t) => {
|
||||||
|
const tagKey = getTagKey(t);
|
||||||
|
const shouldWrite = !store.writtenTags.has(tagKey);
|
||||||
|
if (shouldWrite) {
|
||||||
|
store.writtenTags.add(tagKey);
|
||||||
|
}
|
||||||
|
return shouldWrite;
|
||||||
|
});
|
||||||
|
if (tagsToWrite.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await globalThis.tagCache.writeTags(tagsToWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/binary.js
|
||||||
|
var commonBinaryMimeTypes = /* @__PURE__ */ new Set([
|
||||||
|
"application/octet-stream",
|
||||||
|
// Docs
|
||||||
|
"application/epub+zip",
|
||||||
|
"application/msword",
|
||||||
|
"application/pdf",
|
||||||
|
"application/rtf",
|
||||||
|
"application/vnd.amazon.ebook",
|
||||||
|
"application/vnd.ms-excel",
|
||||||
|
"application/vnd.ms-powerpoint",
|
||||||
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
// Fonts
|
||||||
|
"font/otf",
|
||||||
|
"font/woff",
|
||||||
|
"font/woff2",
|
||||||
|
// Images
|
||||||
|
"image/bmp",
|
||||||
|
"image/gif",
|
||||||
|
"image/jpeg",
|
||||||
|
"image/png",
|
||||||
|
"image/tiff",
|
||||||
|
"image/vnd.microsoft.icon",
|
||||||
|
"image/webp",
|
||||||
|
// Audio
|
||||||
|
"audio/3gpp",
|
||||||
|
"audio/aac",
|
||||||
|
"audio/basic",
|
||||||
|
"audio/flac",
|
||||||
|
"audio/mpeg",
|
||||||
|
"audio/ogg",
|
||||||
|
"audio/wavaudio/webm",
|
||||||
|
"audio/x-aiff",
|
||||||
|
"audio/x-midi",
|
||||||
|
"audio/x-wav",
|
||||||
|
// Video
|
||||||
|
"video/3gpp",
|
||||||
|
"video/mp2t",
|
||||||
|
"video/mpeg",
|
||||||
|
"video/ogg",
|
||||||
|
"video/quicktime",
|
||||||
|
"video/webm",
|
||||||
|
"video/x-msvideo",
|
||||||
|
// Archives
|
||||||
|
"application/java-archive",
|
||||||
|
"application/vnd.apple.installer+xml",
|
||||||
|
"application/x-7z-compressed",
|
||||||
|
"application/x-apple-diskimage",
|
||||||
|
"application/x-bzip",
|
||||||
|
"application/x-bzip2",
|
||||||
|
"application/x-gzip",
|
||||||
|
"application/x-java-archive",
|
||||||
|
"application/x-rar-compressed",
|
||||||
|
"application/x-tar",
|
||||||
|
"application/x-zip",
|
||||||
|
"application/zip",
|
||||||
|
// Serialized data
|
||||||
|
"application/x-protobuf"
|
||||||
|
]);
|
||||||
|
function isBinaryContentType(contentType) {
|
||||||
|
if (!contentType)
|
||||||
|
return false;
|
||||||
|
const value = contentType.split(";")[0];
|
||||||
|
return commonBinaryMimeTypes.has(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/cache.js
|
||||||
|
var SOFT_TAG_PREFIX = "_N_T_/";
|
||||||
|
function isFetchCache(options) {
|
||||||
|
if (typeof options === "boolean") {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
if (typeof options === "object") {
|
||||||
|
return options.kindHint === "fetch" || options.fetchCache || options.kind === "FETCH";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var Cache = class {
|
||||||
|
async get(key, options) {
|
||||||
|
if (globalThis.openNextConfig.dangerous?.disableIncrementalCache) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const softTags = typeof options === "object" ? options.softTags : [];
|
||||||
|
const tags = typeof options === "object" ? options.tags : [];
|
||||||
|
return isFetchCache(options) ? this.getFetchCache(key, softTags, tags) : this.getIncrementalCache(key);
|
||||||
|
}
|
||||||
|
async getFetchCache(key, softTags, tags) {
|
||||||
|
debug("get fetch cache", { key, softTags, tags });
|
||||||
|
try {
|
||||||
|
const cachedEntry = await globalThis.incrementalCache.get(key, "fetch");
|
||||||
|
if (cachedEntry?.value === void 0)
|
||||||
|
return null;
|
||||||
|
const _tags = [...tags ?? [], ...softTags ?? []];
|
||||||
|
const _lastModified = cachedEntry.lastModified ?? Date.now();
|
||||||
|
const _hasBeenRevalidated = cachedEntry.shouldBypassTagCache ? false : await hasBeenRevalidated(key, _tags, cachedEntry);
|
||||||
|
if (_hasBeenRevalidated)
|
||||||
|
return null;
|
||||||
|
if ((tags ?? []).length === 0) {
|
||||||
|
const path = softTags?.find((tag) => tag.startsWith(SOFT_TAG_PREFIX) && !tag.endsWith("layout") && !tag.endsWith("page"));
|
||||||
|
if (path) {
|
||||||
|
const hasPathBeenUpdated = cachedEntry.shouldBypassTagCache ? false : await hasBeenRevalidated(path.replace(SOFT_TAG_PREFIX, ""), [], cachedEntry);
|
||||||
|
if (hasPathBeenUpdated) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
lastModified: _lastModified,
|
||||||
|
value: cachedEntry.value
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
debug("Failed to get fetch cache", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async getIncrementalCache(key) {
|
||||||
|
try {
|
||||||
|
const cachedEntry = await globalThis.incrementalCache.get(key, "cache");
|
||||||
|
if (!cachedEntry?.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const cacheData = cachedEntry.value;
|
||||||
|
const meta = cacheData.meta;
|
||||||
|
const tags = getTagsFromValue(cacheData);
|
||||||
|
const _lastModified = cachedEntry.lastModified ?? Date.now();
|
||||||
|
const _hasBeenRevalidated = cachedEntry.shouldBypassTagCache ? false : await hasBeenRevalidated(key, tags, cachedEntry);
|
||||||
|
if (_hasBeenRevalidated)
|
||||||
|
return null;
|
||||||
|
const store = globalThis.__openNextAls.getStore();
|
||||||
|
if (store) {
|
||||||
|
store.lastModified = _lastModified;
|
||||||
|
}
|
||||||
|
if (cacheData?.type === "route") {
|
||||||
|
return {
|
||||||
|
lastModified: _lastModified,
|
||||||
|
value: {
|
||||||
|
kind: globalThis.isNextAfter15 ? "APP_ROUTE" : "ROUTE",
|
||||||
|
body: Buffer.from(cacheData.body ?? Buffer.alloc(0), isBinaryContentType(String(meta?.headers?.["content-type"])) ? "base64" : "utf8"),
|
||||||
|
status: meta?.status,
|
||||||
|
headers: meta?.headers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (cacheData?.type === "page" || cacheData?.type === "app") {
|
||||||
|
if (globalThis.isNextAfter15 && cacheData?.type === "app") {
|
||||||
|
const segmentData = /* @__PURE__ */ new Map();
|
||||||
|
if (cacheData.segmentData) {
|
||||||
|
for (const [segmentPath, segmentContent] of Object.entries(cacheData.segmentData ?? {})) {
|
||||||
|
segmentData.set(segmentPath, Buffer.from(segmentContent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
lastModified: _lastModified,
|
||||||
|
value: {
|
||||||
|
kind: "APP_PAGE",
|
||||||
|
html: cacheData.html,
|
||||||
|
rscData: Buffer.from(cacheData.rsc),
|
||||||
|
status: meta?.status,
|
||||||
|
headers: meta?.headers,
|
||||||
|
postponed: meta?.postponed,
|
||||||
|
segmentData
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
lastModified: _lastModified,
|
||||||
|
value: {
|
||||||
|
kind: globalThis.isNextAfter15 ? "PAGES" : "PAGE",
|
||||||
|
html: cacheData.html,
|
||||||
|
pageData: cacheData.type === "page" ? cacheData.json : cacheData.rsc,
|
||||||
|
status: meta?.status,
|
||||||
|
headers: meta?.headers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (cacheData?.type === "redirect") {
|
||||||
|
return {
|
||||||
|
lastModified: _lastModified,
|
||||||
|
value: {
|
||||||
|
kind: "REDIRECT",
|
||||||
|
props: cacheData.props
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
warn("Unknown cache type", cacheData);
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
debug("Failed to get body cache", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async set(key, data, ctx) {
|
||||||
|
if (globalThis.openNextConfig.dangerous?.disableIncrementalCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const detachedPromise = globalThis.__openNextAls.getStore()?.pendingPromiseRunner.withResolvers();
|
||||||
|
try {
|
||||||
|
if (data === null || data === void 0) {
|
||||||
|
await globalThis.incrementalCache.delete(key);
|
||||||
|
} else {
|
||||||
|
const revalidate = this.extractRevalidateForSet(ctx);
|
||||||
|
switch (data.kind) {
|
||||||
|
case "ROUTE":
|
||||||
|
case "APP_ROUTE": {
|
||||||
|
const { body, status, headers } = data;
|
||||||
|
await globalThis.incrementalCache.set(key, {
|
||||||
|
type: "route",
|
||||||
|
body: body.toString(isBinaryContentType(String(headers["content-type"])) ? "base64" : "utf8"),
|
||||||
|
meta: {
|
||||||
|
status,
|
||||||
|
headers
|
||||||
|
},
|
||||||
|
revalidate
|
||||||
|
}, "cache");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "PAGE":
|
||||||
|
case "PAGES": {
|
||||||
|
const { html, pageData, status, headers } = data;
|
||||||
|
const isAppPath = typeof pageData === "string";
|
||||||
|
if (isAppPath) {
|
||||||
|
await globalThis.incrementalCache.set(key, {
|
||||||
|
type: "app",
|
||||||
|
html,
|
||||||
|
rsc: pageData,
|
||||||
|
meta: {
|
||||||
|
status,
|
||||||
|
headers
|
||||||
|
},
|
||||||
|
revalidate
|
||||||
|
}, "cache");
|
||||||
|
} else {
|
||||||
|
await globalThis.incrementalCache.set(key, {
|
||||||
|
type: "page",
|
||||||
|
html,
|
||||||
|
json: pageData,
|
||||||
|
revalidate
|
||||||
|
}, "cache");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "APP_PAGE": {
|
||||||
|
const { html, rscData, headers, status, segmentData, postponed } = data;
|
||||||
|
const segmentToWrite = {};
|
||||||
|
if (segmentData) {
|
||||||
|
for (const [segmentPath, segmentContent] of segmentData.entries()) {
|
||||||
|
segmentToWrite[segmentPath] = segmentContent.toString("utf8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await globalThis.incrementalCache.set(key, {
|
||||||
|
type: "app",
|
||||||
|
html,
|
||||||
|
rsc: rscData.toString("utf8"),
|
||||||
|
meta: {
|
||||||
|
status,
|
||||||
|
headers,
|
||||||
|
postponed
|
||||||
|
},
|
||||||
|
revalidate,
|
||||||
|
segmentData: segmentData ? segmentToWrite : void 0
|
||||||
|
}, "cache");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "FETCH":
|
||||||
|
await globalThis.incrementalCache.set(key, data, "fetch");
|
||||||
|
break;
|
||||||
|
case "REDIRECT":
|
||||||
|
await globalThis.incrementalCache.set(key, {
|
||||||
|
type: "redirect",
|
||||||
|
props: data.props,
|
||||||
|
revalidate
|
||||||
|
}, "cache");
|
||||||
|
break;
|
||||||
|
case "IMAGE":
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.updateTagsOnSet(key, data, ctx);
|
||||||
|
debug("Finished setting cache");
|
||||||
|
} catch (e) {
|
||||||
|
error("Failed to set cache", e);
|
||||||
|
} finally {
|
||||||
|
detachedPromise?.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async revalidateTag(tags) {
|
||||||
|
const config = globalThis.openNextConfig.dangerous;
|
||||||
|
if (config?.disableTagCache || config?.disableIncrementalCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const _tags = Array.isArray(tags) ? tags : [tags];
|
||||||
|
if (_tags.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (globalThis.tagCache.mode === "nextMode") {
|
||||||
|
const paths = await globalThis.tagCache.getPathsByTags?.(_tags) ?? [];
|
||||||
|
await writeTags(_tags);
|
||||||
|
if (paths.length > 0) {
|
||||||
|
await globalThis.cdnInvalidationHandler.invalidatePaths(paths.map((path) => ({
|
||||||
|
initialPath: path,
|
||||||
|
rawPath: path,
|
||||||
|
resolvedRoutes: [
|
||||||
|
{
|
||||||
|
route: path,
|
||||||
|
// TODO: ideally here we should check if it's an app router page or route
|
||||||
|
type: "app"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const tag of _tags) {
|
||||||
|
debug("revalidateTag", tag);
|
||||||
|
const paths = await globalThis.tagCache.getByTag(tag);
|
||||||
|
debug("Items", paths);
|
||||||
|
const toInsert = paths.map((path) => ({
|
||||||
|
path,
|
||||||
|
tag
|
||||||
|
}));
|
||||||
|
if (tag.startsWith(SOFT_TAG_PREFIX)) {
|
||||||
|
for (const path of paths) {
|
||||||
|
const _tags2 = await globalThis.tagCache.getByPath(path);
|
||||||
|
const hardTags = _tags2.filter((t) => !t.startsWith(SOFT_TAG_PREFIX));
|
||||||
|
for (const hardTag of hardTags) {
|
||||||
|
const _paths = await globalThis.tagCache.getByTag(hardTag);
|
||||||
|
debug({ hardTag, _paths });
|
||||||
|
toInsert.push(..._paths.map((path2) => ({
|
||||||
|
path: path2,
|
||||||
|
tag: hardTag
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await writeTags(toInsert);
|
||||||
|
const uniquePaths = Array.from(new Set(toInsert.filter((t) => t.tag.startsWith(SOFT_TAG_PREFIX)).map((t) => `/${t.path}`)));
|
||||||
|
if (uniquePaths.length > 0) {
|
||||||
|
await globalThis.cdnInvalidationHandler.invalidatePaths(uniquePaths.map((path) => ({
|
||||||
|
initialPath: path,
|
||||||
|
rawPath: path,
|
||||||
|
resolvedRoutes: [
|
||||||
|
{
|
||||||
|
route: path,
|
||||||
|
// TODO: ideally here we should check if it's an app router page or route
|
||||||
|
type: "app"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error("Failed to revalidate tag", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: We should delete/update tags in this method
|
||||||
|
// This will require an update to the tag cache interface
|
||||||
|
async updateTagsOnSet(key, data, ctx) {
|
||||||
|
if (globalThis.openNextConfig.dangerous?.disableTagCache || globalThis.tagCache.mode === "nextMode" || // Here it means it's a delete
|
||||||
|
!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const derivedTags = data?.kind === "FETCH" ? (
|
||||||
|
//@ts-expect-error - On older versions of next, ctx was a number, but for these cases we use data?.data?.tags
|
||||||
|
ctx?.tags ?? data?.data?.tags ?? []
|
||||||
|
) : data?.kind === "PAGE" ? data.headers?.["x-next-cache-tags"]?.split(",") ?? [] : [];
|
||||||
|
debug("derivedTags", derivedTags);
|
||||||
|
const storedTags = await globalThis.tagCache.getByPath(key);
|
||||||
|
const tagsToWrite = derivedTags.filter((tag) => !storedTags.includes(tag));
|
||||||
|
if (tagsToWrite.length > 0) {
|
||||||
|
await writeTags(tagsToWrite.map((tag) => ({
|
||||||
|
path: key,
|
||||||
|
tag,
|
||||||
|
// In case the tags are not there we just need to create them
|
||||||
|
// but we don't want them to return from `getLastModified` as they are not stale
|
||||||
|
revalidatedAt: 1
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extractRevalidateForSet(ctx) {
|
||||||
|
if (ctx === void 0) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
if (typeof ctx === "number" || ctx === false) {
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
if ("revalidate" in ctx) {
|
||||||
|
return ctx.revalidate;
|
||||||
|
}
|
||||||
|
if ("cacheControl" in ctx) {
|
||||||
|
return ctx.cacheControl?.revalidate;
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
SOFT_TAG_PREFIX
|
||||||
|
});
|
||||||
195
.open-next/.build/composable-cache.cjs
Normal file
195
.open-next/.build/composable-cache.cjs
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
globalThis.disableIncrementalCache = false;globalThis.disableDynamoDBCache = false;globalThis.isNextAfter15 = true;globalThis.openNextDebug = false;globalThis.openNextVersion = "3.9.16";
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __export = (target, all) => {
|
||||||
|
for (var name in all)
|
||||||
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/composable-cache.js
|
||||||
|
var composable_cache_exports = {};
|
||||||
|
__export(composable_cache_exports, {
|
||||||
|
default: () => composable_cache_default
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(composable_cache_exports);
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/logger.js
|
||||||
|
function debug(...args) {
|
||||||
|
if (globalThis.openNextDebug) {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/cache.js
|
||||||
|
function getTagKey(tag) {
|
||||||
|
if (typeof tag === "string") {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
return JSON.stringify({
|
||||||
|
tag: tag.tag,
|
||||||
|
path: tag.path
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function writeTags(tags) {
|
||||||
|
const store = globalThis.__openNextAls.getStore();
|
||||||
|
debug("Writing tags", tags, store);
|
||||||
|
if (!store || globalThis.openNextConfig.dangerous?.disableTagCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tagsToWrite = tags.filter((t) => {
|
||||||
|
const tagKey = getTagKey(t);
|
||||||
|
const shouldWrite = !store.writtenTags.has(tagKey);
|
||||||
|
if (shouldWrite) {
|
||||||
|
store.writtenTags.add(tagKey);
|
||||||
|
}
|
||||||
|
return shouldWrite;
|
||||||
|
});
|
||||||
|
if (tagsToWrite.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await globalThis.tagCache.writeTags(tagsToWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/stream.js
|
||||||
|
var import_web = require("node:stream/web");
|
||||||
|
async function fromReadableStream(stream, base64) {
|
||||||
|
const chunks = [];
|
||||||
|
let totalLength = 0;
|
||||||
|
for await (const chunk of stream) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
totalLength += chunk.length;
|
||||||
|
}
|
||||||
|
if (chunks.length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (chunks.length === 1) {
|
||||||
|
return Buffer.from(chunks[0]).toString(base64 ? "base64" : "utf8");
|
||||||
|
}
|
||||||
|
const buffer = Buffer.alloc(totalLength);
|
||||||
|
let offset = 0;
|
||||||
|
for (const chunk of chunks) {
|
||||||
|
buffer.set(chunk, offset);
|
||||||
|
offset += chunk.length;
|
||||||
|
}
|
||||||
|
return buffer.toString(base64 ? "base64" : "utf8");
|
||||||
|
}
|
||||||
|
function toReadableStream(value, isBase64) {
|
||||||
|
return new import_web.ReadableStream({
|
||||||
|
pull(controller) {
|
||||||
|
controller.enqueue(Buffer.from(value, isBase64 ? "base64" : "utf8"));
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
}, { highWaterMark: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/composable-cache.js
|
||||||
|
var pendingWritePromiseMap = /* @__PURE__ */ new Map();
|
||||||
|
var composable_cache_default = {
|
||||||
|
async get(cacheKey) {
|
||||||
|
try {
|
||||||
|
if (pendingWritePromiseMap.has(cacheKey)) {
|
||||||
|
const stored = pendingWritePromiseMap.get(cacheKey);
|
||||||
|
if (stored) {
|
||||||
|
return stored.then((entry) => ({
|
||||||
|
...entry,
|
||||||
|
value: toReadableStream(entry.value)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = await globalThis.incrementalCache.get(cacheKey, "composable");
|
||||||
|
if (!result?.value?.value) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
debug("composable cache result", result);
|
||||||
|
if (globalThis.tagCache.mode === "nextMode" && result.value.tags.length > 0) {
|
||||||
|
const hasBeenRevalidated = result.shouldBypassTagCache ? false : await globalThis.tagCache.hasBeenRevalidated(result.value.tags, result.lastModified);
|
||||||
|
if (hasBeenRevalidated)
|
||||||
|
return void 0;
|
||||||
|
} else if (globalThis.tagCache.mode === "original" || globalThis.tagCache.mode === void 0) {
|
||||||
|
const hasBeenRevalidated = result.shouldBypassTagCache ? false : await globalThis.tagCache.getLastModified(cacheKey, result.lastModified) === -1;
|
||||||
|
if (hasBeenRevalidated)
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...result.value,
|
||||||
|
value: toReadableStream(result.value.value)
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
debug("Cannot read composable cache entry");
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async set(cacheKey, pendingEntry) {
|
||||||
|
const promiseEntry = pendingEntry.then(async (entry2) => ({
|
||||||
|
...entry2,
|
||||||
|
value: await fromReadableStream(entry2.value)
|
||||||
|
}));
|
||||||
|
pendingWritePromiseMap.set(cacheKey, promiseEntry);
|
||||||
|
const entry = await promiseEntry.finally(() => {
|
||||||
|
pendingWritePromiseMap.delete(cacheKey);
|
||||||
|
});
|
||||||
|
await globalThis.incrementalCache.set(cacheKey, {
|
||||||
|
...entry,
|
||||||
|
value: entry.value
|
||||||
|
}, "composable");
|
||||||
|
if (globalThis.tagCache.mode === "original") {
|
||||||
|
const storedTags = await globalThis.tagCache.getByPath(cacheKey);
|
||||||
|
const tagsToWrite = entry.tags.filter((tag) => !storedTags.includes(tag));
|
||||||
|
if (tagsToWrite.length > 0) {
|
||||||
|
await writeTags(tagsToWrite.map((tag) => ({ tag, path: cacheKey })));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async refreshTags() {
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* The signature has changed in Next.js 16
|
||||||
|
* - Before Next.js 16, the method takes `...tags: string[]`
|
||||||
|
* - From Next.js 16, the method takes `tags: string[]`
|
||||||
|
*/
|
||||||
|
async getExpiration(...tags) {
|
||||||
|
if (globalThis.tagCache.mode === "nextMode") {
|
||||||
|
return globalThis.tagCache.getLastRevalidated(tags.flat());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* This method is only used before Next.js 16
|
||||||
|
*/
|
||||||
|
async expireTags(...tags) {
|
||||||
|
if (globalThis.tagCache.mode === "nextMode") {
|
||||||
|
return writeTags(tags);
|
||||||
|
}
|
||||||
|
const tagCache = globalThis.tagCache;
|
||||||
|
const revalidatedAt = Date.now();
|
||||||
|
const pathsToUpdate = await Promise.all(tags.map(async (tag) => {
|
||||||
|
const paths = await tagCache.getByTag(tag);
|
||||||
|
return paths.map((path) => ({
|
||||||
|
path,
|
||||||
|
tag,
|
||||||
|
revalidatedAt
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
const setToWrite = /* @__PURE__ */ new Set();
|
||||||
|
for (const entry of pathsToUpdate.flat()) {
|
||||||
|
setToWrite.add(entry);
|
||||||
|
}
|
||||||
|
await writeTags(Array.from(setToWrite));
|
||||||
|
},
|
||||||
|
// This one is necessary for older versions of next
|
||||||
|
async receiveExpiredTags(...tags) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
169
.open-next/.build/durable-objects/bucket-cache-purge.js
Normal file
169
.open-next/.build/durable-objects/bucket-cache-purge.js
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
globalThis.openNextDebug = false;globalThis.openNextVersion = "3.9.16";
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/durable-objects/bucket-cache-purge.js
|
||||||
|
import { DurableObject } from "cloudflare:workers";
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/error.js
|
||||||
|
function isOpenNextError(e) {
|
||||||
|
try {
|
||||||
|
return "__openNextInternal" in e;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/logger.js
|
||||||
|
function debug(...args) {
|
||||||
|
if (globalThis.openNextDebug) {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function warn(...args) {
|
||||||
|
console.warn(...args);
|
||||||
|
}
|
||||||
|
var DOWNPLAYED_ERROR_LOGS = [
|
||||||
|
{
|
||||||
|
clientName: "S3Client",
|
||||||
|
commandName: "GetObjectCommand",
|
||||||
|
errorName: "NoSuchKey"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var isDownplayedErrorLog = (errorLog) => DOWNPLAYED_ERROR_LOGS.some((downplayedInput) => downplayedInput.clientName === errorLog?.clientName && downplayedInput.commandName === errorLog?.commandName && (downplayedInput.errorName === errorLog?.error?.name || downplayedInput.errorName === errorLog?.error?.Code));
|
||||||
|
function error(...args) {
|
||||||
|
if (args.some((arg) => isDownplayedErrorLog(arg))) {
|
||||||
|
return debug(...args);
|
||||||
|
}
|
||||||
|
if (args.some((arg) => isOpenNextError(arg))) {
|
||||||
|
const error2 = args.find((arg) => isOpenNextError(arg));
|
||||||
|
if (error2.logLevel < getOpenNextErrorLogLevel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 0) {
|
||||||
|
return console.log(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 1) {
|
||||||
|
return warn(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
return console.error(...args);
|
||||||
|
}
|
||||||
|
console.error(...args);
|
||||||
|
}
|
||||||
|
function getOpenNextErrorLogLevel() {
|
||||||
|
const strLevel = process.env.OPEN_NEXT_ERROR_LOG_LEVEL ?? "1";
|
||||||
|
switch (strLevel.toLowerCase()) {
|
||||||
|
case "debug":
|
||||||
|
case "0":
|
||||||
|
return 0;
|
||||||
|
case "error":
|
||||||
|
case "2":
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/cloudflare-context.js
|
||||||
|
var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/overrides/internal.js
|
||||||
|
var debugCache = (name, ...args) => {
|
||||||
|
if (process.env.NEXT_PRIVATE_DEBUG_CACHE) {
|
||||||
|
console.log(`[${name}] `, ...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
async function internalPurgeCacheByTags(env, tags) {
|
||||||
|
if (!env.CACHE_PURGE_ZONE_ID || !env.CACHE_PURGE_API_TOKEN) {
|
||||||
|
error("No cache zone ID or API token provided. Skipping cache purge.");
|
||||||
|
return "missing-credentials";
|
||||||
|
}
|
||||||
|
let response;
|
||||||
|
try {
|
||||||
|
response = await fetch(`https://api.cloudflare.com/client/v4/zones/${env.CACHE_PURGE_ZONE_ID}/purge_cache`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${env.CACHE_PURGE_API_TOKEN}`,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
tags
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if (response.status === 429) {
|
||||||
|
error("purgeCacheByTags: Rate limit exceeded. Skipping cache purge.");
|
||||||
|
return "rate-limit-exceeded";
|
||||||
|
}
|
||||||
|
const bodyResponse = await response.json();
|
||||||
|
if (!bodyResponse.success) {
|
||||||
|
error("purgeCacheByTags: Cache purge failed. Errors:", bodyResponse.errors.map((error2) => `${error2.code}: ${error2.message}`));
|
||||||
|
return "purge-failed";
|
||||||
|
}
|
||||||
|
debugCache("purgeCacheByTags", "Cache purged successfully for tags:", tags);
|
||||||
|
return "purge-success";
|
||||||
|
} catch (error2) {
|
||||||
|
console.error("Error purging cache by tags:", error2);
|
||||||
|
return "purge-failed";
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
await response?.body?.cancel();
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/durable-objects/bucket-cache-purge.js
|
||||||
|
var DEFAULT_BUFFER_TIME_IN_SECONDS = 5;
|
||||||
|
var MAX_NUMBER_OF_TAGS_PER_PURGE = 100;
|
||||||
|
var BucketCachePurge = class extends DurableObject {
|
||||||
|
bufferTimeInSeconds;
|
||||||
|
constructor(state, env) {
|
||||||
|
super(state, env);
|
||||||
|
this.bufferTimeInSeconds = env.NEXT_CACHE_DO_PURGE_BUFFER_TIME_IN_SECONDS ? parseInt(env.NEXT_CACHE_DO_PURGE_BUFFER_TIME_IN_SECONDS) : DEFAULT_BUFFER_TIME_IN_SECONDS;
|
||||||
|
state.blockConcurrencyWhile(async () => {
|
||||||
|
state.storage.sql.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS cache_purge (
|
||||||
|
tag TEXT NOT NULL
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS tag_index ON cache_purge (tag);
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async purgeCacheByTags(tags) {
|
||||||
|
for (const tag of tags) {
|
||||||
|
this.ctx.storage.sql.exec(`
|
||||||
|
INSERT OR REPLACE INTO cache_purge (tag)
|
||||||
|
VALUES (?)`, [tag]);
|
||||||
|
}
|
||||||
|
const nextAlarm = await this.ctx.storage.getAlarm();
|
||||||
|
if (!nextAlarm) {
|
||||||
|
this.ctx.storage.setAlarm(Date.now() + this.bufferTimeInSeconds * 1e3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async alarm() {
|
||||||
|
let tags = this.ctx.storage.sql.exec(`
|
||||||
|
SELECT * FROM cache_purge LIMIT ${MAX_NUMBER_OF_TAGS_PER_PURGE}
|
||||||
|
`).toArray();
|
||||||
|
do {
|
||||||
|
if (tags.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const result = await internalPurgeCacheByTags(this.env, tags.map((row) => row.tag));
|
||||||
|
if (result === "rate-limit-exceeded") {
|
||||||
|
throw new Error("Rate limit exceeded");
|
||||||
|
}
|
||||||
|
this.ctx.storage.sql.exec(`
|
||||||
|
DELETE FROM cache_purge
|
||||||
|
WHERE tag IN (${tags.map(() => "?").join(",")})
|
||||||
|
`, tags.map((row) => row.tag));
|
||||||
|
if (tags.length < MAX_NUMBER_OF_TAGS_PER_PURGE) {
|
||||||
|
tags = [];
|
||||||
|
} else {
|
||||||
|
tags = this.ctx.storage.sql.exec(`
|
||||||
|
SELECT * FROM cache_purge LIMIT ${MAX_NUMBER_OF_TAGS_PER_PURGE}
|
||||||
|
`).toArray();
|
||||||
|
}
|
||||||
|
} while (tags.length >= 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
BucketCachePurge
|
||||||
|
};
|
||||||
283
.open-next/.build/durable-objects/queue.js
Normal file
283
.open-next/.build/durable-objects/queue.js
Normal file
|
|
@ -0,0 +1,283 @@
|
||||||
|
globalThis.openNextDebug = false;globalThis.openNextVersion = "3.9.16";
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/error.js
|
||||||
|
var IgnorableError = class extends Error {
|
||||||
|
__openNextInternal = true;
|
||||||
|
canIgnore = true;
|
||||||
|
logLevel = 0;
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "IgnorableError";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var RecoverableError = class extends Error {
|
||||||
|
__openNextInternal = true;
|
||||||
|
canIgnore = true;
|
||||||
|
logLevel = 1;
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "RecoverableError";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var FatalError = class extends Error {
|
||||||
|
__openNextInternal = true;
|
||||||
|
canIgnore = false;
|
||||||
|
logLevel = 2;
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "FatalError";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function isOpenNextError(e) {
|
||||||
|
try {
|
||||||
|
return "__openNextInternal" in e;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/logger.js
|
||||||
|
function debug(...args) {
|
||||||
|
if (globalThis.openNextDebug) {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function warn(...args) {
|
||||||
|
console.warn(...args);
|
||||||
|
}
|
||||||
|
var DOWNPLAYED_ERROR_LOGS = [
|
||||||
|
{
|
||||||
|
clientName: "S3Client",
|
||||||
|
commandName: "GetObjectCommand",
|
||||||
|
errorName: "NoSuchKey"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var isDownplayedErrorLog = (errorLog) => DOWNPLAYED_ERROR_LOGS.some((downplayedInput) => downplayedInput.clientName === errorLog?.clientName && downplayedInput.commandName === errorLog?.commandName && (downplayedInput.errorName === errorLog?.error?.name || downplayedInput.errorName === errorLog?.error?.Code));
|
||||||
|
function error(...args) {
|
||||||
|
if (args.some((arg) => isDownplayedErrorLog(arg))) {
|
||||||
|
return debug(...args);
|
||||||
|
}
|
||||||
|
if (args.some((arg) => isOpenNextError(arg))) {
|
||||||
|
const error2 = args.find((arg) => isOpenNextError(arg));
|
||||||
|
if (error2.logLevel < getOpenNextErrorLogLevel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 0) {
|
||||||
|
return console.log(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 1) {
|
||||||
|
return warn(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
return console.error(...args);
|
||||||
|
}
|
||||||
|
console.error(...args);
|
||||||
|
}
|
||||||
|
function getOpenNextErrorLogLevel() {
|
||||||
|
const strLevel = process.env.OPEN_NEXT_ERROR_LOG_LEVEL ?? "1";
|
||||||
|
switch (strLevel.toLowerCase()) {
|
||||||
|
case "debug":
|
||||||
|
case "0":
|
||||||
|
return 0;
|
||||||
|
case "error":
|
||||||
|
case "2":
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/durable-objects/queue.js
|
||||||
|
import { DurableObject } from "cloudflare:workers";
|
||||||
|
var DEFAULT_MAX_REVALIDATION = 5;
|
||||||
|
var DEFAULT_REVALIDATION_TIMEOUT_MS = 1e4;
|
||||||
|
var DEFAULT_RETRY_INTERVAL_MS = 2e3;
|
||||||
|
var DEFAULT_MAX_RETRIES = 6;
|
||||||
|
var DOQueueHandler = class extends DurableObject {
|
||||||
|
// Ongoing revalidations are deduped by the deduplication id
|
||||||
|
// Since this is running in waitUntil, we expect the durable object state to persist this during the duration of the revalidation
|
||||||
|
// TODO: handle incremental cache with only eventual consistency (i.e. KV or R2/D1 with the optional cache layer on top)
|
||||||
|
ongoingRevalidations = /* @__PURE__ */ new Map();
|
||||||
|
sql;
|
||||||
|
routeInFailedState = /* @__PURE__ */ new Map();
|
||||||
|
service;
|
||||||
|
// Configurable params
|
||||||
|
maxRevalidations;
|
||||||
|
revalidationTimeout;
|
||||||
|
revalidationRetryInterval;
|
||||||
|
maxRetries;
|
||||||
|
disableSQLite;
|
||||||
|
constructor(ctx, env) {
|
||||||
|
super(ctx, env);
|
||||||
|
this.service = env.WORKER_SELF_REFERENCE;
|
||||||
|
if (!this.service)
|
||||||
|
throw new IgnorableError("No service binding for cache revalidation worker");
|
||||||
|
this.sql = ctx.storage.sql;
|
||||||
|
this.maxRevalidations = env.NEXT_CACHE_DO_QUEUE_MAX_REVALIDATION ? parseInt(env.NEXT_CACHE_DO_QUEUE_MAX_REVALIDATION) : DEFAULT_MAX_REVALIDATION;
|
||||||
|
this.revalidationTimeout = env.NEXT_CACHE_DO_QUEUE_REVALIDATION_TIMEOUT_MS ? parseInt(env.NEXT_CACHE_DO_QUEUE_REVALIDATION_TIMEOUT_MS) : DEFAULT_REVALIDATION_TIMEOUT_MS;
|
||||||
|
this.revalidationRetryInterval = env.NEXT_CACHE_DO_QUEUE_RETRY_INTERVAL_MS ? parseInt(env.NEXT_CACHE_DO_QUEUE_RETRY_INTERVAL_MS) : DEFAULT_RETRY_INTERVAL_MS;
|
||||||
|
this.maxRetries = env.NEXT_CACHE_DO_QUEUE_MAX_RETRIES ? parseInt(env.NEXT_CACHE_DO_QUEUE_MAX_RETRIES) : DEFAULT_MAX_RETRIES;
|
||||||
|
this.disableSQLite = env.NEXT_CACHE_DO_QUEUE_DISABLE_SQLITE === "true";
|
||||||
|
ctx.blockConcurrencyWhile(async () => {
|
||||||
|
debug(`Restoring the state of the durable object`);
|
||||||
|
await this.initState();
|
||||||
|
});
|
||||||
|
debug(`Durable object initialized`);
|
||||||
|
}
|
||||||
|
async revalidate(msg) {
|
||||||
|
if (this.ongoingRevalidations.size > 2 * this.maxRevalidations) {
|
||||||
|
warn(`Your durable object has 2 times the maximum number of revalidations (${this.maxRevalidations}) in progress. If this happens often, you should consider increasing the NEXT_CACHE_DO_QUEUE_MAX_REVALIDATION or the number of durable objects with the MAX_REVALIDATE_CONCURRENCY env var.`);
|
||||||
|
}
|
||||||
|
if (this.ongoingRevalidations.has(msg.MessageDeduplicationId))
|
||||||
|
return;
|
||||||
|
if (this.routeInFailedState.has(msg.MessageDeduplicationId))
|
||||||
|
return;
|
||||||
|
if (this.checkSyncTable(msg))
|
||||||
|
return;
|
||||||
|
if (this.ongoingRevalidations.size >= this.maxRevalidations) {
|
||||||
|
debug(`The maximum number of revalidations (${this.maxRevalidations}) is reached. Blocking until one of the revalidations finishes.`);
|
||||||
|
while (this.ongoingRevalidations.size >= this.maxRevalidations) {
|
||||||
|
const ongoingRevalidations = this.ongoingRevalidations.values();
|
||||||
|
debug(`Waiting for one of the revalidations to finish`);
|
||||||
|
await Promise.race(ongoingRevalidations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const revalidationPromise = this.executeRevalidation(msg);
|
||||||
|
this.ongoingRevalidations.set(msg.MessageDeduplicationId, revalidationPromise);
|
||||||
|
this.ctx.waitUntil(revalidationPromise);
|
||||||
|
}
|
||||||
|
async executeRevalidation(msg) {
|
||||||
|
let response;
|
||||||
|
try {
|
||||||
|
debug(`Revalidating ${msg.MessageBody.host}${msg.MessageBody.url}`);
|
||||||
|
const { MessageBody: { host, url } } = msg;
|
||||||
|
const protocol = host.includes("localhost") ? "http" : "https";
|
||||||
|
response = await this.service.fetch(`${protocol}://${host}${url}`, {
|
||||||
|
method: "HEAD",
|
||||||
|
headers: {
|
||||||
|
// This is defined during build
|
||||||
|
"x-prerender-revalidate": "a93160fac8c4e7d386ed2d8b07c7b4c0",
|
||||||
|
"x-isr": "1"
|
||||||
|
},
|
||||||
|
// This one is kind of problematic, it will always show the wall time of the revalidation to `this.revalidationTimeout`
|
||||||
|
signal: AbortSignal.timeout(this.revalidationTimeout)
|
||||||
|
});
|
||||||
|
if (response.status === 200 && response.headers.get("x-nextjs-cache") !== "REVALIDATED") {
|
||||||
|
this.routeInFailedState.delete(msg.MessageDeduplicationId);
|
||||||
|
throw new FatalError(`The revalidation for ${host}${url} cannot be done. This error should never happen.`);
|
||||||
|
} else if (response.status === 404) {
|
||||||
|
this.routeInFailedState.delete(msg.MessageDeduplicationId);
|
||||||
|
throw new IgnorableError(`The revalidation for ${host}${url} cannot be done because the page is not found. It's either expected or an error in user code itself`);
|
||||||
|
} else if (response.status === 500) {
|
||||||
|
await this.addToFailedState(msg);
|
||||||
|
throw new IgnorableError(`Something went wrong while revalidating ${host}${url}`);
|
||||||
|
} else if (response.status !== 200) {
|
||||||
|
await this.addToFailedState(msg);
|
||||||
|
throw new RecoverableError(`An unknown error occurred while revalidating ${host}${url}`);
|
||||||
|
}
|
||||||
|
if (!this.disableSQLite) {
|
||||||
|
this.sql.exec(
|
||||||
|
"INSERT OR REPLACE INTO sync (id, lastSuccess, buildId) VALUES (?, unixepoch(), ?)",
|
||||||
|
// We cannot use the deduplication id because it's not unique per route - every time a route is revalidated, the deduplication id is different.
|
||||||
|
`${host}${url}`,
|
||||||
|
"15aOepE5x4uUwOLZRAN9M"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.routeInFailedState.delete(msg.MessageDeduplicationId);
|
||||||
|
} catch (e) {
|
||||||
|
if (!isOpenNextError(e)) {
|
||||||
|
await this.addToFailedState(msg);
|
||||||
|
}
|
||||||
|
error(e);
|
||||||
|
} finally {
|
||||||
|
this.ongoingRevalidations.delete(msg.MessageDeduplicationId);
|
||||||
|
try {
|
||||||
|
await response?.body?.cancel();
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async alarm() {
|
||||||
|
const currentDateTime = Date.now();
|
||||||
|
const nextEventToRetry = Array.from(this.routeInFailedState.values()).filter(({ nextAlarmMs }) => nextAlarmMs > currentDateTime).sort(({ nextAlarmMs: a }, { nextAlarmMs: b }) => a - b)[0];
|
||||||
|
const expiredEvents = Array.from(this.routeInFailedState.values()).filter(({ nextAlarmMs }) => nextAlarmMs <= currentDateTime);
|
||||||
|
const allEventsToRetry = nextEventToRetry ? [nextEventToRetry, ...expiredEvents] : expiredEvents;
|
||||||
|
for (const event of allEventsToRetry) {
|
||||||
|
debug(`Retrying revalidation for ${event.msg.MessageBody.host}${event.msg.MessageBody.url}`);
|
||||||
|
await this.executeRevalidation(event.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async addToFailedState(msg) {
|
||||||
|
debug(`Adding ${msg.MessageBody.host}${msg.MessageBody.url} to the failed state`);
|
||||||
|
const existingFailedState = this.routeInFailedState.get(msg.MessageDeduplicationId);
|
||||||
|
let updatedFailedState;
|
||||||
|
if (existingFailedState) {
|
||||||
|
if (existingFailedState.retryCount >= this.maxRetries) {
|
||||||
|
error(`The revalidation for ${msg.MessageBody.host}${msg.MessageBody.url} has failed after ${this.maxRetries} retries. It will not be tried again, but subsequent ISR requests will retry.`);
|
||||||
|
this.routeInFailedState.delete(msg.MessageDeduplicationId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nextAlarmMs = Date.now() + Math.pow(2, existingFailedState.retryCount + 1) * this.revalidationRetryInterval;
|
||||||
|
updatedFailedState = {
|
||||||
|
...existingFailedState,
|
||||||
|
retryCount: existingFailedState.retryCount + 1,
|
||||||
|
nextAlarmMs
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
updatedFailedState = {
|
||||||
|
msg,
|
||||||
|
retryCount: 1,
|
||||||
|
nextAlarmMs: Date.now() + 2e3
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.routeInFailedState.set(msg.MessageDeduplicationId, updatedFailedState);
|
||||||
|
if (!this.disableSQLite) {
|
||||||
|
this.sql.exec("INSERT OR REPLACE INTO failed_state (id, data, buildId) VALUES (?, ?, ?)", msg.MessageDeduplicationId, JSON.stringify(updatedFailedState), "15aOepE5x4uUwOLZRAN9M");
|
||||||
|
}
|
||||||
|
await this.addAlarm();
|
||||||
|
}
|
||||||
|
async addAlarm() {
|
||||||
|
const existingAlarm = await this.ctx.storage.getAlarm({ allowConcurrency: false });
|
||||||
|
if (existingAlarm)
|
||||||
|
return;
|
||||||
|
if (this.routeInFailedState.size === 0)
|
||||||
|
return;
|
||||||
|
let nextAlarmToSetup = Math.min(...Array.from(this.routeInFailedState.values()).map(({ nextAlarmMs }) => nextAlarmMs));
|
||||||
|
if (nextAlarmToSetup < Date.now()) {
|
||||||
|
nextAlarmToSetup = Date.now() + this.revalidationRetryInterval;
|
||||||
|
}
|
||||||
|
await this.ctx.storage.setAlarm(nextAlarmToSetup);
|
||||||
|
}
|
||||||
|
// This function is used to restore the state of the durable object
|
||||||
|
// We don't restore the ongoing revalidations because we cannot know in which state they are
|
||||||
|
// We only restore the failed state and the alarm
|
||||||
|
async initState() {
|
||||||
|
if (this.disableSQLite)
|
||||||
|
return;
|
||||||
|
this.sql.exec("CREATE TABLE IF NOT EXISTS failed_state (id TEXT PRIMARY KEY, data TEXT, buildId TEXT)");
|
||||||
|
this.sql.exec("CREATE TABLE IF NOT EXISTS sync (id TEXT PRIMARY KEY, lastSuccess INTEGER, buildId TEXT)");
|
||||||
|
this.sql.exec("DELETE FROM failed_state WHERE buildId != ?", "15aOepE5x4uUwOLZRAN9M");
|
||||||
|
this.sql.exec("DELETE FROM sync WHERE buildId != ?", "15aOepE5x4uUwOLZRAN9M");
|
||||||
|
const failedStateCursor = this.sql.exec("SELECT * FROM failed_state");
|
||||||
|
for (const row of failedStateCursor) {
|
||||||
|
this.routeInFailedState.set(row.id, JSON.parse(row.data));
|
||||||
|
}
|
||||||
|
await this.addAlarm();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* @returns `true` if the route has been revalidated since the lastModified from the message, `false` otherwise
|
||||||
|
*/
|
||||||
|
checkSyncTable(msg) {
|
||||||
|
try {
|
||||||
|
if (this.disableSQLite)
|
||||||
|
return false;
|
||||||
|
return this.sql.exec("SELECT 1 FROM sync WHERE id = ? AND lastSuccess > ? LIMIT 1", `${msg.MessageBody.host}${msg.MessageBody.url}`, Math.round(msg.MessageBody.lastModified / 1e3)).toArray().length > 0;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
DOQueueHandler
|
||||||
|
};
|
||||||
55
.open-next/.build/durable-objects/sharded-tag-cache.js
Normal file
55
.open-next/.build/durable-objects/sharded-tag-cache.js
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
globalThis.openNextDebug = false;globalThis.openNextVersion = "3.9.16";
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/durable-objects/sharded-tag-cache.js
|
||||||
|
import { DurableObject } from "cloudflare:workers";
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/cloudflare-context.js
|
||||||
|
var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/overrides/internal.js
|
||||||
|
var debugCache = (name, ...args) => {
|
||||||
|
if (process.env.NEXT_PRIVATE_DEBUG_CACHE) {
|
||||||
|
console.log(`[${name}] `, ...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/durable-objects/sharded-tag-cache.js
|
||||||
|
var DOShardedTagCache = class extends DurableObject {
|
||||||
|
sql;
|
||||||
|
constructor(state, env) {
|
||||||
|
super(state, env);
|
||||||
|
this.sql = state.storage.sql;
|
||||||
|
state.blockConcurrencyWhile(async () => {
|
||||||
|
this.sql.exec(`CREATE TABLE IF NOT EXISTS revalidations (tag TEXT PRIMARY KEY, revalidatedAt INTEGER)`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async getLastRevalidated(tags) {
|
||||||
|
try {
|
||||||
|
const result = this.sql.exec(`SELECT MAX(revalidatedAt) AS time FROM revalidations WHERE tag IN (${tags.map(() => "?").join(", ")})`, ...tags).toArray();
|
||||||
|
const timeMs = result[0]?.time ?? 0;
|
||||||
|
debugCache("DOShardedTagCache", `getLastRevalidated tags=${tags} -> time=${timeMs}`);
|
||||||
|
return timeMs;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async hasBeenRevalidated(tags, lastModified) {
|
||||||
|
const revalidated = this.sql.exec(`SELECT 1 FROM revalidations WHERE tag IN (${tags.map(() => "?").join(", ")}) AND revalidatedAt > ? LIMIT 1`, ...tags, lastModified ?? Date.now()).toArray().length > 0;
|
||||||
|
debugCache("DOShardedTagCache", `hasBeenRevalidated tags=${tags} -> revalidated=${revalidated}`);
|
||||||
|
return revalidated;
|
||||||
|
}
|
||||||
|
async writeTags(tags, lastModified) {
|
||||||
|
debugCache("DOShardedTagCache", `writeTags tags=${tags} time=${lastModified}`);
|
||||||
|
tags.forEach((tag) => {
|
||||||
|
this.sql.exec(`INSERT OR REPLACE INTO revalidations (tag, revalidatedAt) VALUES (?, ?)`, tag, lastModified);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async getRevalidationTimes(tags) {
|
||||||
|
const result = this.sql.exec(`SELECT tag, revalidatedAt FROM revalidations WHERE tag IN (${tags.map(() => "?").join(", ")})`, ...tags).toArray();
|
||||||
|
return Object.fromEntries(result.map((row) => [row.tag, row.revalidatedAt]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
DOShardedTagCache
|
||||||
|
};
|
||||||
215
.open-next/.build/open-next.config.edge.mjs
Normal file
215
.open-next/.build/open-next.config.edge.mjs
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/cloudflare-context.js
|
||||||
|
var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
|
||||||
|
function getCloudflareContext(options = { async: false }) {
|
||||||
|
return options.async ? getCloudflareContextAsync() : getCloudflareContextSync();
|
||||||
|
}
|
||||||
|
function getCloudflareContextFromGlobalScope() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global[cloudflareContextSymbol];
|
||||||
|
}
|
||||||
|
function inSSG() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global.__NEXT_DATA__?.nextExport === true;
|
||||||
|
}
|
||||||
|
function getCloudflareContextSync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
if (inSSG()) {
|
||||||
|
throw new Error(`
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called in sync mode in either a static route or at the top level of a non-static one, both cases are not allowed but can be solved by either:
|
||||||
|
- make sure that the call is not at the top level and that the route is not static
|
||||||
|
- call \`getCloudflareContext({async: true})\` to use the \`async\` mode
|
||||||
|
- avoid calling \`getCloudflareContext\` in the route
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
async function getCloudflareContextAsync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
const inNodejsRuntime = process.env.NEXT_RUNTIME === "nodejs";
|
||||||
|
if (inNodejsRuntime || inSSG()) {
|
||||||
|
const cloudflareContext2 = await getCloudflareContextFromWrangler();
|
||||||
|
addCloudflareContextToNodejsGlobal(cloudflareContext2);
|
||||||
|
return cloudflareContext2;
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
function addCloudflareContextToNodejsGlobal(cloudflareContext) {
|
||||||
|
const global = globalThis;
|
||||||
|
global[cloudflareContextSymbol] = cloudflareContext;
|
||||||
|
}
|
||||||
|
async function getCloudflareContextFromWrangler(options) {
|
||||||
|
const { getPlatformProxy } = await import(
|
||||||
|
/* webpackIgnore: true */
|
||||||
|
`${"__wrangler".replaceAll("_", "")}`
|
||||||
|
);
|
||||||
|
const environment = options?.environment ?? process.env.NEXT_DEV_WRANGLER_ENV;
|
||||||
|
const { env, cf, ctx } = await getPlatformProxy({
|
||||||
|
...options,
|
||||||
|
// The `env` passed to the fetch handler does not contain variables from `.env*` files.
|
||||||
|
// because we invoke wrangler with `CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV`=`"false"`.
|
||||||
|
// Initializing `envFiles` with an empty list is the equivalent for this API call.
|
||||||
|
envFiles: [],
|
||||||
|
environment
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
env,
|
||||||
|
cf,
|
||||||
|
ctx
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var initOpenNextCloudflareForDevErrorMsg = `
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called without having called \`initOpenNextCloudflareForDev\` from the Next.js config file.
|
||||||
|
You should update your Next.js config file as shown below:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
// next.config.mjs
|
||||||
|
|
||||||
|
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
|
||||||
|
|
||||||
|
initOpenNextCloudflareForDev();
|
||||||
|
|
||||||
|
const nextConfig = { ... };
|
||||||
|
export default nextConfig;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/overrides/asset-resolver/index.js
|
||||||
|
var resolver = {
|
||||||
|
name: "cloudflare-asset-resolver",
|
||||||
|
async maybeGetAssetResult(event) {
|
||||||
|
const { ASSETS } = getCloudflareContext().env;
|
||||||
|
if (!ASSETS || !isUserWorkerFirst(globalThis.__ASSETS_RUN_WORKER_FIRST__, event.rawPath)) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const { method, headers } = event;
|
||||||
|
if (method !== "GET" && method != "HEAD") {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const url = new URL(event.rawPath, "https://assets.local");
|
||||||
|
const response = await ASSETS.fetch(url, {
|
||||||
|
headers,
|
||||||
|
method
|
||||||
|
});
|
||||||
|
if (response.status === 404) {
|
||||||
|
await response.body?.cancel();
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: "core",
|
||||||
|
statusCode: response.status,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
body: getResponseBody(method, response),
|
||||||
|
isBase64Encoded: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getResponseBody(method, response) {
|
||||||
|
if (method === "HEAD") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return response.body || new ReadableStream();
|
||||||
|
}
|
||||||
|
function isUserWorkerFirst(runWorkerFirst, pathname) {
|
||||||
|
if (!Array.isArray(runWorkerFirst)) {
|
||||||
|
return runWorkerFirst ?? false;
|
||||||
|
}
|
||||||
|
let hasPositiveMatch = false;
|
||||||
|
for (let rule of runWorkerFirst) {
|
||||||
|
let isPositiveRule = true;
|
||||||
|
if (rule.startsWith("!")) {
|
||||||
|
rule = rule.slice(1);
|
||||||
|
isPositiveRule = false;
|
||||||
|
} else if (hasPositiveMatch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const match = new RegExp(`^${rule.replace(/([[\]().*+?^$|{}\\])/g, "\\$1").replace("\\*", ".*")}$`).test(pathname);
|
||||||
|
if (match) {
|
||||||
|
if (isPositiveRule) {
|
||||||
|
hasPositiveMatch = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasPositiveMatch;
|
||||||
|
}
|
||||||
|
var asset_resolver_default = resolver;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/config.js
|
||||||
|
function defineCloudflareConfig(config = {}) {
|
||||||
|
const { incrementalCache, tagCache, queue, cachePurge, enableCacheInterception = false, routePreloadingBehavior = "none" } = config;
|
||||||
|
return {
|
||||||
|
default: {
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-node",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue),
|
||||||
|
cdnInvalidation: resolveCdnInvalidation(cachePurge)
|
||||||
|
},
|
||||||
|
routePreloadingBehavior
|
||||||
|
},
|
||||||
|
// node:crypto is used to compute cache keys
|
||||||
|
edgeExternals: ["node:crypto"],
|
||||||
|
cloudflare: {
|
||||||
|
useWorkerdCondition: true
|
||||||
|
},
|
||||||
|
dangerous: {
|
||||||
|
enableCacheInterception
|
||||||
|
},
|
||||||
|
middleware: {
|
||||||
|
external: true,
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-edge",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue)
|
||||||
|
},
|
||||||
|
assetResolver: () => asset_resolver_default
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function resolveIncrementalCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveTagCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveQueue(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveCdnInvalidation(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open-next.config.ts
|
||||||
|
var open_next_config_default = defineCloudflareConfig({});
|
||||||
|
export {
|
||||||
|
open_next_config_default as default
|
||||||
|
};
|
||||||
217
.open-next/.build/open-next.config.mjs
Normal file
217
.open-next/.build/open-next.config.mjs
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
import { createRequire as topLevelCreateRequire } from 'module';const require = topLevelCreateRequire(import.meta.url);import bannerUrl from 'url';const __dirname = bannerUrl.fileURLToPath(new URL('.', import.meta.url));
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/cloudflare-context.js
|
||||||
|
var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
|
||||||
|
function getCloudflareContext(options = { async: false }) {
|
||||||
|
return options.async ? getCloudflareContextAsync() : getCloudflareContextSync();
|
||||||
|
}
|
||||||
|
function getCloudflareContextFromGlobalScope() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global[cloudflareContextSymbol];
|
||||||
|
}
|
||||||
|
function inSSG() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global.__NEXT_DATA__?.nextExport === true;
|
||||||
|
}
|
||||||
|
function getCloudflareContextSync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
if (inSSG()) {
|
||||||
|
throw new Error(`
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called in sync mode in either a static route or at the top level of a non-static one, both cases are not allowed but can be solved by either:
|
||||||
|
- make sure that the call is not at the top level and that the route is not static
|
||||||
|
- call \`getCloudflareContext({async: true})\` to use the \`async\` mode
|
||||||
|
- avoid calling \`getCloudflareContext\` in the route
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
async function getCloudflareContextAsync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
const inNodejsRuntime = process.env.NEXT_RUNTIME === "nodejs";
|
||||||
|
if (inNodejsRuntime || inSSG()) {
|
||||||
|
const cloudflareContext2 = await getCloudflareContextFromWrangler();
|
||||||
|
addCloudflareContextToNodejsGlobal(cloudflareContext2);
|
||||||
|
return cloudflareContext2;
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
function addCloudflareContextToNodejsGlobal(cloudflareContext) {
|
||||||
|
const global = globalThis;
|
||||||
|
global[cloudflareContextSymbol] = cloudflareContext;
|
||||||
|
}
|
||||||
|
async function getCloudflareContextFromWrangler(options) {
|
||||||
|
const { getPlatformProxy } = await import(
|
||||||
|
/* webpackIgnore: true */
|
||||||
|
`${"__wrangler".replaceAll("_", "")}`
|
||||||
|
);
|
||||||
|
const environment = options?.environment ?? process.env.NEXT_DEV_WRANGLER_ENV;
|
||||||
|
const { env, cf, ctx } = await getPlatformProxy({
|
||||||
|
...options,
|
||||||
|
// The `env` passed to the fetch handler does not contain variables from `.env*` files.
|
||||||
|
// because we invoke wrangler with `CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV`=`"false"`.
|
||||||
|
// Initializing `envFiles` with an empty list is the equivalent for this API call.
|
||||||
|
envFiles: [],
|
||||||
|
environment
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
env,
|
||||||
|
cf,
|
||||||
|
ctx
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var initOpenNextCloudflareForDevErrorMsg = `
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called without having called \`initOpenNextCloudflareForDev\` from the Next.js config file.
|
||||||
|
You should update your Next.js config file as shown below:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
// next.config.mjs
|
||||||
|
|
||||||
|
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
|
||||||
|
|
||||||
|
initOpenNextCloudflareForDev();
|
||||||
|
|
||||||
|
const nextConfig = { ... };
|
||||||
|
export default nextConfig;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/overrides/asset-resolver/index.js
|
||||||
|
var resolver = {
|
||||||
|
name: "cloudflare-asset-resolver",
|
||||||
|
async maybeGetAssetResult(event) {
|
||||||
|
const { ASSETS } = getCloudflareContext().env;
|
||||||
|
if (!ASSETS || !isUserWorkerFirst(globalThis.__ASSETS_RUN_WORKER_FIRST__, event.rawPath)) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const { method, headers } = event;
|
||||||
|
if (method !== "GET" && method != "HEAD") {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const url = new URL(event.rawPath, "https://assets.local");
|
||||||
|
const response = await ASSETS.fetch(url, {
|
||||||
|
headers,
|
||||||
|
method
|
||||||
|
});
|
||||||
|
if (response.status === 404) {
|
||||||
|
await response.body?.cancel();
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: "core",
|
||||||
|
statusCode: response.status,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
body: getResponseBody(method, response),
|
||||||
|
isBase64Encoded: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getResponseBody(method, response) {
|
||||||
|
if (method === "HEAD") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return response.body || new ReadableStream();
|
||||||
|
}
|
||||||
|
function isUserWorkerFirst(runWorkerFirst, pathname) {
|
||||||
|
if (!Array.isArray(runWorkerFirst)) {
|
||||||
|
return runWorkerFirst ?? false;
|
||||||
|
}
|
||||||
|
let hasPositiveMatch = false;
|
||||||
|
for (let rule of runWorkerFirst) {
|
||||||
|
let isPositiveRule = true;
|
||||||
|
if (rule.startsWith("!")) {
|
||||||
|
rule = rule.slice(1);
|
||||||
|
isPositiveRule = false;
|
||||||
|
} else if (hasPositiveMatch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const match = new RegExp(`^${rule.replace(/([[\]().*+?^$|{}\\])/g, "\\$1").replace("\\*", ".*")}$`).test(pathname);
|
||||||
|
if (match) {
|
||||||
|
if (isPositiveRule) {
|
||||||
|
hasPositiveMatch = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasPositiveMatch;
|
||||||
|
}
|
||||||
|
var asset_resolver_default = resolver;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/config.js
|
||||||
|
function defineCloudflareConfig(config = {}) {
|
||||||
|
const { incrementalCache, tagCache, queue, cachePurge, enableCacheInterception = false, routePreloadingBehavior = "none" } = config;
|
||||||
|
return {
|
||||||
|
default: {
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-node",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue),
|
||||||
|
cdnInvalidation: resolveCdnInvalidation(cachePurge)
|
||||||
|
},
|
||||||
|
routePreloadingBehavior
|
||||||
|
},
|
||||||
|
// node:crypto is used to compute cache keys
|
||||||
|
edgeExternals: ["node:crypto"],
|
||||||
|
cloudflare: {
|
||||||
|
useWorkerdCondition: true
|
||||||
|
},
|
||||||
|
dangerous: {
|
||||||
|
enableCacheInterception
|
||||||
|
},
|
||||||
|
middleware: {
|
||||||
|
external: true,
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-edge",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue)
|
||||||
|
},
|
||||||
|
assetResolver: () => asset_resolver_default
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function resolveIncrementalCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveTagCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveQueue(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveCdnInvalidation(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open-next.config.ts
|
||||||
|
var open_next_config_default = defineCloudflareConfig({});
|
||||||
|
export {
|
||||||
|
open_next_config_default as default
|
||||||
|
};
|
||||||
1
.open-next/assets/BUILD_ID
Normal file
1
.open-next/assets/BUILD_ID
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
15aOepE5x4uUwOLZRAN9M
|
||||||
3
.open-next/assets/_headers
Normal file
3
.open-next/assets/_headers
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/_next/static/*
|
||||||
|
Cache-Control: public,max-age=31536000,immutable
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
self.__BUILD_MANIFEST=function(e,r,t){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:5,errorRate:1e-4,numBits:96,numHashes:14,bitArray:[1,0,1,e,e,e,e,0,e,e,e,e,e,r,r,r,r,e,e,e,e,e,e,e,r,r,e,r,e,r,r,r,e,r,r,r,e,r,e,e,e,r,r,r,r,r,r,e,r,r,r,e,r,e,r,r,e,e,e,e,e,e,r,e,e,r,r,r,e,e,r,e,e,r,e,e,r,r,e,e,r,e,e,e,e,r,r,e,r,r,e,r,e,e,e,e]},__routerFilterDynamic:{numItems:r,errorRate:1e-4,numBits:r,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-cb2a52f75f2162e2.js"],sortedPages:["/_app","/_error"]}}(1,0,1e-4),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[492],{4585:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"styles",{enumerable:!0,get:function(){return l}});let l={error:{fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},desc:{display:"inline-block"},h1:{display:"inline-block",margin:"0 20px 0 0",padding:"0 23px 0 0",fontSize:24,fontWeight:500,verticalAlign:"top",lineHeight:"49px"},h2:{fontSize:14,fontWeight:400,lineHeight:"49px",margin:0}};("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},8886:(e,t,l)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"HTTPAccessErrorFallback",{enumerable:!0,get:function(){return o}});let r=l(5155),n=l(4585);function o(e){let{status:t,message:l}=e;return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("title",{children:t+": "+l}),(0,r.jsx)("div",{style:n.styles.error,children:(0,r.jsxs)("div",{children:[(0,r.jsx)("style",{dangerouslySetInnerHTML:{__html:"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}),(0,r.jsx)("h1",{className:"next-error-h1",style:n.styles.h1,children:t}),(0,r.jsx)("div",{style:n.styles.desc,children:(0,r.jsx)("h2",{style:n.styles.h2,children:l})})]})})]})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},9520:(e,t,l)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return o}});let r=l(5155),n=l(8886),o=function(){return(0,r.jsx)("html",{children:(0,r.jsx)("body",{children:(0,r.jsx)(n.HTTPAccessErrorFallback,{status:404,message:"This page could not be found."})})})};("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},9859:(e,t,l)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_not-found/page",function(){return l(9520)}])}},e=>{e.O(0,[441,255,358],()=>e(e.s=9859)),_N_E=e.O()}]);
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[974],{4659:(e,r,i)=>{Promise.resolve().then(i.t.bind(i,2619,23)),Promise.resolve().then(i.bind(i,4897))},4897:(e,r,i)=>{"use strict";i.r(r),i.d(r,{Button:()=>u,buttonVariants:()=>o});var t=i(5155),n=i(120),a=i(3101),d=i(2821),s=i(5889);let o=(0,a.F)("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",{variants:{variant:{default:"bg-primary text-primary-foreground [a]:hover:bg-primary/80",outline:"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",ghost:"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",destructive:"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",xs:"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",sm:"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",lg:"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",icon:"size-8","icon-xs":"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3","icon-sm":"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg","icon-lg":"size-9"}},defaultVariants:{variant:"default",size:"default"}});function u(e){let{className:r,variant:i="default",size:a="default",...u}=e;return(0,t.jsx)(n.$,{"data-slot":"button",className:function(){for(var e=arguments.length,r=Array(e),i=0;i<e;i++)r[i]=arguments[i];return(0,s.QP)((0,d.$)(r))}(o({variant:i,size:a,className:r})),...u})}}},e=>{e.O(0,[366,619,441,255,358],()=>e(e.s=4659)),_N_E=e.O()}]);
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[358],{3167:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,7150,23)),Promise.resolve().then(n.t.bind(n,1959,23)),Promise.resolve().then(n.t.bind(n,7989,23)),Promise.resolve().then(n.t.bind(n,3886,23)),Promise.resolve().then(n.t.bind(n,9766,23)),Promise.resolve().then(n.t.bind(n,5278,23)),Promise.resolve().then(n.t.bind(n,8924,23)),Promise.resolve().then(n.t.bind(n,4431,23)),Promise.resolve().then(n.bind(n,622))},9393:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[441,255],()=>(s(1666),s(3167))),_N_E=e.O()}]);
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[636],{326:(_,n,p)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return p(5139)}])}},_=>{var n=n=>_(_.s=n);_.O(0,[593,792],()=>(n(326),n(6763))),_N_E=_.O()}]);
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[731],{2164:(_,n,e)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return e(1646)}])}},_=>{_.O(0,[636,593,792],()=>_(_.s=2164)),_N_E=_.O()}]);
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
||||||
|
(()=>{"use strict";var e={},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={exports:{}},i=!0;try{e[o](a,a.exports,r),i=!1}finally{i&&delete t[o]}return a.exports}r.m=e,(()=>{var e=[];r.O=(t,o,n,a)=>{if(o){a=a||0;for(var i=e.length;i>0&&e[i-1][2]>a;i--)e[i]=e[i-1];e[i]=[o,n,a];return}for(var u=1/0,i=0;i<e.length;i++){for(var[o,n,a]=e[i],l=!0,c=0;c<o.length;c++)(!1&a||u>=a)&&Object.keys(r.O).every(e=>r.O[e](o[c]))?o.splice(c--,1):(l=!1,a<u&&(u=a));if(l){e.splice(i--,1);var d=n();void 0!==d&&(t=d)}}return t}})(),r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;r.t=function(o,n){if(1&n&&(o=this(o)),8&n||"object"==typeof o&&o&&(4&n&&o.__esModule||16&n&&"function"==typeof o.then))return o;var a=Object.create(null);r.r(a);var i={};e=e||[null,t({}),t([]),t(t)];for(var u=2&n&&o;"object"==typeof u&&!~e.indexOf(u);u=t(u))Object.getOwnPropertyNames(u).forEach(e=>i[e]=()=>o[e]);return i.default=()=>o,r.d(a,i),a}})(),r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,o)=>(r.f[o](e,t),t),[])),r.u=e=>{},r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={},t="_N_E:";r.l=(o,n,a,i)=>{if(e[o])return void e[o].push(n);if(void 0!==a)for(var u,l,c=document.getElementsByTagName("script"),d=0;d<c.length;d++){var f=c[d];if(f.getAttribute("src")==o||f.getAttribute("data-webpack")==t+a){u=f;break}}u||(l=!0,(u=document.createElement("script")).charset="utf-8",u.timeout=120,r.nc&&u.setAttribute("nonce",r.nc),u.setAttribute("data-webpack",t+a),u.src=r.tu(o)),e[o]=[n];var s=(t,r)=>{u.onerror=u.onload=null,clearTimeout(p);var n=e[o];if(delete e[o],u.parentNode&&u.parentNode.removeChild(u),n&&n.forEach(e=>e(r)),t)return t(r)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:u}),12e4);u.onerror=s.bind(null,u.onerror),u.onload=s.bind(null,u.onload),l&&document.head.appendChild(u)}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:e=>e},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("nextjs#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="/_next/",(()=>{var e={68:0,891:0};r.f.j=(t,o)=>{var n=r.o(e,t)?e[t]:void 0;if(0!==n)if(n)o.push(n[2]);else if(/^(68|891)$/.test(t))e[t]=0;else{var a=new Promise((r,o)=>n=e[t]=[r,o]);o.push(n[2]=a);var i=r.p+r.u(t),u=Error();r.l(i,o=>{if(r.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var a=o&&("load"===o.type?"missing":o.type),i=o&&o.target&&o.target.src;u.message="Loading chunk "+t+" failed.\n("+a+": "+i+")",u.name="ChunkLoadError",u.type=a,u.request=i,n[1](u)}},"chunk-"+t,t)}},r.O.j=t=>0===e[t];var t=(t,o)=>{var n,a,[i,u,l]=o,c=0;if(i.some(t=>0!==e[t])){for(n in u)r.o(u,n)&&(r.m[n]=u[n]);if(l)var d=l(r)}for(t&&t(o);c<i.length;c++)a=i[c],r.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return r.O(d)},o=self.webpackChunk_N_E=self.webpackChunk_N_E||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})()})();
|
||||||
3
.open-next/assets/_next/static/css/a3cf521d5fc8fd2d.css
Normal file
3
.open-next/assets/_next/static/css/a3cf521d5fc8fd2d.css
Normal file
File diff suppressed because one or more lines are too long
BIN
.open-next/assets/_next/static/media/19cfc7226ec3afaa-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/19cfc7226ec3afaa-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/21350d82a1f187e9-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/21350d82a1f187e9-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/28a2004cf8372660-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/28a2004cf8372660-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/47f136985ef5b5cb-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/47f136985ef5b5cb-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/4ead58c4dcc3f285-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/4ead58c4dcc3f285-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/8e9860b6e62d6359-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/8e9860b6e62d6359-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/ba9851c3c22cd980-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/ba9851c3c22cd980-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/c5fe6dc8356a8c31-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/c5fe6dc8356a8c31-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/df0a9ae256c0569c-s.woff2
Normal file
BIN
.open-next/assets/_next/static/media/df0a9ae256c0569c-s.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/e4af272ccee01ff0-s.p.woff2
Normal file
BIN
.open-next/assets/_next/static/media/e4af272ccee01ff0-s.p.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/_next/static/media/eaead17c7dbfcd5d-s.p.woff2
Normal file
BIN
.open-next/assets/_next/static/media/eaead17c7dbfcd5d-s.p.woff2
Normal file
Binary file not shown.
BIN
.open-next/assets/favicon.ico
Normal file
BIN
.open-next/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
1
.open-next/assets/file.svg
Normal file
1
.open-next/assets/file.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 391 B |
1
.open-next/assets/globe.svg
Normal file
1
.open-next/assets/globe.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
1
.open-next/assets/next.svg
Normal file
1
.open-next/assets/next.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
.open-next/assets/vercel.svg
Normal file
1
.open-next/assets/vercel.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
||||||
|
After Width: | Height: | Size: 128 B |
1
.open-next/assets/window.svg
Normal file
1
.open-next/assets/window.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
||||||
|
After Width: | Height: | Size: 385 B |
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/500.cache
vendored
Normal file
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/500.cache
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"type":"app","html":"<!DOCTYPE html><html><head><meta charSet=\"utf-8\" data-next-head=\"\"/><meta name=\"viewport\" content=\"width=device-width\" data-next-head=\"\"/><title data-next-head=\"\">500: Internal Server Error</title><noscript data-n-css=\"\"></noscript><script defer=\"\" nomodule=\"\" src=\"/_next/static/chunks/polyfills-42372ed130431b0a.js\"></script><script src=\"/_next/static/chunks/webpack-88963a06a789d277.js\" defer=\"\"></script><script src=\"/_next/static/chunks/framework-a6e0b7e30f98059a.js\" defer=\"\"></script><script src=\"/_next/static/chunks/main-fd57048560d67b20.js\" defer=\"\"></script><script src=\"/_next/static/chunks/pages/_app-7d307437aca18ad4.js\" defer=\"\"></script><script src=\"/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js\" defer=\"\"></script><script src=\"/_next/static/15aOepE5x4uUwOLZRAN9M/_buildManifest.js\" defer=\"\"></script><script src=\"/_next/static/15aOepE5x4uUwOLZRAN9M/_ssgManifest.js\" defer=\"\"></script></head><body><div id=\"__next\"><div style=\"font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center\"><div style=\"line-height:48px\"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class=\"next-error-h1\" style=\"display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top\">500</h1><div style=\"display:inline-block\"><h2 style=\"font-size:14px;font-weight:400;line-height:28px\">Internal Server Error<!-- -->.</h2></div></div></div></div><script id=\"__NEXT_DATA__\" type=\"application/json\">{\"props\":{\"pageProps\":{\"statusCode\":500}},\"page\":\"/_error\",\"query\":{},\"buildId\":\"15aOepE5x4uUwOLZRAN9M\",\"nextExport\":true,\"isFallback\":false,\"gip\":true,\"scriptLoader\":[]}</script></body></html>"}
|
||||||
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/_not-found.cache
vendored
Normal file
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/_not-found.cache
vendored
Normal file
File diff suppressed because one or more lines are too long
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/appointment.cache
vendored
Normal file
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/appointment.cache
vendored
Normal file
File diff suppressed because one or more lines are too long
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/contact.cache
vendored
Normal file
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/contact.cache
vendored
Normal file
File diff suppressed because one or more lines are too long
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/favicon.ico.cache
vendored
Normal file
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/favicon.ico.cache
vendored
Normal file
File diff suppressed because one or more lines are too long
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/index.cache
vendored
Normal file
1
.open-next/cache/15aOepE5x4uUwOLZRAN9M/index.cache
vendored
Normal file
File diff suppressed because one or more lines are too long
85
.open-next/cloudflare-templates/images.d.ts
vendored
Normal file
85
.open-next/cloudflare-templates/images.d.ts
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
export type RemotePattern = {
|
||||||
|
protocol?: "http" | "https";
|
||||||
|
hostname: string;
|
||||||
|
port?: string;
|
||||||
|
pathname: string;
|
||||||
|
search?: string;
|
||||||
|
};
|
||||||
|
export type LocalPattern = {
|
||||||
|
pathname: string;
|
||||||
|
search?: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Handles requests to /_next/image(/), including image optimizations.
|
||||||
|
*
|
||||||
|
* Image optimization is disabled and the original image is returned if `env.IMAGES` is undefined.
|
||||||
|
*
|
||||||
|
* Throws an exception on unexpected errors.
|
||||||
|
*
|
||||||
|
* @param requestURL
|
||||||
|
* @param requestHeaders
|
||||||
|
* @param env
|
||||||
|
* @returns A promise that resolves to the resolved request.
|
||||||
|
*/
|
||||||
|
export declare function handleImageRequest(requestURL: URL, requestHeaders: Headers, env: CloudflareEnv): Promise<Response>;
|
||||||
|
/**
|
||||||
|
* Handles requests to /cdn-cgi/image/ in development.
|
||||||
|
*
|
||||||
|
* Extracts the image URL, fetches the image, and checks the content type against
|
||||||
|
* Cloudflare's supported input formats.
|
||||||
|
*
|
||||||
|
* @param requestURL The full request URL.
|
||||||
|
* @param env The Cloudflare environment bindings.
|
||||||
|
* @returns A promise that resolves to the image response.
|
||||||
|
*/
|
||||||
|
export declare function handleCdnCgiImageRequest(requestURL: URL, env: CloudflareEnv): Promise<Response>;
|
||||||
|
/**
|
||||||
|
* Parses a /cdn-cgi/image/ request URL.
|
||||||
|
*
|
||||||
|
* Extracts the image URL from the `/cdn-cgi/image/<options>/<image-url>` path format.
|
||||||
|
* Rejects protocol-relative URLs (`//...`). The cdn-cgi options are not parsed or
|
||||||
|
* validated as they are Cloudflare's concern.
|
||||||
|
*
|
||||||
|
* @param pathname The URL pathname (e.g. `/cdn-cgi/image/width=640,quality=75,format=auto/path/to/image.png`).
|
||||||
|
* @returns the parsed URL result or an error.
|
||||||
|
*/
|
||||||
|
export declare function parseCdnCgiImageRequest(pathname: string): {
|
||||||
|
ok: true;
|
||||||
|
url: string;
|
||||||
|
static: boolean;
|
||||||
|
} | ErrorResult;
|
||||||
|
export type OptimizedImageFormat = "image/avif" | "image/webp";
|
||||||
|
type ErrorResult = {
|
||||||
|
ok: false;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
export declare function matchLocalPattern(pattern: LocalPattern, url: {
|
||||||
|
pathname: string;
|
||||||
|
search: string;
|
||||||
|
}): boolean;
|
||||||
|
export declare function matchRemotePattern(pattern: RemotePattern, url: URL): boolean;
|
||||||
|
type ImageContentType = "image/avif" | "image/webp" | "image/png" | "image/jpeg" | "image/jxl" | "image/jp2" | "image/heic" | "image/gif" | "image/svg+xml" | "image/x-icon" | "image/x-icns" | "image/tiff" | "image/bmp";
|
||||||
|
/**
|
||||||
|
* Detects the content type by looking at the first few bytes of a file
|
||||||
|
*
|
||||||
|
* Based on https://github.com/vercel/next.js/blob/72c9635/packages/next/src/server/image-optimizer.ts#L155
|
||||||
|
*
|
||||||
|
* @param buffer The image bytes
|
||||||
|
* @returns a content type of undefined for unsupported content
|
||||||
|
*/
|
||||||
|
export declare function detectImageContentType(buffer: Uint8Array): ImageContentType | null;
|
||||||
|
declare global {
|
||||||
|
var __IMAGES_REMOTE_PATTERNS__: RemotePattern[];
|
||||||
|
var __IMAGES_LOCAL_PATTERNS__: LocalPattern[];
|
||||||
|
var __IMAGES_DEVICE_SIZES__: number[];
|
||||||
|
var __IMAGES_IMAGE_SIZES__: number[];
|
||||||
|
var __IMAGES_QUALITIES__: number[];
|
||||||
|
var __IMAGES_FORMATS__: NextConfigImageFormat[];
|
||||||
|
var __IMAGES_MINIMUM_CACHE_TTL_SEC__: number;
|
||||||
|
var __IMAGES_ALLOW_SVG__: boolean;
|
||||||
|
var __IMAGES_CONTENT_SECURITY_POLICY__: string;
|
||||||
|
var __IMAGES_CONTENT_DISPOSITION__: string;
|
||||||
|
var __IMAGES_MAX_REDIRECTS__: number;
|
||||||
|
type NextConfigImageFormat = "image/avif" | "image/webp";
|
||||||
|
}
|
||||||
|
export {};
|
||||||
690
.open-next/cloudflare-templates/images.js
Normal file
690
.open-next/cloudflare-templates/images.js
Normal file
|
|
@ -0,0 +1,690 @@
|
||||||
|
import { error, warn } from "@opennextjs/aws/adapters/logger.js";
|
||||||
|
/**
|
||||||
|
* Handles requests to /_next/image(/), including image optimizations.
|
||||||
|
*
|
||||||
|
* Image optimization is disabled and the original image is returned if `env.IMAGES` is undefined.
|
||||||
|
*
|
||||||
|
* Throws an exception on unexpected errors.
|
||||||
|
*
|
||||||
|
* @param requestURL
|
||||||
|
* @param requestHeaders
|
||||||
|
* @param env
|
||||||
|
* @returns A promise that resolves to the resolved request.
|
||||||
|
*/
|
||||||
|
export async function handleImageRequest(requestURL, requestHeaders, env) {
|
||||||
|
const parseResult = parseImageRequest(requestURL, requestHeaders);
|
||||||
|
if (!parseResult.ok) {
|
||||||
|
return new Response(parseResult.message, {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let imageResponse;
|
||||||
|
if (parseResult.url.startsWith("/")) {
|
||||||
|
if (env.ASSETS === undefined) {
|
||||||
|
error("env.ASSETS binding is not defined");
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: 404,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const absoluteURL = new URL(parseResult.url, requestURL);
|
||||||
|
imageResponse = await env.ASSETS.fetch(absoluteURL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let fetchImageResult;
|
||||||
|
try {
|
||||||
|
fetchImageResult = await fetchWithRedirects(parseResult.url, 7_000, __IMAGES_MAX_REDIRECTS__);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new Error("Failed to fetch image", { cause: e });
|
||||||
|
}
|
||||||
|
if (!fetchImageResult.ok) {
|
||||||
|
if (fetchImageResult.error === "timed_out") {
|
||||||
|
return new Response('"url" parameter is valid but upstream response timed out', {
|
||||||
|
status: 504,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (fetchImageResult.error === "too_many_redirects") {
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: 508,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw new Error("Failed to fetch image");
|
||||||
|
}
|
||||||
|
imageResponse = fetchImageResult.response;
|
||||||
|
}
|
||||||
|
if (!imageResponse.ok || imageResponse.body === null) {
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: imageResponse.status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let immutable = false;
|
||||||
|
if (parseResult.static) {
|
||||||
|
immutable = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const cacheControlHeader = imageResponse.headers.get("Cache-Control");
|
||||||
|
if (cacheControlHeader !== null) {
|
||||||
|
// TODO: Properly parse header
|
||||||
|
immutable = cacheControlHeader.includes("immutable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const readHeaderResult = await readImageHeader(imageResponse);
|
||||||
|
if (readHeaderResult instanceof Response) {
|
||||||
|
return readHeaderResult;
|
||||||
|
}
|
||||||
|
const { contentType, imageStream } = readHeaderResult;
|
||||||
|
if (contentType === null) {
|
||||||
|
warn(`Failed to detect content type of "${parseResult.url}"`);
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (contentType === SVG) {
|
||||||
|
if (!__IMAGES_ALLOW_SVG__) {
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const response = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
if (contentType === GIF) {
|
||||||
|
if (env.IMAGES === undefined) {
|
||||||
|
warn("env.IMAGES binding is not defined");
|
||||||
|
const response = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
const imageSource = env.IMAGES.input(imageStream);
|
||||||
|
const imageTransformationResult = await imageSource
|
||||||
|
.transform({
|
||||||
|
width: parseResult.width,
|
||||||
|
fit: "scale-down",
|
||||||
|
})
|
||||||
|
.output({
|
||||||
|
quality: parseResult.quality,
|
||||||
|
format: GIF,
|
||||||
|
});
|
||||||
|
const outputImageStream = imageTransformationResult.image();
|
||||||
|
const response = createImageResponse(outputImageStream, GIF, {
|
||||||
|
immutable,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
if (contentType === AVIF || contentType === WEBP || contentType === JPEG || contentType === PNG) {
|
||||||
|
if (env.IMAGES === undefined) {
|
||||||
|
warn("env.IMAGES binding is not defined");
|
||||||
|
const response = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
const outputFormat = parseResult.format ?? contentType;
|
||||||
|
const imageSource = env.IMAGES.input(imageStream);
|
||||||
|
const imageTransformationResult = await imageSource
|
||||||
|
.transform({
|
||||||
|
width: parseResult.width,
|
||||||
|
fit: "scale-down",
|
||||||
|
})
|
||||||
|
.output({
|
||||||
|
quality: parseResult.quality,
|
||||||
|
format: outputFormat,
|
||||||
|
});
|
||||||
|
const outputImageStream = imageTransformationResult.image();
|
||||||
|
const response = createImageResponse(outputImageStream, outputFormat, {
|
||||||
|
immutable,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
warn(`Image content type ${contentType} not supported`);
|
||||||
|
const response = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles requests to /cdn-cgi/image/ in development.
|
||||||
|
*
|
||||||
|
* Extracts the image URL, fetches the image, and checks the content type against
|
||||||
|
* Cloudflare's supported input formats.
|
||||||
|
*
|
||||||
|
* @param requestURL The full request URL.
|
||||||
|
* @param env The Cloudflare environment bindings.
|
||||||
|
* @returns A promise that resolves to the image response.
|
||||||
|
*/
|
||||||
|
export async function handleCdnCgiImageRequest(requestURL, env) {
|
||||||
|
const parseResult = parseCdnCgiImageRequest(requestURL.pathname);
|
||||||
|
if (!parseResult.ok) {
|
||||||
|
return new Response(parseResult.message, {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let imageResponse;
|
||||||
|
if (parseResult.url.startsWith("/")) {
|
||||||
|
if (env.ASSETS === undefined) {
|
||||||
|
return new Response("env.ASSETS binding is not defined", {
|
||||||
|
status: 404,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const absoluteURL = new URL(parseResult.url, requestURL);
|
||||||
|
imageResponse = await env.ASSETS.fetch(absoluteURL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
imageResponse = await fetch(parseResult.url);
|
||||||
|
}
|
||||||
|
if (!imageResponse.ok || imageResponse.body === null) {
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: imageResponse.status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const readHeaderResult = await readImageHeader(imageResponse);
|
||||||
|
if (readHeaderResult instanceof Response) {
|
||||||
|
return readHeaderResult;
|
||||||
|
}
|
||||||
|
const { contentType, imageStream } = readHeaderResult;
|
||||||
|
if (contentType === null || !SUPPORTED_CDN_CGI_INPUT_TYPES.has(contentType)) {
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (contentType === SVG && !__IMAGES_ALLOW_SVG__) {
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Response(imageStream, {
|
||||||
|
headers: { "Content-Type": contentType },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parses a /cdn-cgi/image/ request URL.
|
||||||
|
*
|
||||||
|
* Extracts the image URL from the `/cdn-cgi/image/<options>/<image-url>` path format.
|
||||||
|
* Rejects protocol-relative URLs (`//...`). The cdn-cgi options are not parsed or
|
||||||
|
* validated as they are Cloudflare's concern.
|
||||||
|
*
|
||||||
|
* @param pathname The URL pathname (e.g. `/cdn-cgi/image/width=640,quality=75,format=auto/path/to/image.png`).
|
||||||
|
* @returns the parsed URL result or an error.
|
||||||
|
*/
|
||||||
|
export function parseCdnCgiImageRequest(pathname) {
|
||||||
|
const match = pathname.match(/^\/cdn-cgi\/image\/(?<options>[^/]+)\/(?<url>.+)$/);
|
||||||
|
if (match === null ||
|
||||||
|
// Valid URLs have at least one option
|
||||||
|
!match.groups?.options ||
|
||||||
|
!match.groups?.url) {
|
||||||
|
return { ok: false, message: "Invalid /cdn-cgi/image/ URL format" };
|
||||||
|
}
|
||||||
|
const imageUrl = match.groups.url;
|
||||||
|
// The regex separator consumes one `/`, so if imageUrl starts with `/`
|
||||||
|
// the original URL segment was protocol-relative (`//...`).
|
||||||
|
if (imageUrl.startsWith("/")) {
|
||||||
|
return { ok: false, message: '"url" parameter cannot be a protocol-relative URL (//)' };
|
||||||
|
}
|
||||||
|
// Resolve the image URL: it may be absolute (https://...) or relative.
|
||||||
|
let resolvedUrl;
|
||||||
|
if (imageUrl.match(/^https?:\/\//)) {
|
||||||
|
resolvedUrl = imageUrl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Relative URLs need a leading slash.
|
||||||
|
resolvedUrl = `/${imageUrl}`;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
url: resolvedUrl,
|
||||||
|
static: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reads the first 32 bytes of an image response to detect its content type.
|
||||||
|
*
|
||||||
|
* Tees the response body so the image stream can still be consumed after detection.
|
||||||
|
*
|
||||||
|
* @param imageResponse The image response whose body to read.
|
||||||
|
* @returns The detected content type and image stream, or an error Response if the header bytes
|
||||||
|
* could not be read.
|
||||||
|
*/
|
||||||
|
async function readImageHeader(imageResponse) {
|
||||||
|
// Note: imageResponse.body is non-null — callers check before calling.
|
||||||
|
const [contentTypeStream, imageStream] = imageResponse.body.tee();
|
||||||
|
const headerBytes = new Uint8Array(32);
|
||||||
|
const reader = contentTypeStream.getReader({ mode: "byob" });
|
||||||
|
const readResult = await reader.readAtLeast(32, headerBytes);
|
||||||
|
if (readResult.value === undefined) {
|
||||||
|
await imageResponse.body.cancel();
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const contentType = detectImageContentType(readResult.value);
|
||||||
|
return { contentType, imageStream };
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fetch call with max redirects and timeouts.
|
||||||
|
*
|
||||||
|
* Re-throws the exception thrown by a fetch call.
|
||||||
|
* @param url
|
||||||
|
* @param timeoutMS Timeout for a single fetch call.
|
||||||
|
* @param maxRedirectCount
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function fetchWithRedirects(url, timeoutMS, maxRedirectCount) {
|
||||||
|
// TODO: Add dangerouslyAllowLocalIP support
|
||||||
|
let response;
|
||||||
|
try {
|
||||||
|
response = await fetch(url, {
|
||||||
|
signal: AbortSignal.timeout(timeoutMS),
|
||||||
|
redirect: "manual",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (e instanceof Error && e.name === "TimeoutError") {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
error: "timed_out",
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
if (redirectResponseStatuses.includes(response.status)) {
|
||||||
|
const locationHeader = response.headers.get("Location");
|
||||||
|
if (locationHeader !== null) {
|
||||||
|
if (maxRedirectCount < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
error: "too_many_redirects",
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
let redirectTarget;
|
||||||
|
if (locationHeader.startsWith("/")) {
|
||||||
|
redirectTarget = new URL(locationHeader, url).href;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
redirectTarget = locationHeader;
|
||||||
|
}
|
||||||
|
const result = await fetchWithRedirects(redirectTarget, timeoutMS, maxRedirectCount - 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = {
|
||||||
|
ok: true,
|
||||||
|
response: response,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const redirectResponseStatuses = [301, 302, 303, 307, 308];
|
||||||
|
function createImageResponse(image, contentType, imageResponseFlags) {
|
||||||
|
const response = new Response(image, {
|
||||||
|
headers: {
|
||||||
|
Vary: "Accept",
|
||||||
|
"Content-Type": contentType,
|
||||||
|
"Content-Disposition": __IMAGES_CONTENT_DISPOSITION__,
|
||||||
|
"Content-Security-Policy": __IMAGES_CONTENT_SECURITY_POLICY__,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (imageResponseFlags.immutable) {
|
||||||
|
response.headers.set("Cache-Control", "public, max-age=315360000, immutable");
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parses the image request URL and headers.
|
||||||
|
*
|
||||||
|
* This function validates the parameters and returns either the parsed result or an error message.
|
||||||
|
*
|
||||||
|
* @param requestURL request URL
|
||||||
|
* @param requestHeaders request headers
|
||||||
|
* @returns an instance of `ParseImageRequestURLSuccessResult` when successful, or an instance of `ErrorResult` when failed.
|
||||||
|
*/
|
||||||
|
function parseImageRequest(requestURL, requestHeaders) {
|
||||||
|
const formats = __IMAGES_FORMATS__;
|
||||||
|
const parsedUrlOrError = validateUrlQueryParameter(requestURL);
|
||||||
|
if (!("url" in parsedUrlOrError)) {
|
||||||
|
return parsedUrlOrError;
|
||||||
|
}
|
||||||
|
const widthOrError = validateWidthQueryParameter(requestURL);
|
||||||
|
if (typeof widthOrError !== "number") {
|
||||||
|
return widthOrError;
|
||||||
|
}
|
||||||
|
const qualityOrError = validateQualityQueryParameter(requestURL);
|
||||||
|
if (typeof qualityOrError !== "number") {
|
||||||
|
return qualityOrError;
|
||||||
|
}
|
||||||
|
const acceptHeader = requestHeaders.get("Accept") ?? "";
|
||||||
|
let format = null;
|
||||||
|
// Find a more specific format that the client accepts.
|
||||||
|
for (const allowedFormat of formats) {
|
||||||
|
if (acceptHeader.includes(allowedFormat)) {
|
||||||
|
format = allowedFormat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = {
|
||||||
|
ok: true,
|
||||||
|
url: parsedUrlOrError.url,
|
||||||
|
width: widthOrError,
|
||||||
|
quality: qualityOrError,
|
||||||
|
format,
|
||||||
|
static: parsedUrlOrError.static,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Validates that there is exactly one "url" query parameter.
|
||||||
|
*
|
||||||
|
* Checks length, protocol-relative URLs, local/remote pattern matching, recursion, and protocol.
|
||||||
|
*
|
||||||
|
* @param requestURL The request URL containing the "url" query parameter.
|
||||||
|
* @returns the validated URL or an error result.
|
||||||
|
*/
|
||||||
|
function validateUrlQueryParameter(requestURL) {
|
||||||
|
// There should be a single "url" parameter.
|
||||||
|
const urls = requestURL.searchParams.getAll("url");
|
||||||
|
if (urls.length < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is required',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (urls.length > 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter cannot be an array',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const url = urls[0];
|
||||||
|
if (url.length > 3072) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is too long',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (url.startsWith("//")) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter cannot be a protocol-relative URL (//)',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (url.startsWith("/")) {
|
||||||
|
const staticAsset = url.startsWith(`${__NEXT_BASE_PATH__ || ""}/_next/static/media`);
|
||||||
|
const pathname = getPathnameFromRelativeURL(url);
|
||||||
|
if (/\/_next\/image($|\/)/.test(decodeURIComponent(pathname))) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter cannot be recursive',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!staticAsset) {
|
||||||
|
if (!hasLocalMatch(__IMAGES_LOCAL_PATTERNS__, url)) {
|
||||||
|
const result = { ok: false, message: '"url" parameter is not allowed' };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { url, static: staticAsset };
|
||||||
|
}
|
||||||
|
let parsedURL;
|
||||||
|
try {
|
||||||
|
parsedURL = new URL(url);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
const result = { ok: false, message: '"url" parameter is invalid' };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const validProtocols = ["http:", "https:"];
|
||||||
|
if (!validProtocols.includes(parsedURL.protocol)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is invalid',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!hasRemoteMatch(__IMAGES_REMOTE_PATTERNS__, parsedURL)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is not allowed',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return { url: parsedURL.href, static: false };
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Validates the "w" (width) query parameter.
|
||||||
|
*
|
||||||
|
* @returns the validated width number or an error result.
|
||||||
|
*/
|
||||||
|
function validateWidthQueryParameter(requestURL) {
|
||||||
|
const widthQueryValues = requestURL.searchParams.getAll("w");
|
||||||
|
if (widthQueryValues.length < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) is required',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (widthQueryValues.length > 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) cannot be an array',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const widthQueryValue = widthQueryValues[0];
|
||||||
|
if (!/^[0-9]+$/.test(widthQueryValue)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) must be an integer greater than 0',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const width = parseInt(widthQueryValue, 10);
|
||||||
|
if (width <= 0 || isNaN(width)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) must be an integer greater than 0',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const sizeValid = __IMAGES_DEVICE_SIZES__.includes(width) || __IMAGES_IMAGE_SIZES__.includes(width);
|
||||||
|
if (!sizeValid) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: `"w" parameter (width) of ${width} is not allowed`,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Validates the "q" (quality) query parameter.
|
||||||
|
*
|
||||||
|
* @returns the validated quality number or an error result.
|
||||||
|
*/
|
||||||
|
function validateQualityQueryParameter(requestURL) {
|
||||||
|
const qualityQueryValues = requestURL.searchParams.getAll("q");
|
||||||
|
if (qualityQueryValues.length < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) is required',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (qualityQueryValues.length > 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) cannot be an array',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const qualityQueryValue = qualityQueryValues[0];
|
||||||
|
if (!/^[0-9]+$/.test(qualityQueryValue)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) must be an integer between 1 and 100',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const quality = parseInt(qualityQueryValue, 10);
|
||||||
|
if (isNaN(quality) || quality < 1 || quality > 100) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) must be an integer between 1 and 100',
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!__IMAGES_QUALITIES__.includes(quality)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: `"q" parameter (quality) of ${quality} is not allowed`,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return quality;
|
||||||
|
}
|
||||||
|
function getPathnameFromRelativeURL(relativeURL) {
|
||||||
|
return relativeURL.split("?")[0];
|
||||||
|
}
|
||||||
|
function hasLocalMatch(localPatterns, relativeURL) {
|
||||||
|
const parseRelativeURLResult = parseRelativeURL(relativeURL);
|
||||||
|
for (const localPattern of localPatterns) {
|
||||||
|
const matched = matchLocalPattern(localPattern, parseRelativeURLResult);
|
||||||
|
if (matched) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function parseRelativeURL(relativeURL) {
|
||||||
|
if (!relativeURL.includes("?")) {
|
||||||
|
const result = {
|
||||||
|
pathname: relativeURL,
|
||||||
|
search: "",
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const parts = relativeURL.split("?");
|
||||||
|
const pathname = parts[0];
|
||||||
|
const search = "?" + parts.slice(1).join("?");
|
||||||
|
const result = {
|
||||||
|
pathname,
|
||||||
|
search,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
export function matchLocalPattern(pattern, url) {
|
||||||
|
if (pattern.search !== undefined && pattern.search !== url.search) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return new RegExp(pattern.pathname).test(url.pathname);
|
||||||
|
}
|
||||||
|
function hasRemoteMatch(remotePatterns, url) {
|
||||||
|
for (const remotePattern of remotePatterns) {
|
||||||
|
const matched = matchRemotePattern(remotePattern, url);
|
||||||
|
if (matched) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
export function matchRemotePattern(pattern, url) {
|
||||||
|
// https://github.com/vercel/next.js/blob/d76f0b1/packages/next/src/shared/lib/match-remote-pattern.ts
|
||||||
|
if (pattern.protocol !== undefined &&
|
||||||
|
pattern.protocol.replace(/:$/, "") !== url.protocol.replace(/:$/, "")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.port !== undefined && pattern.port !== url.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.hostname === undefined || !new RegExp(pattern.hostname).test(url.hostname)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.search !== undefined && pattern.search !== url.search) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Should be the same as writeImagesManifest()
|
||||||
|
return new RegExp(pattern.pathname).test(url.pathname);
|
||||||
|
}
|
||||||
|
const AVIF = "image/avif";
|
||||||
|
const WEBP = "image/webp";
|
||||||
|
const PNG = "image/png";
|
||||||
|
const JPEG = "image/jpeg";
|
||||||
|
const JXL = "image/jxl";
|
||||||
|
const JP2 = "image/jp2";
|
||||||
|
const HEIC = "image/heic";
|
||||||
|
const GIF = "image/gif";
|
||||||
|
const SVG = "image/svg+xml";
|
||||||
|
const ICO = "image/x-icon";
|
||||||
|
const ICNS = "image/x-icns";
|
||||||
|
const TIFF = "image/tiff";
|
||||||
|
const BMP = "image/bmp";
|
||||||
|
/**
|
||||||
|
* Image content types supported as input by Cloudflare's cdn-cgi image transformation.
|
||||||
|
*
|
||||||
|
* @see https://developers.cloudflare.com/images/transform-images/#supported-input-formats
|
||||||
|
*/
|
||||||
|
const SUPPORTED_CDN_CGI_INPUT_TYPES = new Set([JPEG, PNG, GIF, WEBP, SVG, HEIC]);
|
||||||
|
/**
|
||||||
|
* Detects the content type by looking at the first few bytes of a file
|
||||||
|
*
|
||||||
|
* Based on https://github.com/vercel/next.js/blob/72c9635/packages/next/src/server/image-optimizer.ts#L155
|
||||||
|
*
|
||||||
|
* @param buffer The image bytes
|
||||||
|
* @returns a content type of undefined for unsupported content
|
||||||
|
*/
|
||||||
|
export function detectImageContentType(buffer) {
|
||||||
|
if ([0xff, 0xd8, 0xff].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JPEG;
|
||||||
|
}
|
||||||
|
if ([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].every((b, i) => buffer[i] === b)) {
|
||||||
|
return PNG;
|
||||||
|
}
|
||||||
|
if ([0x47, 0x49, 0x46, 0x38].every((b, i) => buffer[i] === b)) {
|
||||||
|
return GIF;
|
||||||
|
}
|
||||||
|
if ([0x52, 0x49, 0x46, 0x46, 0, 0, 0, 0, 0x57, 0x45, 0x42, 0x50].every((b, i) => !b || buffer[i] === b)) {
|
||||||
|
return WEBP;
|
||||||
|
}
|
||||||
|
if ([0x3c, 0x3f, 0x78, 0x6d, 0x6c].every((b, i) => buffer[i] === b)) {
|
||||||
|
return SVG;
|
||||||
|
}
|
||||||
|
if ([0x3c, 0x73, 0x76, 0x67].every((b, i) => buffer[i] === b)) {
|
||||||
|
return SVG;
|
||||||
|
}
|
||||||
|
if ([0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66].every((b, i) => !b || buffer[i] === b)) {
|
||||||
|
return AVIF;
|
||||||
|
}
|
||||||
|
if ([0x00, 0x00, 0x01, 0x00].every((b, i) => buffer[i] === b)) {
|
||||||
|
return ICO;
|
||||||
|
}
|
||||||
|
if ([0x69, 0x63, 0x6e, 0x73].every((b, i) => buffer[i] === b)) {
|
||||||
|
return ICNS;
|
||||||
|
}
|
||||||
|
if ([0x49, 0x49, 0x2a, 0x00].every((b, i) => buffer[i] === b)) {
|
||||||
|
return TIFF;
|
||||||
|
}
|
||||||
|
if ([0x42, 0x4d].every((b, i) => buffer[i] === b)) {
|
||||||
|
return BMP;
|
||||||
|
}
|
||||||
|
if ([0xff, 0x0a].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JXL;
|
||||||
|
}
|
||||||
|
if ([0x00, 0x00, 0x00, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 0x0d, 0x0a, 0x87, 0x0a].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JXL;
|
||||||
|
}
|
||||||
|
if ([0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63].every((b, i) => !b || buffer[i] === b)) {
|
||||||
|
return HEIC;
|
||||||
|
}
|
||||||
|
if ([0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JP2;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
16
.open-next/cloudflare-templates/init.d.ts
vendored
Normal file
16
.open-next/cloudflare-templates/init.d.ts
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* Initialization for the workerd runtime.
|
||||||
|
*
|
||||||
|
* The file must be imported at the top level the worker.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Executes the handler with the Cloudflare context.
|
||||||
|
*/
|
||||||
|
export declare function runWithCloudflareRequestContext(request: Request, env: CloudflareEnv, ctx: ExecutionContext, handler: () => Promise<Response>): Promise<Response>;
|
||||||
|
declare global {
|
||||||
|
var __BUILD_TIMESTAMP_MS__: number;
|
||||||
|
var __NEXT_BASE_PATH__: string;
|
||||||
|
var __ASSETS_RUN_WORKER_FIRST__: boolean | string[] | undefined;
|
||||||
|
var __DEPLOYMENT_ID__: string;
|
||||||
|
var __TRAILING_SLASH__: boolean;
|
||||||
|
}
|
||||||
122
.open-next/cloudflare-templates/init.js
Normal file
122
.open-next/cloudflare-templates/init.js
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
* Initialization for the workerd runtime.
|
||||||
|
*
|
||||||
|
* The file must be imported at the top level the worker.
|
||||||
|
*/
|
||||||
|
import { AsyncLocalStorage } from "node:async_hooks";
|
||||||
|
import process from "node:process";
|
||||||
|
import stream from "node:stream";
|
||||||
|
// @ts-expect-error: resolved by wrangler build
|
||||||
|
import * as nextEnvVars from "./next-env.mjs";
|
||||||
|
const cloudflareContextALS = new AsyncLocalStorage();
|
||||||
|
// Note: this symbol needs to be kept in sync with `src/api/get-cloudflare-context.ts`
|
||||||
|
Object.defineProperty(globalThis, Symbol.for("__cloudflare-context__"), {
|
||||||
|
get() {
|
||||||
|
return cloudflareContextALS.getStore();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* Executes the handler with the Cloudflare context.
|
||||||
|
*/
|
||||||
|
export async function runWithCloudflareRequestContext(request, env, ctx, handler) {
|
||||||
|
init(request, env);
|
||||||
|
return cloudflareContextALS.run({ env, ctx, cf: request.cf }, handler);
|
||||||
|
}
|
||||||
|
let initialized = false;
|
||||||
|
/**
|
||||||
|
* Initializes the runtime on the first call,
|
||||||
|
* no-op on subsequent invocations.
|
||||||
|
*/
|
||||||
|
function init(request, env) {
|
||||||
|
if (initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
const url = new URL(request.url);
|
||||||
|
initRuntime();
|
||||||
|
populateProcessEnv(url, env);
|
||||||
|
}
|
||||||
|
function initRuntime() {
|
||||||
|
// Some packages rely on `process.version` and `process.versions.node` (i.e. Jose@4)
|
||||||
|
// TODO: Remove when https://github.com/unjs/unenv/pull/493 is merged
|
||||||
|
Object.assign(process, { version: process.version || "v22.14.0" });
|
||||||
|
// @ts-expect-error Node type does not match workerd
|
||||||
|
Object.assign(process.versions, { node: "22.14.0", ...process.versions });
|
||||||
|
globalThis.__dirname ??= "";
|
||||||
|
globalThis.__filename ??= "";
|
||||||
|
// Some packages rely on `import.meta.url` but it is undefined in workerd
|
||||||
|
// For example it causes a bunch of issues, and will make even import crash with payload
|
||||||
|
import.meta.url ??= "file:///worker.js";
|
||||||
|
// Do not crash on cache not supported
|
||||||
|
// https://github.com/cloudflare/workerd/pull/2434
|
||||||
|
// compatibility flag "cache_option_enabled" -> does not support "force-cache"
|
||||||
|
const __original_fetch = globalThis.fetch;
|
||||||
|
globalThis.fetch = (input, init) => {
|
||||||
|
if (init) {
|
||||||
|
delete init.cache;
|
||||||
|
}
|
||||||
|
return __original_fetch(input, init);
|
||||||
|
};
|
||||||
|
const CustomRequest = class extends globalThis.Request {
|
||||||
|
constructor(input, init) {
|
||||||
|
if (init) {
|
||||||
|
delete init.cache;
|
||||||
|
// https://github.com/cloudflare/workerd/issues/2746
|
||||||
|
// https://github.com/cloudflare/workerd/issues/3245
|
||||||
|
Object.defineProperty(init, "body", {
|
||||||
|
// @ts-ignore
|
||||||
|
value: init.body instanceof stream.Readable ? ReadableStream.from(init.body) : init.body,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
super(input, init);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Object.assign(globalThis, {
|
||||||
|
Request: CustomRequest,
|
||||||
|
__BUILD_TIMESTAMP_MS__,
|
||||||
|
__NEXT_BASE_PATH__,
|
||||||
|
__ASSETS_RUN_WORKER_FIRST__,
|
||||||
|
__TRAILING_SLASH__,
|
||||||
|
// The external middleware will use the convertTo function of the `edge` converter
|
||||||
|
// by default it will try to fetch the request, but since we are running everything in the same worker
|
||||||
|
// we need to use the request as is.
|
||||||
|
__dangerous_ON_edge_converter_returns_request: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Populate process.env with:
|
||||||
|
* - the environment variables and secrets from the cloudflare platform
|
||||||
|
* - the variables from Next .env* files
|
||||||
|
* - the origin resolver information
|
||||||
|
*/
|
||||||
|
function populateProcessEnv(url, env) {
|
||||||
|
for (const [key, value] of Object.entries(env)) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
process.env[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mode = env.NEXTJS_ENV ?? "production";
|
||||||
|
if (nextEnvVars[mode]) {
|
||||||
|
for (const key in nextEnvVars[mode]) {
|
||||||
|
process.env[key] ??= nextEnvVars[mode][key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set the default Origin for the origin resolver.
|
||||||
|
// This is only needed for an external middleware bundle
|
||||||
|
process.env.OPEN_NEXT_ORIGIN = JSON.stringify({
|
||||||
|
default: {
|
||||||
|
host: url.hostname,
|
||||||
|
protocol: url.protocol.slice(0, -1),
|
||||||
|
port: url.port,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
/* We need to set this environment variable to make redirects work properly in preview mode.
|
||||||
|
* Next sets this in standalone mode during `startServer`. Without this the protocol would always be `https` here:
|
||||||
|
* https://github.com/vercel/next.js/blob/6b1e48080e896e0d44a05fe009cb79d2d3f91774/packages/next/src/server/app-render/action-handler.ts#L307-L316
|
||||||
|
*/
|
||||||
|
process.env.__NEXT_PRIVATE_ORIGIN = url.origin;
|
||||||
|
// `__DEPLOYMENT_ID__` is a string (passed via ESBuild).
|
||||||
|
if (__DEPLOYMENT_ID__) {
|
||||||
|
process.env.DEPLOYMENT_ID = __DEPLOYMENT_ID__;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
.open-next/cloudflare-templates/shims/empty.d.ts
vendored
Normal file
2
.open-next/cloudflare-templates/shims/empty.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
declare const _default: {};
|
||||||
|
export default _default;
|
||||||
1
.open-next/cloudflare-templates/shims/empty.js
Normal file
1
.open-next/cloudflare-templates/shims/empty.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export default {};
|
||||||
1
.open-next/cloudflare-templates/shims/env.d.ts
vendored
Normal file
1
.open-next/cloudflare-templates/shims/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export declare function loadEnvConfig(): void;
|
||||||
1
.open-next/cloudflare-templates/shims/env.js
Normal file
1
.open-next/cloudflare-templates/shims/env.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export function loadEnvConfig() { }
|
||||||
1
.open-next/cloudflare-templates/shims/fetch.d.ts
vendored
Normal file
1
.open-next/cloudflare-templates/shims/fetch.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export default fetch;
|
||||||
1
.open-next/cloudflare-templates/shims/fetch.js
Normal file
1
.open-next/cloudflare-templates/shims/fetch.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export default fetch;
|
||||||
2
.open-next/cloudflare-templates/shims/throw.d.ts
vendored
Normal file
2
.open-next/cloudflare-templates/shims/throw.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
declare const _default: {};
|
||||||
|
export default _default;
|
||||||
2
.open-next/cloudflare-templates/shims/throw.js
Normal file
2
.open-next/cloudflare-templates/shims/throw.js
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
throw "OpenNext shim";
|
||||||
|
export default {};
|
||||||
28
.open-next/cloudflare-templates/skew-protection.d.ts
vendored
Normal file
28
.open-next/cloudflare-templates/skew-protection.d.ts
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/** Name of the env var containing the mapping */
|
||||||
|
export declare const DEPLOYMENT_MAPPING_ENV_NAME = "CF_DEPLOYMENT_MAPPING";
|
||||||
|
/** Version used for the latest worker */
|
||||||
|
export declare const CURRENT_VERSION_ID = "current";
|
||||||
|
/**
|
||||||
|
* Routes the request to the requested deployment.
|
||||||
|
*
|
||||||
|
* A specific deployment can be requested via:
|
||||||
|
* - the `dpl` search parameter for assets
|
||||||
|
* - the `x-deployment-id` for other requests
|
||||||
|
*
|
||||||
|
* When a specific deployment is requested, we route to that deployment via the preview URLs.
|
||||||
|
* See https://developers.cloudflare.com/workers/configuration/previews/
|
||||||
|
*
|
||||||
|
* When the requested deployment is not supported a 400 response is returned.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - The re-routing is only active for the deployed version of the app (on a custom domain)
|
||||||
|
* - Assets are also handled when `run_worker_first` is enabled.
|
||||||
|
* See https://developers.cloudflare.com/workers/static-assets/binding/#run_worker_first
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export declare function maybeGetSkewProtectionResponse(request: Request): Promise<Response> | Response | undefined;
|
||||||
|
declare global {
|
||||||
|
var __SKEW_PROTECTION_ENABLED__: boolean;
|
||||||
|
}
|
||||||
60
.open-next/cloudflare-templates/skew-protection.js
Normal file
60
.open-next/cloudflare-templates/skew-protection.js
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import process from "node:process";
|
||||||
|
/** Name of the env var containing the mapping */
|
||||||
|
export const DEPLOYMENT_MAPPING_ENV_NAME = "CF_DEPLOYMENT_MAPPING";
|
||||||
|
/** Version used for the latest worker */
|
||||||
|
export const CURRENT_VERSION_ID = "current";
|
||||||
|
let deploymentMapping;
|
||||||
|
/**
|
||||||
|
* Routes the request to the requested deployment.
|
||||||
|
*
|
||||||
|
* A specific deployment can be requested via:
|
||||||
|
* - the `dpl` search parameter for assets
|
||||||
|
* - the `x-deployment-id` for other requests
|
||||||
|
*
|
||||||
|
* When a specific deployment is requested, we route to that deployment via the preview URLs.
|
||||||
|
* See https://developers.cloudflare.com/workers/configuration/previews/
|
||||||
|
*
|
||||||
|
* When the requested deployment is not supported a 400 response is returned.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - The re-routing is only active for the deployed version of the app (on a custom domain)
|
||||||
|
* - Assets are also handled when `run_worker_first` is enabled.
|
||||||
|
* See https://developers.cloudflare.com/workers/static-assets/binding/#run_worker_first
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function maybeGetSkewProtectionResponse(request) {
|
||||||
|
// no early return as esbuild would not treeshake the code.
|
||||||
|
if (__SKEW_PROTECTION_ENABLED__) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
// Skew protection is only active for the latest version of the app served on a custom domain.
|
||||||
|
if (url.hostname === "localhost" || url.hostname.endsWith(".workers.dev")) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const requestDeploymentId = request.headers.get("x-deployment-id") ?? url.searchParams.get("dpl");
|
||||||
|
if (!requestDeploymentId || requestDeploymentId === process.env.DEPLOYMENT_ID) {
|
||||||
|
// The request does not specify a deployment id or it is the current deployment id
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
deploymentMapping ??= process.env[DEPLOYMENT_MAPPING_ENV_NAME]
|
||||||
|
? JSON.parse(process.env[DEPLOYMENT_MAPPING_ENV_NAME])
|
||||||
|
: {};
|
||||||
|
if (!(requestDeploymentId in deploymentMapping)) {
|
||||||
|
// Unknown deployment id, serve the current version
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const version = deploymentMapping[requestDeploymentId];
|
||||||
|
if (!version || version === CURRENT_VERSION_ID) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const versionDomain = version.split("-")[0];
|
||||||
|
const hostname = `${versionDomain}-${process.env.CF_WORKER_NAME}.${process.env.CF_PREVIEW_DOMAIN}.workers.dev`;
|
||||||
|
url.hostname = hostname;
|
||||||
|
const requestToOlderDeployment = new Request(url, request);
|
||||||
|
// Remove the origin header to prevent an error with POST requests
|
||||||
|
const headers = new Headers(request.headers);
|
||||||
|
headers.delete("origin");
|
||||||
|
return fetch(requestToOlderDeployment, { headers });
|
||||||
|
}
|
||||||
|
}
|
||||||
7
.open-next/cloudflare-templates/worker.d.ts
vendored
Normal file
7
.open-next/cloudflare-templates/worker.d.ts
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export { DOQueueHandler } from "./.build/durable-objects/queue.js";
|
||||||
|
export { DOShardedTagCache } from "./.build/durable-objects/sharded-tag-cache.js";
|
||||||
|
export { BucketCachePurge } from "./.build/durable-objects/bucket-cache-purge.js";
|
||||||
|
declare const _default: {
|
||||||
|
fetch(request: Request<unknown, IncomingRequestCfProperties<unknown>>, env: CloudflareEnv, ctx: ExecutionContext<unknown>): Promise<any>;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
43
.open-next/cloudflare-templates/worker.js
Normal file
43
.open-next/cloudflare-templates/worker.js
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//@ts-expect-error: Will be resolved by wrangler build
|
||||||
|
import { handleCdnCgiImageRequest, handleImageRequest } from "./cloudflare/images.js";
|
||||||
|
//@ts-expect-error: Will be resolved by wrangler build
|
||||||
|
import { runWithCloudflareRequestContext } from "./cloudflare/init.js";
|
||||||
|
//@ts-expect-error: Will be resolved by wrangler build
|
||||||
|
import { maybeGetSkewProtectionResponse } from "./cloudflare/skew-protection.js";
|
||||||
|
// @ts-expect-error: Will be resolved by wrangler build
|
||||||
|
import { handler as middlewareHandler } from "./middleware/handler.mjs";
|
||||||
|
//@ts-expect-error: Will be resolved by wrangler build
|
||||||
|
export { DOQueueHandler } from "./.build/durable-objects/queue.js";
|
||||||
|
//@ts-expect-error: Will be resolved by wrangler build
|
||||||
|
export { DOShardedTagCache } from "./.build/durable-objects/sharded-tag-cache.js";
|
||||||
|
//@ts-expect-error: Will be resolved by wrangler build
|
||||||
|
export { BucketCachePurge } from "./.build/durable-objects/bucket-cache-purge.js";
|
||||||
|
export default {
|
||||||
|
async fetch(request, env, ctx) {
|
||||||
|
return runWithCloudflareRequestContext(request, env, ctx, async () => {
|
||||||
|
const response = maybeGetSkewProtectionResponse(request);
|
||||||
|
if (response) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
const url = new URL(request.url);
|
||||||
|
// Serve images in development.
|
||||||
|
// Note: "/cdn-cgi/image/..." requests do not reach production workers.
|
||||||
|
if (url.pathname.startsWith("/cdn-cgi/image/")) {
|
||||||
|
return handleCdnCgiImageRequest(url, env);
|
||||||
|
}
|
||||||
|
// Fallback for the Next default image loader.
|
||||||
|
if (url.pathname ===
|
||||||
|
`${globalThis.__NEXT_BASE_PATH__}/_next/image${globalThis.__TRAILING_SLASH__ ? "/" : ""}`) {
|
||||||
|
return await handleImageRequest(url, request.headers, env);
|
||||||
|
}
|
||||||
|
// - `Request`s are handled by the Next server
|
||||||
|
const reqOrResp = await middlewareHandler(request, env, ctx);
|
||||||
|
if (reqOrResp instanceof Response) {
|
||||||
|
return reqOrResp;
|
||||||
|
}
|
||||||
|
// @ts-expect-error: resolved by wrangler build
|
||||||
|
const { handler } = await import("./server-functions/default/handler.mjs");
|
||||||
|
return handler(reqOrResp, env, ctx, request.signal);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
3
.open-next/cloudflare/cache-assets-manifest.sql
Normal file
3
.open-next/cloudflare/cache-assets-manifest.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS tags (tag TEXT NOT NULL, path TEXT NOT NULL, UNIQUE(tag, path) ON CONFLICT REPLACE);
|
||||||
|
CREATE TABLE IF NOT EXISTS revalidations (tag TEXT NOT NULL, revalidatedAt INTEGER NOT NULL, UNIQUE(tag) ON CONFLICT REPLACE);
|
||||||
|
INSERT INTO tags (tag, path) VALUES ("15aOepE5x4uUwOLZRAN9M/_N_T_/layout", "15aOepE5x4uUwOLZRAN9M/_not-found"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/_not-found/layout", "15aOepE5x4uUwOLZRAN9M/_not-found"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/_not-found/page", "15aOepE5x4uUwOLZRAN9M/_not-found"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/_not-found", "15aOepE5x4uUwOLZRAN9M/_not-found"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/layout", "15aOepE5x4uUwOLZRAN9M/appointment"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/appointment/layout", "15aOepE5x4uUwOLZRAN9M/appointment"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/appointment/page", "15aOepE5x4uUwOLZRAN9M/appointment"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/appointment", "15aOepE5x4uUwOLZRAN9M/appointment"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/layout", "15aOepE5x4uUwOLZRAN9M/contact"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/contact/layout", "15aOepE5x4uUwOLZRAN9M/contact"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/contact/page", "15aOepE5x4uUwOLZRAN9M/contact"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/contact", "15aOepE5x4uUwOLZRAN9M/contact"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/layout", "15aOepE5x4uUwOLZRAN9M/favicon.ico"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/favicon.ico/layout", "15aOepE5x4uUwOLZRAN9M/favicon.ico"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/favicon.ico/route", "15aOepE5x4uUwOLZRAN9M/favicon.ico"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/favicon.ico", "15aOepE5x4uUwOLZRAN9M/favicon.ico"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/layout", "15aOepE5x4uUwOLZRAN9M/index"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/page", "15aOepE5x4uUwOLZRAN9M/index"), ("15aOepE5x4uUwOLZRAN9M/_N_T_/", "15aOepE5x4uUwOLZRAN9M/index");
|
||||||
659
.open-next/cloudflare/images.js
Normal file
659
.open-next/cloudflare/images.js
Normal file
|
|
@ -0,0 +1,659 @@
|
||||||
|
// <define:__IMAGES_DEVICE_SIZES__>
|
||||||
|
var define_IMAGES_DEVICE_SIZES_default = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
|
||||||
|
|
||||||
|
// <define:__IMAGES_FORMATS__>
|
||||||
|
var define_IMAGES_FORMATS_default = ["image/webp"];
|
||||||
|
|
||||||
|
// <define:__IMAGES_IMAGE_SIZES__>
|
||||||
|
var define_IMAGES_IMAGE_SIZES_default = [16, 32, 48, 64, 96, 128, 256, 384];
|
||||||
|
|
||||||
|
// <define:__IMAGES_LOCAL_PATTERNS__>
|
||||||
|
var define_IMAGES_LOCAL_PATTERNS_default = [{ pathname: "^(?:\\/(?!\\.{1,2}(?:\\/|$))(?:(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$)).)*?))$" }];
|
||||||
|
|
||||||
|
// <define:__IMAGES_QUALITIES__>
|
||||||
|
var define_IMAGES_QUALITIES_default = [75];
|
||||||
|
|
||||||
|
// <define:__IMAGES_REMOTE_PATTERNS__>
|
||||||
|
var define_IMAGES_REMOTE_PATTERNS_default = [];
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/utils/error.js
|
||||||
|
function isOpenNextError(e) {
|
||||||
|
try {
|
||||||
|
return "__openNextInternal" in e;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/aws/dist/adapters/logger.js
|
||||||
|
function debug(...args) {
|
||||||
|
if (globalThis.openNextDebug) {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function warn(...args) {
|
||||||
|
console.warn(...args);
|
||||||
|
}
|
||||||
|
var DOWNPLAYED_ERROR_LOGS = [
|
||||||
|
{
|
||||||
|
clientName: "S3Client",
|
||||||
|
commandName: "GetObjectCommand",
|
||||||
|
errorName: "NoSuchKey"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var isDownplayedErrorLog = (errorLog) => DOWNPLAYED_ERROR_LOGS.some((downplayedInput) => downplayedInput.clientName === errorLog?.clientName && downplayedInput.commandName === errorLog?.commandName && (downplayedInput.errorName === errorLog?.error?.name || downplayedInput.errorName === errorLog?.error?.Code));
|
||||||
|
function error(...args) {
|
||||||
|
if (args.some((arg) => isDownplayedErrorLog(arg))) {
|
||||||
|
return debug(...args);
|
||||||
|
}
|
||||||
|
if (args.some((arg) => isOpenNextError(arg))) {
|
||||||
|
const error2 = args.find((arg) => isOpenNextError(arg));
|
||||||
|
if (error2.logLevel < getOpenNextErrorLogLevel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 0) {
|
||||||
|
return console.log(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
if (error2.logLevel === 1) {
|
||||||
|
return warn(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg));
|
||||||
|
}
|
||||||
|
return console.error(...args);
|
||||||
|
}
|
||||||
|
console.error(...args);
|
||||||
|
}
|
||||||
|
function getOpenNextErrorLogLevel() {
|
||||||
|
const strLevel = process.env.OPEN_NEXT_ERROR_LOG_LEVEL ?? "1";
|
||||||
|
switch (strLevel.toLowerCase()) {
|
||||||
|
case "debug":
|
||||||
|
case "0":
|
||||||
|
return 0;
|
||||||
|
case "error":
|
||||||
|
case "2":
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/cli/templates/images.js
|
||||||
|
async function handleImageRequest(requestURL, requestHeaders, env) {
|
||||||
|
const parseResult = parseImageRequest(requestURL, requestHeaders);
|
||||||
|
if (!parseResult.ok) {
|
||||||
|
return new Response(parseResult.message, {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let imageResponse;
|
||||||
|
if (parseResult.url.startsWith("/")) {
|
||||||
|
if (env.ASSETS === void 0) {
|
||||||
|
error("env.ASSETS binding is not defined");
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: 404
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const absoluteURL = new URL(parseResult.url, requestURL);
|
||||||
|
imageResponse = await env.ASSETS.fetch(absoluteURL);
|
||||||
|
} else {
|
||||||
|
let fetchImageResult;
|
||||||
|
try {
|
||||||
|
fetchImageResult = await fetchWithRedirects(parseResult.url, 7e3, 3);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error("Failed to fetch image", { cause: e });
|
||||||
|
}
|
||||||
|
if (!fetchImageResult.ok) {
|
||||||
|
if (fetchImageResult.error === "timed_out") {
|
||||||
|
return new Response('"url" parameter is valid but upstream response timed out', {
|
||||||
|
status: 504
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (fetchImageResult.error === "too_many_redirects") {
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: 508
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw new Error("Failed to fetch image");
|
||||||
|
}
|
||||||
|
imageResponse = fetchImageResult.response;
|
||||||
|
}
|
||||||
|
if (!imageResponse.ok || imageResponse.body === null) {
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: imageResponse.status
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let immutable = false;
|
||||||
|
if (parseResult.static) {
|
||||||
|
immutable = true;
|
||||||
|
} else {
|
||||||
|
const cacheControlHeader = imageResponse.headers.get("Cache-Control");
|
||||||
|
if (cacheControlHeader !== null) {
|
||||||
|
immutable = cacheControlHeader.includes("immutable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const readHeaderResult = await readImageHeader(imageResponse);
|
||||||
|
if (readHeaderResult instanceof Response) {
|
||||||
|
return readHeaderResult;
|
||||||
|
}
|
||||||
|
const { contentType, imageStream } = readHeaderResult;
|
||||||
|
if (contentType === null) {
|
||||||
|
warn(`Failed to detect content type of "${parseResult.url}"`);
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (contentType === SVG) {
|
||||||
|
if (true) {
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const response2 = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable
|
||||||
|
});
|
||||||
|
return response2;
|
||||||
|
}
|
||||||
|
if (contentType === GIF) {
|
||||||
|
if (env.IMAGES === void 0) {
|
||||||
|
warn("env.IMAGES binding is not defined");
|
||||||
|
const response3 = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable
|
||||||
|
});
|
||||||
|
return response3;
|
||||||
|
}
|
||||||
|
const imageSource = env.IMAGES.input(imageStream);
|
||||||
|
const imageTransformationResult = await imageSource.transform({
|
||||||
|
width: parseResult.width,
|
||||||
|
fit: "scale-down"
|
||||||
|
}).output({
|
||||||
|
quality: parseResult.quality,
|
||||||
|
format: GIF
|
||||||
|
});
|
||||||
|
const outputImageStream = imageTransformationResult.image();
|
||||||
|
const response2 = createImageResponse(outputImageStream, GIF, {
|
||||||
|
immutable
|
||||||
|
});
|
||||||
|
return response2;
|
||||||
|
}
|
||||||
|
if (contentType === AVIF || contentType === WEBP || contentType === JPEG || contentType === PNG) {
|
||||||
|
if (env.IMAGES === void 0) {
|
||||||
|
warn("env.IMAGES binding is not defined");
|
||||||
|
const response3 = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable
|
||||||
|
});
|
||||||
|
return response3;
|
||||||
|
}
|
||||||
|
const outputFormat = parseResult.format ?? contentType;
|
||||||
|
const imageSource = env.IMAGES.input(imageStream);
|
||||||
|
const imageTransformationResult = await imageSource.transform({
|
||||||
|
width: parseResult.width,
|
||||||
|
fit: "scale-down"
|
||||||
|
}).output({
|
||||||
|
quality: parseResult.quality,
|
||||||
|
format: outputFormat
|
||||||
|
});
|
||||||
|
const outputImageStream = imageTransformationResult.image();
|
||||||
|
const response2 = createImageResponse(outputImageStream, outputFormat, {
|
||||||
|
immutable
|
||||||
|
});
|
||||||
|
return response2;
|
||||||
|
}
|
||||||
|
warn(`Image content type ${contentType} not supported`);
|
||||||
|
const response = createImageResponse(imageStream, contentType, {
|
||||||
|
immutable
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
async function handleCdnCgiImageRequest(requestURL, env) {
|
||||||
|
const parseResult = parseCdnCgiImageRequest(requestURL.pathname);
|
||||||
|
if (!parseResult.ok) {
|
||||||
|
return new Response(parseResult.message, {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let imageResponse;
|
||||||
|
if (parseResult.url.startsWith("/")) {
|
||||||
|
if (env.ASSETS === void 0) {
|
||||||
|
return new Response("env.ASSETS binding is not defined", {
|
||||||
|
status: 404
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const absoluteURL = new URL(parseResult.url, requestURL);
|
||||||
|
imageResponse = await env.ASSETS.fetch(absoluteURL);
|
||||||
|
} else {
|
||||||
|
imageResponse = await fetch(parseResult.url);
|
||||||
|
}
|
||||||
|
if (!imageResponse.ok || imageResponse.body === null) {
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: imageResponse.status
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const readHeaderResult = await readImageHeader(imageResponse);
|
||||||
|
if (readHeaderResult instanceof Response) {
|
||||||
|
return readHeaderResult;
|
||||||
|
}
|
||||||
|
const { contentType, imageStream } = readHeaderResult;
|
||||||
|
if (contentType === null || !SUPPORTED_CDN_CGI_INPUT_TYPES.has(contentType)) {
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (contentType === SVG && true) {
|
||||||
|
return new Response('"url" parameter is valid but image type is not allowed', {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Response(imageStream, {
|
||||||
|
headers: { "Content-Type": contentType }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function parseCdnCgiImageRequest(pathname) {
|
||||||
|
const match = pathname.match(/^\/cdn-cgi\/image\/(?<options>[^/]+)\/(?<url>.+)$/);
|
||||||
|
if (match === null || // Valid URLs have at least one option
|
||||||
|
!match.groups?.options || !match.groups?.url) {
|
||||||
|
return { ok: false, message: "Invalid /cdn-cgi/image/ URL format" };
|
||||||
|
}
|
||||||
|
const imageUrl = match.groups.url;
|
||||||
|
if (imageUrl.startsWith("/")) {
|
||||||
|
return { ok: false, message: '"url" parameter cannot be a protocol-relative URL (//)' };
|
||||||
|
}
|
||||||
|
let resolvedUrl;
|
||||||
|
if (imageUrl.match(/^https?:\/\//)) {
|
||||||
|
resolvedUrl = imageUrl;
|
||||||
|
} else {
|
||||||
|
resolvedUrl = `/${imageUrl}`;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
url: resolvedUrl,
|
||||||
|
static: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async function readImageHeader(imageResponse) {
|
||||||
|
const [contentTypeStream, imageStream] = imageResponse.body.tee();
|
||||||
|
const headerBytes = new Uint8Array(32);
|
||||||
|
const reader = contentTypeStream.getReader({ mode: "byob" });
|
||||||
|
const readResult = await reader.readAtLeast(32, headerBytes);
|
||||||
|
if (readResult.value === void 0) {
|
||||||
|
await imageResponse.body.cancel();
|
||||||
|
return new Response('"url" parameter is valid but upstream response is invalid', {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const contentType = detectImageContentType(readResult.value);
|
||||||
|
return { contentType, imageStream };
|
||||||
|
}
|
||||||
|
async function fetchWithRedirects(url, timeoutMS, maxRedirectCount) {
|
||||||
|
let response;
|
||||||
|
try {
|
||||||
|
response = await fetch(url, {
|
||||||
|
signal: AbortSignal.timeout(timeoutMS),
|
||||||
|
redirect: "manual"
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error && e.name === "TimeoutError") {
|
||||||
|
const result2 = {
|
||||||
|
ok: false,
|
||||||
|
error: "timed_out"
|
||||||
|
};
|
||||||
|
return result2;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
if (redirectResponseStatuses.includes(response.status)) {
|
||||||
|
const locationHeader = response.headers.get("Location");
|
||||||
|
if (locationHeader !== null) {
|
||||||
|
if (maxRedirectCount < 1) {
|
||||||
|
const result3 = {
|
||||||
|
ok: false,
|
||||||
|
error: "too_many_redirects"
|
||||||
|
};
|
||||||
|
return result3;
|
||||||
|
}
|
||||||
|
let redirectTarget;
|
||||||
|
if (locationHeader.startsWith("/")) {
|
||||||
|
redirectTarget = new URL(locationHeader, url).href;
|
||||||
|
} else {
|
||||||
|
redirectTarget = locationHeader;
|
||||||
|
}
|
||||||
|
const result2 = await fetchWithRedirects(redirectTarget, timeoutMS, maxRedirectCount - 1);
|
||||||
|
return result2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = {
|
||||||
|
ok: true,
|
||||||
|
response
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
var redirectResponseStatuses = [301, 302, 303, 307, 308];
|
||||||
|
function createImageResponse(image, contentType, imageResponseFlags) {
|
||||||
|
const response = new Response(image, {
|
||||||
|
headers: {
|
||||||
|
Vary: "Accept",
|
||||||
|
"Content-Type": contentType,
|
||||||
|
"Content-Disposition": "attachment",
|
||||||
|
"Content-Security-Policy": "script-src 'none'; frame-src 'none'; sandbox;"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (imageResponseFlags.immutable) {
|
||||||
|
response.headers.set("Cache-Control", "public, max-age=315360000, immutable");
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
function parseImageRequest(requestURL, requestHeaders) {
|
||||||
|
const formats = define_IMAGES_FORMATS_default;
|
||||||
|
const parsedUrlOrError = validateUrlQueryParameter(requestURL);
|
||||||
|
if (!("url" in parsedUrlOrError)) {
|
||||||
|
return parsedUrlOrError;
|
||||||
|
}
|
||||||
|
const widthOrError = validateWidthQueryParameter(requestURL);
|
||||||
|
if (typeof widthOrError !== "number") {
|
||||||
|
return widthOrError;
|
||||||
|
}
|
||||||
|
const qualityOrError = validateQualityQueryParameter(requestURL);
|
||||||
|
if (typeof qualityOrError !== "number") {
|
||||||
|
return qualityOrError;
|
||||||
|
}
|
||||||
|
const acceptHeader = requestHeaders.get("Accept") ?? "";
|
||||||
|
let format = null;
|
||||||
|
for (const allowedFormat of formats) {
|
||||||
|
if (acceptHeader.includes(allowedFormat)) {
|
||||||
|
format = allowedFormat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const result = {
|
||||||
|
ok: true,
|
||||||
|
url: parsedUrlOrError.url,
|
||||||
|
width: widthOrError,
|
||||||
|
quality: qualityOrError,
|
||||||
|
format,
|
||||||
|
static: parsedUrlOrError.static
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function validateUrlQueryParameter(requestURL) {
|
||||||
|
const urls = requestURL.searchParams.getAll("url");
|
||||||
|
if (urls.length < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is required'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (urls.length > 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter cannot be an array'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const url = urls[0];
|
||||||
|
if (url.length > 3072) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is too long'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (url.startsWith("//")) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter cannot be a protocol-relative URL (//)'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (url.startsWith("/")) {
|
||||||
|
const staticAsset = url.startsWith(`${__NEXT_BASE_PATH__ || ""}/_next/static/media`);
|
||||||
|
const pathname = getPathnameFromRelativeURL(url);
|
||||||
|
if (/\/_next\/image($|\/)/.test(decodeURIComponent(pathname))) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter cannot be recursive'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!staticAsset) {
|
||||||
|
if (!hasLocalMatch(define_IMAGES_LOCAL_PATTERNS_default, url)) {
|
||||||
|
const result = { ok: false, message: '"url" parameter is not allowed' };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { url, static: staticAsset };
|
||||||
|
}
|
||||||
|
let parsedURL;
|
||||||
|
try {
|
||||||
|
parsedURL = new URL(url);
|
||||||
|
} catch {
|
||||||
|
const result = { ok: false, message: '"url" parameter is invalid' };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const validProtocols = ["http:", "https:"];
|
||||||
|
if (!validProtocols.includes(parsedURL.protocol)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is invalid'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!hasRemoteMatch(define_IMAGES_REMOTE_PATTERNS_default, parsedURL)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"url" parameter is not allowed'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return { url: parsedURL.href, static: false };
|
||||||
|
}
|
||||||
|
function validateWidthQueryParameter(requestURL) {
|
||||||
|
const widthQueryValues = requestURL.searchParams.getAll("w");
|
||||||
|
if (widthQueryValues.length < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) is required'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (widthQueryValues.length > 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) cannot be an array'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const widthQueryValue = widthQueryValues[0];
|
||||||
|
if (!/^[0-9]+$/.test(widthQueryValue)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) must be an integer greater than 0'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const width = parseInt(widthQueryValue, 10);
|
||||||
|
if (width <= 0 || isNaN(width)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"w" parameter (width) must be an integer greater than 0'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const sizeValid = define_IMAGES_DEVICE_SIZES_default.includes(width) || define_IMAGES_IMAGE_SIZES_default.includes(width);
|
||||||
|
if (!sizeValid) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: `"w" parameter (width) of ${width} is not allowed`
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
function validateQualityQueryParameter(requestURL) {
|
||||||
|
const qualityQueryValues = requestURL.searchParams.getAll("q");
|
||||||
|
if (qualityQueryValues.length < 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) is required'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (qualityQueryValues.length > 1) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) cannot be an array'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const qualityQueryValue = qualityQueryValues[0];
|
||||||
|
if (!/^[0-9]+$/.test(qualityQueryValue)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) must be an integer between 1 and 100'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const quality = parseInt(qualityQueryValue, 10);
|
||||||
|
if (isNaN(quality) || quality < 1 || quality > 100) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: '"q" parameter (quality) must be an integer between 1 and 100'
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!define_IMAGES_QUALITIES_default.includes(quality)) {
|
||||||
|
const result = {
|
||||||
|
ok: false,
|
||||||
|
message: `"q" parameter (quality) of ${quality} is not allowed`
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return quality;
|
||||||
|
}
|
||||||
|
function getPathnameFromRelativeURL(relativeURL) {
|
||||||
|
return relativeURL.split("?")[0];
|
||||||
|
}
|
||||||
|
function hasLocalMatch(localPatterns, relativeURL) {
|
||||||
|
const parseRelativeURLResult = parseRelativeURL(relativeURL);
|
||||||
|
for (const localPattern of localPatterns) {
|
||||||
|
const matched = matchLocalPattern(localPattern, parseRelativeURLResult);
|
||||||
|
if (matched) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function parseRelativeURL(relativeURL) {
|
||||||
|
if (!relativeURL.includes("?")) {
|
||||||
|
const result2 = {
|
||||||
|
pathname: relativeURL,
|
||||||
|
search: ""
|
||||||
|
};
|
||||||
|
return result2;
|
||||||
|
}
|
||||||
|
const parts = relativeURL.split("?");
|
||||||
|
const pathname = parts[0];
|
||||||
|
const search = "?" + parts.slice(1).join("?");
|
||||||
|
const result = {
|
||||||
|
pathname,
|
||||||
|
search
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function matchLocalPattern(pattern, url) {
|
||||||
|
if (pattern.search !== void 0 && pattern.search !== url.search) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return new RegExp(pattern.pathname).test(url.pathname);
|
||||||
|
}
|
||||||
|
function hasRemoteMatch(remotePatterns, url) {
|
||||||
|
for (const remotePattern of remotePatterns) {
|
||||||
|
const matched = matchRemotePattern(remotePattern, url);
|
||||||
|
if (matched) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function matchRemotePattern(pattern, url) {
|
||||||
|
if (pattern.protocol !== void 0 && pattern.protocol.replace(/:$/, "") !== url.protocol.replace(/:$/, "")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.port !== void 0 && pattern.port !== url.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.hostname === void 0 || !new RegExp(pattern.hostname).test(url.hostname)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.search !== void 0 && pattern.search !== url.search) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return new RegExp(pattern.pathname).test(url.pathname);
|
||||||
|
}
|
||||||
|
var AVIF = "image/avif";
|
||||||
|
var WEBP = "image/webp";
|
||||||
|
var PNG = "image/png";
|
||||||
|
var JPEG = "image/jpeg";
|
||||||
|
var JXL = "image/jxl";
|
||||||
|
var JP2 = "image/jp2";
|
||||||
|
var HEIC = "image/heic";
|
||||||
|
var GIF = "image/gif";
|
||||||
|
var SVG = "image/svg+xml";
|
||||||
|
var ICO = "image/x-icon";
|
||||||
|
var ICNS = "image/x-icns";
|
||||||
|
var TIFF = "image/tiff";
|
||||||
|
var BMP = "image/bmp";
|
||||||
|
var SUPPORTED_CDN_CGI_INPUT_TYPES = /* @__PURE__ */ new Set([JPEG, PNG, GIF, WEBP, SVG, HEIC]);
|
||||||
|
function detectImageContentType(buffer) {
|
||||||
|
if ([255, 216, 255].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JPEG;
|
||||||
|
}
|
||||||
|
if ([137, 80, 78, 71, 13, 10, 26, 10].every((b, i) => buffer[i] === b)) {
|
||||||
|
return PNG;
|
||||||
|
}
|
||||||
|
if ([71, 73, 70, 56].every((b, i) => buffer[i] === b)) {
|
||||||
|
return GIF;
|
||||||
|
}
|
||||||
|
if ([82, 73, 70, 70, 0, 0, 0, 0, 87, 69, 66, 80].every((b, i) => !b || buffer[i] === b)) {
|
||||||
|
return WEBP;
|
||||||
|
}
|
||||||
|
if ([60, 63, 120, 109, 108].every((b, i) => buffer[i] === b)) {
|
||||||
|
return SVG;
|
||||||
|
}
|
||||||
|
if ([60, 115, 118, 103].every((b, i) => buffer[i] === b)) {
|
||||||
|
return SVG;
|
||||||
|
}
|
||||||
|
if ([0, 0, 0, 0, 102, 116, 121, 112, 97, 118, 105, 102].every((b, i) => !b || buffer[i] === b)) {
|
||||||
|
return AVIF;
|
||||||
|
}
|
||||||
|
if ([0, 0, 1, 0].every((b, i) => buffer[i] === b)) {
|
||||||
|
return ICO;
|
||||||
|
}
|
||||||
|
if ([105, 99, 110, 115].every((b, i) => buffer[i] === b)) {
|
||||||
|
return ICNS;
|
||||||
|
}
|
||||||
|
if ([73, 73, 42, 0].every((b, i) => buffer[i] === b)) {
|
||||||
|
return TIFF;
|
||||||
|
}
|
||||||
|
if ([66, 77].every((b, i) => buffer[i] === b)) {
|
||||||
|
return BMP;
|
||||||
|
}
|
||||||
|
if ([255, 10].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JXL;
|
||||||
|
}
|
||||||
|
if ([0, 0, 0, 12, 74, 88, 76, 32, 13, 10, 135, 10].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JXL;
|
||||||
|
}
|
||||||
|
if ([0, 0, 0, 0, 102, 116, 121, 112, 104, 101, 105, 99].every((b, i) => !b || buffer[i] === b)) {
|
||||||
|
return HEIC;
|
||||||
|
}
|
||||||
|
if ([0, 0, 0, 12, 106, 80, 32, 32, 13, 10, 135, 10].every((b, i) => buffer[i] === b)) {
|
||||||
|
return JP2;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
detectImageContentType,
|
||||||
|
handleCdnCgiImageRequest,
|
||||||
|
handleImageRequest,
|
||||||
|
matchLocalPattern,
|
||||||
|
matchRemotePattern,
|
||||||
|
parseCdnCgiImageRequest
|
||||||
|
};
|
||||||
88
.open-next/cloudflare/init.js
Normal file
88
.open-next/cloudflare/init.js
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { AsyncLocalStorage } from "node:async_hooks";
|
||||||
|
import process from "node:process";
|
||||||
|
import stream from "node:stream";
|
||||||
|
import * as nextEnvVars from "./next-env.mjs";
|
||||||
|
const cloudflareContextALS = new AsyncLocalStorage();
|
||||||
|
Object.defineProperty(globalThis, Symbol.for("__cloudflare-context__"), {
|
||||||
|
get() {
|
||||||
|
return cloudflareContextALS.getStore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
async function runWithCloudflareRequestContext(request, env, ctx, handler) {
|
||||||
|
init(request, env);
|
||||||
|
return cloudflareContextALS.run({ env, ctx, cf: request.cf }, handler);
|
||||||
|
}
|
||||||
|
let initialized = false;
|
||||||
|
function init(request, env) {
|
||||||
|
if (initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
const url = new URL(request.url);
|
||||||
|
initRuntime();
|
||||||
|
populateProcessEnv(url, env);
|
||||||
|
}
|
||||||
|
function initRuntime() {
|
||||||
|
Object.assign(process, { version: process.version || "v22.14.0" });
|
||||||
|
Object.assign(process.versions, { node: "22.14.0", ...process.versions });
|
||||||
|
globalThis.__dirname ??= "";
|
||||||
|
globalThis.__filename ??= "";
|
||||||
|
import.meta.url ??= "file:///worker.js";
|
||||||
|
const __original_fetch = globalThis.fetch;
|
||||||
|
globalThis.fetch = (input, init2) => {
|
||||||
|
if (init2) {
|
||||||
|
delete init2.cache;
|
||||||
|
}
|
||||||
|
return __original_fetch(input, init2);
|
||||||
|
};
|
||||||
|
const CustomRequest = class extends globalThis.Request {
|
||||||
|
constructor(input, init2) {
|
||||||
|
if (init2) {
|
||||||
|
delete init2.cache;
|
||||||
|
Object.defineProperty(init2, "body", {
|
||||||
|
// @ts-ignore
|
||||||
|
value: init2.body instanceof stream.Readable ? ReadableStream.from(init2.body) : init2.body
|
||||||
|
});
|
||||||
|
}
|
||||||
|
super(input, init2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Object.assign(globalThis, {
|
||||||
|
Request: CustomRequest,
|
||||||
|
__BUILD_TIMESTAMP_MS__: 1773771192154,
|
||||||
|
__NEXT_BASE_PATH__: "",
|
||||||
|
__ASSETS_RUN_WORKER_FIRST__: false,
|
||||||
|
__TRAILING_SLASH__: false,
|
||||||
|
// The external middleware will use the convertTo function of the `edge` converter
|
||||||
|
// by default it will try to fetch the request, but since we are running everything in the same worker
|
||||||
|
// we need to use the request as is.
|
||||||
|
__dangerous_ON_edge_converter_returns_request: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function populateProcessEnv(url, env) {
|
||||||
|
for (const [key, value] of Object.entries(env)) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
process.env[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mode = env.NEXTJS_ENV ?? "production";
|
||||||
|
if (nextEnvVars[mode]) {
|
||||||
|
for (const key in nextEnvVars[mode]) {
|
||||||
|
process.env[key] ??= nextEnvVars[mode][key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.env.OPEN_NEXT_ORIGIN = JSON.stringify({
|
||||||
|
default: {
|
||||||
|
host: url.hostname,
|
||||||
|
protocol: url.protocol.slice(0, -1),
|
||||||
|
port: url.port
|
||||||
|
}
|
||||||
|
});
|
||||||
|
process.env.__NEXT_PRIVATE_ORIGIN = url.origin;
|
||||||
|
if ("") {
|
||||||
|
process.env.DEPLOYMENT_ID = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
runWithCloudflareRequestContext
|
||||||
|
};
|
||||||
3
.open-next/cloudflare/next-env.mjs
Normal file
3
.open-next/cloudflare/next-env.mjs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export const production = {};
|
||||||
|
export const development = {};
|
||||||
|
export const test = {};
|
||||||
36
.open-next/cloudflare/skew-protection.js
Normal file
36
.open-next/cloudflare/skew-protection.js
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import process from "node:process";
|
||||||
|
const DEPLOYMENT_MAPPING_ENV_NAME = "CF_DEPLOYMENT_MAPPING";
|
||||||
|
const CURRENT_VERSION_ID = "current";
|
||||||
|
let deploymentMapping;
|
||||||
|
function maybeGetSkewProtectionResponse(request) {
|
||||||
|
if (false) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
if (url.hostname === "localhost" || url.hostname.endsWith(".workers.dev")) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const requestDeploymentId = request.headers.get("x-deployment-id") ?? url.searchParams.get("dpl");
|
||||||
|
if (!requestDeploymentId || requestDeploymentId === process.env.DEPLOYMENT_ID) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
deploymentMapping ??= process.env[DEPLOYMENT_MAPPING_ENV_NAME] ? JSON.parse(process.env[DEPLOYMENT_MAPPING_ENV_NAME]) : {};
|
||||||
|
if (!(requestDeploymentId in deploymentMapping)) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const version = deploymentMapping[requestDeploymentId];
|
||||||
|
if (!version || version === CURRENT_VERSION_ID) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const versionDomain = version.split("-")[0];
|
||||||
|
const hostname = `${versionDomain}-${process.env.CF_WORKER_NAME}.${process.env.CF_PREVIEW_DOMAIN}.workers.dev`;
|
||||||
|
url.hostname = hostname;
|
||||||
|
const requestToOlderDeployment = new Request(url, request);
|
||||||
|
const headers = new Headers(request.headers);
|
||||||
|
headers.delete("origin");
|
||||||
|
return fetch(requestToOlderDeployment, { headers });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
CURRENT_VERSION_ID,
|
||||||
|
DEPLOYMENT_MAPPING_ENV_NAME,
|
||||||
|
maybeGetSkewProtectionResponse
|
||||||
|
};
|
||||||
1
.open-next/dynamodb-provider/dynamodb-cache.json
Normal file
1
.open-next/dynamodb-provider/dynamodb-cache.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
[{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/_not-found"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/_not-found/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/_not-found"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/_not-found/page"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/_not-found"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/_not-found"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/_not-found"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/appointment"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/appointment/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/appointment"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/appointment/page"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/appointment"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/appointment"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/appointment"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/contact"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/contact/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/contact"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/contact/page"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/contact"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/contact"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/contact"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/favicon.ico"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/favicon.ico/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/favicon.ico"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/favicon.ico/route"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/favicon.ico"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/favicon.ico"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/favicon.ico"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/layout"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/index"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/page"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/index"},"revalidatedAt":{"N":"1"}},{"tag":{"S":"15aOepE5x4uUwOLZRAN9M/_N_T_/"},"path":{"S":"15aOepE5x4uUwOLZRAN9M/index"},"revalidatedAt":{"N":"1"}}]
|
||||||
217
.open-next/dynamodb-provider/open-next.config.mjs
Normal file
217
.open-next/dynamodb-provider/open-next.config.mjs
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
import { createRequire as topLevelCreateRequire } from 'module';const require = topLevelCreateRequire(import.meta.url);import bannerUrl from 'url';const __dirname = bannerUrl.fileURLToPath(new URL('.', import.meta.url));
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/cloudflare-context.js
|
||||||
|
var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
|
||||||
|
function getCloudflareContext(options = { async: false }) {
|
||||||
|
return options.async ? getCloudflareContextAsync() : getCloudflareContextSync();
|
||||||
|
}
|
||||||
|
function getCloudflareContextFromGlobalScope() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global[cloudflareContextSymbol];
|
||||||
|
}
|
||||||
|
function inSSG() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global.__NEXT_DATA__?.nextExport === true;
|
||||||
|
}
|
||||||
|
function getCloudflareContextSync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
if (inSSG()) {
|
||||||
|
throw new Error(`
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called in sync mode in either a static route or at the top level of a non-static one, both cases are not allowed but can be solved by either:
|
||||||
|
- make sure that the call is not at the top level and that the route is not static
|
||||||
|
- call \`getCloudflareContext({async: true})\` to use the \`async\` mode
|
||||||
|
- avoid calling \`getCloudflareContext\` in the route
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
async function getCloudflareContextAsync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
const inNodejsRuntime = process.env.NEXT_RUNTIME === "nodejs";
|
||||||
|
if (inNodejsRuntime || inSSG()) {
|
||||||
|
const cloudflareContext2 = await getCloudflareContextFromWrangler();
|
||||||
|
addCloudflareContextToNodejsGlobal(cloudflareContext2);
|
||||||
|
return cloudflareContext2;
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
function addCloudflareContextToNodejsGlobal(cloudflareContext) {
|
||||||
|
const global = globalThis;
|
||||||
|
global[cloudflareContextSymbol] = cloudflareContext;
|
||||||
|
}
|
||||||
|
async function getCloudflareContextFromWrangler(options) {
|
||||||
|
const { getPlatformProxy } = await import(
|
||||||
|
/* webpackIgnore: true */
|
||||||
|
`${"__wrangler".replaceAll("_", "")}`
|
||||||
|
);
|
||||||
|
const environment = options?.environment ?? process.env.NEXT_DEV_WRANGLER_ENV;
|
||||||
|
const { env, cf, ctx } = await getPlatformProxy({
|
||||||
|
...options,
|
||||||
|
// The `env` passed to the fetch handler does not contain variables from `.env*` files.
|
||||||
|
// because we invoke wrangler with `CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV`=`"false"`.
|
||||||
|
// Initializing `envFiles` with an empty list is the equivalent for this API call.
|
||||||
|
envFiles: [],
|
||||||
|
environment
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
env,
|
||||||
|
cf,
|
||||||
|
ctx
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var initOpenNextCloudflareForDevErrorMsg = `
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called without having called \`initOpenNextCloudflareForDev\` from the Next.js config file.
|
||||||
|
You should update your Next.js config file as shown below:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
// next.config.mjs
|
||||||
|
|
||||||
|
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
|
||||||
|
|
||||||
|
initOpenNextCloudflareForDev();
|
||||||
|
|
||||||
|
const nextConfig = { ... };
|
||||||
|
export default nextConfig;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/overrides/asset-resolver/index.js
|
||||||
|
var resolver = {
|
||||||
|
name: "cloudflare-asset-resolver",
|
||||||
|
async maybeGetAssetResult(event) {
|
||||||
|
const { ASSETS } = getCloudflareContext().env;
|
||||||
|
if (!ASSETS || !isUserWorkerFirst(globalThis.__ASSETS_RUN_WORKER_FIRST__, event.rawPath)) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const { method, headers } = event;
|
||||||
|
if (method !== "GET" && method != "HEAD") {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const url = new URL(event.rawPath, "https://assets.local");
|
||||||
|
const response = await ASSETS.fetch(url, {
|
||||||
|
headers,
|
||||||
|
method
|
||||||
|
});
|
||||||
|
if (response.status === 404) {
|
||||||
|
await response.body?.cancel();
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: "core",
|
||||||
|
statusCode: response.status,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
body: getResponseBody(method, response),
|
||||||
|
isBase64Encoded: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getResponseBody(method, response) {
|
||||||
|
if (method === "HEAD") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return response.body || new ReadableStream();
|
||||||
|
}
|
||||||
|
function isUserWorkerFirst(runWorkerFirst, pathname) {
|
||||||
|
if (!Array.isArray(runWorkerFirst)) {
|
||||||
|
return runWorkerFirst ?? false;
|
||||||
|
}
|
||||||
|
let hasPositiveMatch = false;
|
||||||
|
for (let rule of runWorkerFirst) {
|
||||||
|
let isPositiveRule = true;
|
||||||
|
if (rule.startsWith("!")) {
|
||||||
|
rule = rule.slice(1);
|
||||||
|
isPositiveRule = false;
|
||||||
|
} else if (hasPositiveMatch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const match = new RegExp(`^${rule.replace(/([[\]().*+?^$|{}\\])/g, "\\$1").replace("\\*", ".*")}$`).test(pathname);
|
||||||
|
if (match) {
|
||||||
|
if (isPositiveRule) {
|
||||||
|
hasPositiveMatch = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasPositiveMatch;
|
||||||
|
}
|
||||||
|
var asset_resolver_default = resolver;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/config.js
|
||||||
|
function defineCloudflareConfig(config = {}) {
|
||||||
|
const { incrementalCache, tagCache, queue, cachePurge, enableCacheInterception = false, routePreloadingBehavior = "none" } = config;
|
||||||
|
return {
|
||||||
|
default: {
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-node",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue),
|
||||||
|
cdnInvalidation: resolveCdnInvalidation(cachePurge)
|
||||||
|
},
|
||||||
|
routePreloadingBehavior
|
||||||
|
},
|
||||||
|
// node:crypto is used to compute cache keys
|
||||||
|
edgeExternals: ["node:crypto"],
|
||||||
|
cloudflare: {
|
||||||
|
useWorkerdCondition: true
|
||||||
|
},
|
||||||
|
dangerous: {
|
||||||
|
enableCacheInterception
|
||||||
|
},
|
||||||
|
middleware: {
|
||||||
|
external: true,
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-edge",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue)
|
||||||
|
},
|
||||||
|
assetResolver: () => asset_resolver_default
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function resolveIncrementalCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveTagCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveQueue(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveCdnInvalidation(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open-next.config.ts
|
||||||
|
var open_next_config_default = defineCloudflareConfig({});
|
||||||
|
export {
|
||||||
|
open_next_config_default as default
|
||||||
|
};
|
||||||
2660
.open-next/middleware/handler.mjs
Normal file
2660
.open-next/middleware/handler.mjs
Normal file
File diff suppressed because one or more lines are too long
215
.open-next/middleware/open-next.config.mjs
Normal file
215
.open-next/middleware/open-next.config.mjs
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/cloudflare-context.js
|
||||||
|
var cloudflareContextSymbol = Symbol.for("__cloudflare-context__");
|
||||||
|
function getCloudflareContext(options = { async: false }) {
|
||||||
|
return options.async ? getCloudflareContextAsync() : getCloudflareContextSync();
|
||||||
|
}
|
||||||
|
function getCloudflareContextFromGlobalScope() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global[cloudflareContextSymbol];
|
||||||
|
}
|
||||||
|
function inSSG() {
|
||||||
|
const global = globalThis;
|
||||||
|
return global.__NEXT_DATA__?.nextExport === true;
|
||||||
|
}
|
||||||
|
function getCloudflareContextSync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
if (inSSG()) {
|
||||||
|
throw new Error(`
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called in sync mode in either a static route or at the top level of a non-static one, both cases are not allowed but can be solved by either:
|
||||||
|
- make sure that the call is not at the top level and that the route is not static
|
||||||
|
- call \`getCloudflareContext({async: true})\` to use the \`async\` mode
|
||||||
|
- avoid calling \`getCloudflareContext\` in the route
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
async function getCloudflareContextAsync() {
|
||||||
|
const cloudflareContext = getCloudflareContextFromGlobalScope();
|
||||||
|
if (cloudflareContext) {
|
||||||
|
return cloudflareContext;
|
||||||
|
}
|
||||||
|
const inNodejsRuntime = process.env.NEXT_RUNTIME === "nodejs";
|
||||||
|
if (inNodejsRuntime || inSSG()) {
|
||||||
|
const cloudflareContext2 = await getCloudflareContextFromWrangler();
|
||||||
|
addCloudflareContextToNodejsGlobal(cloudflareContext2);
|
||||||
|
return cloudflareContext2;
|
||||||
|
}
|
||||||
|
throw new Error(initOpenNextCloudflareForDevErrorMsg);
|
||||||
|
}
|
||||||
|
function addCloudflareContextToNodejsGlobal(cloudflareContext) {
|
||||||
|
const global = globalThis;
|
||||||
|
global[cloudflareContextSymbol] = cloudflareContext;
|
||||||
|
}
|
||||||
|
async function getCloudflareContextFromWrangler(options) {
|
||||||
|
const { getPlatformProxy } = await import(
|
||||||
|
/* webpackIgnore: true */
|
||||||
|
`${"__wrangler".replaceAll("_", "")}`
|
||||||
|
);
|
||||||
|
const environment = options?.environment ?? process.env.NEXT_DEV_WRANGLER_ENV;
|
||||||
|
const { env, cf, ctx } = await getPlatformProxy({
|
||||||
|
...options,
|
||||||
|
// The `env` passed to the fetch handler does not contain variables from `.env*` files.
|
||||||
|
// because we invoke wrangler with `CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV`=`"false"`.
|
||||||
|
// Initializing `envFiles` with an empty list is the equivalent for this API call.
|
||||||
|
envFiles: [],
|
||||||
|
environment
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
env,
|
||||||
|
cf,
|
||||||
|
ctx
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var initOpenNextCloudflareForDevErrorMsg = `
|
||||||
|
|
||||||
|
ERROR: \`getCloudflareContext\` has been called without having called \`initOpenNextCloudflareForDev\` from the Next.js config file.
|
||||||
|
You should update your Next.js config file as shown below:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
// next.config.mjs
|
||||||
|
|
||||||
|
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
|
||||||
|
|
||||||
|
initOpenNextCloudflareForDev();
|
||||||
|
|
||||||
|
const nextConfig = { ... };
|
||||||
|
export default nextConfig;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/overrides/asset-resolver/index.js
|
||||||
|
var resolver = {
|
||||||
|
name: "cloudflare-asset-resolver",
|
||||||
|
async maybeGetAssetResult(event) {
|
||||||
|
const { ASSETS } = getCloudflareContext().env;
|
||||||
|
if (!ASSETS || !isUserWorkerFirst(globalThis.__ASSETS_RUN_WORKER_FIRST__, event.rawPath)) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const { method, headers } = event;
|
||||||
|
if (method !== "GET" && method != "HEAD") {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
const url = new URL(event.rawPath, "https://assets.local");
|
||||||
|
const response = await ASSETS.fetch(url, {
|
||||||
|
headers,
|
||||||
|
method
|
||||||
|
});
|
||||||
|
if (response.status === 404) {
|
||||||
|
await response.body?.cancel();
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: "core",
|
||||||
|
statusCode: response.status,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
body: getResponseBody(method, response),
|
||||||
|
isBase64Encoded: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getResponseBody(method, response) {
|
||||||
|
if (method === "HEAD") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return response.body || new ReadableStream();
|
||||||
|
}
|
||||||
|
function isUserWorkerFirst(runWorkerFirst, pathname) {
|
||||||
|
if (!Array.isArray(runWorkerFirst)) {
|
||||||
|
return runWorkerFirst ?? false;
|
||||||
|
}
|
||||||
|
let hasPositiveMatch = false;
|
||||||
|
for (let rule of runWorkerFirst) {
|
||||||
|
let isPositiveRule = true;
|
||||||
|
if (rule.startsWith("!")) {
|
||||||
|
rule = rule.slice(1);
|
||||||
|
isPositiveRule = false;
|
||||||
|
} else if (hasPositiveMatch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const match = new RegExp(`^${rule.replace(/([[\]().*+?^$|{}\\])/g, "\\$1").replace("\\*", ".*")}$`).test(pathname);
|
||||||
|
if (match) {
|
||||||
|
if (isPositiveRule) {
|
||||||
|
hasPositiveMatch = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasPositiveMatch;
|
||||||
|
}
|
||||||
|
var asset_resolver_default = resolver;
|
||||||
|
|
||||||
|
// node_modules/@opennextjs/cloudflare/dist/api/config.js
|
||||||
|
function defineCloudflareConfig(config = {}) {
|
||||||
|
const { incrementalCache, tagCache, queue, cachePurge, enableCacheInterception = false, routePreloadingBehavior = "none" } = config;
|
||||||
|
return {
|
||||||
|
default: {
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-node",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue),
|
||||||
|
cdnInvalidation: resolveCdnInvalidation(cachePurge)
|
||||||
|
},
|
||||||
|
routePreloadingBehavior
|
||||||
|
},
|
||||||
|
// node:crypto is used to compute cache keys
|
||||||
|
edgeExternals: ["node:crypto"],
|
||||||
|
cloudflare: {
|
||||||
|
useWorkerdCondition: true
|
||||||
|
},
|
||||||
|
dangerous: {
|
||||||
|
enableCacheInterception
|
||||||
|
},
|
||||||
|
middleware: {
|
||||||
|
external: true,
|
||||||
|
override: {
|
||||||
|
wrapper: "cloudflare-edge",
|
||||||
|
converter: "edge",
|
||||||
|
proxyExternalRequest: "fetch",
|
||||||
|
incrementalCache: resolveIncrementalCache(incrementalCache),
|
||||||
|
tagCache: resolveTagCache(tagCache),
|
||||||
|
queue: resolveQueue(queue)
|
||||||
|
},
|
||||||
|
assetResolver: () => asset_resolver_default
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function resolveIncrementalCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveTagCache(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveQueue(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
function resolveCdnInvalidation(value = "dummy") {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return typeof value === "function" ? value : () => value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open-next.config.ts
|
||||||
|
var open_next_config_default = defineCloudflareConfig({});
|
||||||
|
export {
|
||||||
|
open_next_config_default as default
|
||||||
|
};
|
||||||
1
.open-next/server-functions/default/.next/BUILD_ID
Normal file
1
.open-next/server-functions/default/.next/BUILD_ID
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
15aOepE5x4uUwOLZRAN9M
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"pages": {
|
||||||
|
"/_not-found/page": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/4bd1b696-c023c6e3521b1417.js",
|
||||||
|
"static/chunks/255-3991756713d22f05.js",
|
||||||
|
"static/chunks/main-app-f6d7a6830bbc9284.js",
|
||||||
|
"static/chunks/app/_not-found/page-9131b7abe6b98a6e.js"
|
||||||
|
],
|
||||||
|
"/layout": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/4bd1b696-c023c6e3521b1417.js",
|
||||||
|
"static/chunks/255-3991756713d22f05.js",
|
||||||
|
"static/chunks/main-app-f6d7a6830bbc9284.js",
|
||||||
|
"static/css/a3cf521d5fc8fd2d.css",
|
||||||
|
"static/chunks/366-6401b0800e501f14.js",
|
||||||
|
"static/chunks/619-ba102abea3e3d0e4.js",
|
||||||
|
"static/chunks/app/layout-9b75d8b5295058d6.js"
|
||||||
|
],
|
||||||
|
"/appointment/page": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/4bd1b696-c023c6e3521b1417.js",
|
||||||
|
"static/chunks/255-3991756713d22f05.js",
|
||||||
|
"static/chunks/main-app-f6d7a6830bbc9284.js",
|
||||||
|
"static/chunks/366-6401b0800e501f14.js",
|
||||||
|
"static/chunks/app/appointment/page-1023bd9f1d0c33d0.js"
|
||||||
|
],
|
||||||
|
"/contact/page": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/4bd1b696-c023c6e3521b1417.js",
|
||||||
|
"static/chunks/255-3991756713d22f05.js",
|
||||||
|
"static/chunks/main-app-f6d7a6830bbc9284.js",
|
||||||
|
"static/chunks/366-6401b0800e501f14.js",
|
||||||
|
"static/chunks/app/contact/page-1023bd9f1d0c33d0.js"
|
||||||
|
],
|
||||||
|
"/page": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/4bd1b696-c023c6e3521b1417.js",
|
||||||
|
"static/chunks/255-3991756713d22f05.js",
|
||||||
|
"static/chunks/main-app-f6d7a6830bbc9284.js",
|
||||||
|
"static/chunks/366-6401b0800e501f14.js",
|
||||||
|
"static/chunks/619-ba102abea3e3d0e4.js",
|
||||||
|
"static/chunks/app/page-15c28cf7e1a979df.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"/_not-found/page": "/_not-found",
|
||||||
|
"/favicon.ico/route": "/favicon.ico",
|
||||||
|
"/appointment/page": "/appointment",
|
||||||
|
"/contact/page": "/contact",
|
||||||
|
"/page": "/"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"polyfillFiles": [
|
||||||
|
"static/chunks/polyfills-42372ed130431b0a.js"
|
||||||
|
],
|
||||||
|
"devFiles": [],
|
||||||
|
"ampDevFiles": [],
|
||||||
|
"lowPriorityFiles": [
|
||||||
|
"static/15aOepE5x4uUwOLZRAN9M/_buildManifest.js",
|
||||||
|
"static/15aOepE5x4uUwOLZRAN9M/_ssgManifest.js"
|
||||||
|
],
|
||||||
|
"rootMainFiles": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/4bd1b696-c023c6e3521b1417.js",
|
||||||
|
"static/chunks/255-3991756713d22f05.js",
|
||||||
|
"static/chunks/main-app-f6d7a6830bbc9284.js"
|
||||||
|
],
|
||||||
|
"rootMainFilesTree": {},
|
||||||
|
"pages": {
|
||||||
|
"/_app": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/framework-a6e0b7e30f98059a.js",
|
||||||
|
"static/chunks/main-fd57048560d67b20.js",
|
||||||
|
"static/chunks/pages/_app-7d307437aca18ad4.js"
|
||||||
|
],
|
||||||
|
"/_error": [
|
||||||
|
"static/chunks/webpack-88963a06a789d277.js",
|
||||||
|
"static/chunks/framework-a6e0b7e30f98059a.js",
|
||||||
|
"static/chunks/main-fd57048560d67b20.js",
|
||||||
|
"static/chunks/pages/_error-cb2a52f75f2162e2.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ampFirstPages": []
|
||||||
|
}
|
||||||
1
.open-next/server-functions/default/.next/package.json
Normal file
1
.open-next/server-functions/default/.next/package.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"type": "commonjs"}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
{
|
||||||
|
"version": 4,
|
||||||
|
"routes": {
|
||||||
|
"/": {
|
||||||
|
"experimentalBypassFor": [
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "next-action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "content-type",
|
||||||
|
"value": "multipart/form-data;.*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"initialRevalidateSeconds": false,
|
||||||
|
"srcRoute": "/",
|
||||||
|
"dataRoute": "/index.rsc",
|
||||||
|
"allowHeader": [
|
||||||
|
"host",
|
||||||
|
"x-matched-path",
|
||||||
|
"x-prerender-revalidate",
|
||||||
|
"x-prerender-revalidate-if-generated",
|
||||||
|
"x-next-revalidated-tags",
|
||||||
|
"x-next-revalidate-tag-token"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/favicon.ico": {
|
||||||
|
"initialHeaders": {
|
||||||
|
"cache-control": "public, max-age=0, must-revalidate",
|
||||||
|
"content-type": "image/x-icon",
|
||||||
|
"x-next-cache-tags": "_N_T_/layout,_N_T_/favicon.ico/layout,_N_T_/favicon.ico/route,_N_T_/favicon.ico"
|
||||||
|
},
|
||||||
|
"experimentalBypassFor": [
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "next-action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "content-type",
|
||||||
|
"value": "multipart/form-data;.*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"initialRevalidateSeconds": false,
|
||||||
|
"srcRoute": "/favicon.ico",
|
||||||
|
"dataRoute": null,
|
||||||
|
"allowHeader": [
|
||||||
|
"host",
|
||||||
|
"x-matched-path",
|
||||||
|
"x-prerender-revalidate",
|
||||||
|
"x-prerender-revalidate-if-generated",
|
||||||
|
"x-next-revalidated-tags",
|
||||||
|
"x-next-revalidate-tag-token"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/appointment": {
|
||||||
|
"experimentalBypassFor": [
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "next-action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "content-type",
|
||||||
|
"value": "multipart/form-data;.*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"initialRevalidateSeconds": false,
|
||||||
|
"srcRoute": "/appointment",
|
||||||
|
"dataRoute": "/appointment.rsc",
|
||||||
|
"allowHeader": [
|
||||||
|
"host",
|
||||||
|
"x-matched-path",
|
||||||
|
"x-prerender-revalidate",
|
||||||
|
"x-prerender-revalidate-if-generated",
|
||||||
|
"x-next-revalidated-tags",
|
||||||
|
"x-next-revalidate-tag-token"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/contact": {
|
||||||
|
"experimentalBypassFor": [
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "next-action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "content-type",
|
||||||
|
"value": "multipart/form-data;.*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"initialRevalidateSeconds": false,
|
||||||
|
"srcRoute": "/contact",
|
||||||
|
"dataRoute": "/contact.rsc",
|
||||||
|
"allowHeader": [
|
||||||
|
"host",
|
||||||
|
"x-matched-path",
|
||||||
|
"x-prerender-revalidate",
|
||||||
|
"x-prerender-revalidate-if-generated",
|
||||||
|
"x-next-revalidated-tags",
|
||||||
|
"x-next-revalidate-tag-token"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/_not-found": {
|
||||||
|
"initialStatus": 404,
|
||||||
|
"experimentalBypassFor": [
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "next-action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
"key": "content-type",
|
||||||
|
"value": "multipart/form-data;.*"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"initialRevalidateSeconds": false,
|
||||||
|
"srcRoute": "/_not-found",
|
||||||
|
"dataRoute": "/_not-found.rsc",
|
||||||
|
"allowHeader": [
|
||||||
|
"host",
|
||||||
|
"x-matched-path",
|
||||||
|
"x-prerender-revalidate",
|
||||||
|
"x-prerender-revalidate-if-generated",
|
||||||
|
"x-next-revalidated-tags",
|
||||||
|
"x-next-revalidate-tag-token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dynamicRoutes": {},
|
||||||
|
"notFoundRoutes": [],
|
||||||
|
"preview": {
|
||||||
|
"previewModeId": "a93160fac8c4e7d386ed2d8b07c7b4c0",
|
||||||
|
"previewModeSigningKey": "d1d468940684708e7e19f5d29a716018cd9c58d63f836fbda405227f1d18c3be",
|
||||||
|
"previewModeEncryptionKey": "f52f67d125da3174f4d3cc829cddca979756925e0d81a88a68649074b8a114cc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
||||||
|
|
@ -0,0 +1,321 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"config": {
|
||||||
|
"env": {},
|
||||||
|
"webpack": null,
|
||||||
|
"eslint": {
|
||||||
|
"ignoreDuringBuilds": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"ignoreBuildErrors": false,
|
||||||
|
"tsconfigPath": "tsconfig.json"
|
||||||
|
},
|
||||||
|
"typedRoutes": false,
|
||||||
|
"distDir": ".next",
|
||||||
|
"cleanDistDir": true,
|
||||||
|
"assetPrefix": "",
|
||||||
|
"cacheMaxMemorySize": 52428800,
|
||||||
|
"configOrigin": "next.config.ts",
|
||||||
|
"useFileSystemPublicRoutes": true,
|
||||||
|
"generateEtags": true,
|
||||||
|
"pageExtensions": [
|
||||||
|
"tsx",
|
||||||
|
"ts",
|
||||||
|
"jsx",
|
||||||
|
"js"
|
||||||
|
],
|
||||||
|
"poweredByHeader": true,
|
||||||
|
"compress": true,
|
||||||
|
"images": {
|
||||||
|
"deviceSizes": [
|
||||||
|
640,
|
||||||
|
750,
|
||||||
|
828,
|
||||||
|
1080,
|
||||||
|
1200,
|
||||||
|
1920,
|
||||||
|
2048,
|
||||||
|
3840
|
||||||
|
],
|
||||||
|
"imageSizes": [
|
||||||
|
16,
|
||||||
|
32,
|
||||||
|
48,
|
||||||
|
64,
|
||||||
|
96,
|
||||||
|
128,
|
||||||
|
256,
|
||||||
|
384
|
||||||
|
],
|
||||||
|
"path": "/_next/image",
|
||||||
|
"loader": "default",
|
||||||
|
"loaderFile": "",
|
||||||
|
"domains": [],
|
||||||
|
"disableStaticImages": false,
|
||||||
|
"minimumCacheTTL": 60,
|
||||||
|
"formats": [
|
||||||
|
"image/webp"
|
||||||
|
],
|
||||||
|
"maximumResponseBody": 50000000,
|
||||||
|
"dangerouslyAllowSVG": false,
|
||||||
|
"contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;",
|
||||||
|
"contentDispositionType": "attachment",
|
||||||
|
"remotePatterns": [],
|
||||||
|
"unoptimized": false
|
||||||
|
},
|
||||||
|
"devIndicators": {
|
||||||
|
"position": "bottom-left"
|
||||||
|
},
|
||||||
|
"onDemandEntries": {
|
||||||
|
"maxInactiveAge": 60000,
|
||||||
|
"pagesBufferLength": 5
|
||||||
|
},
|
||||||
|
"amp": {
|
||||||
|
"canonicalBase": ""
|
||||||
|
},
|
||||||
|
"basePath": "",
|
||||||
|
"sassOptions": {},
|
||||||
|
"trailingSlash": false,
|
||||||
|
"i18n": null,
|
||||||
|
"productionBrowserSourceMaps": false,
|
||||||
|
"excludeDefaultMomentLocales": true,
|
||||||
|
"serverRuntimeConfig": {},
|
||||||
|
"publicRuntimeConfig": {},
|
||||||
|
"reactProductionProfiling": false,
|
||||||
|
"reactStrictMode": null,
|
||||||
|
"reactMaxHeadersLength": 6000,
|
||||||
|
"httpAgentOptions": {
|
||||||
|
"keepAlive": true
|
||||||
|
},
|
||||||
|
"logging": {},
|
||||||
|
"compiler": {},
|
||||||
|
"expireTime": 31536000,
|
||||||
|
"staticPageGenerationTimeout": 60,
|
||||||
|
"output": "standalone",
|
||||||
|
"modularizeImports": {
|
||||||
|
"@mui/icons-material": {
|
||||||
|
"transform": "@mui/icons-material/{{member}}"
|
||||||
|
},
|
||||||
|
"lodash": {
|
||||||
|
"transform": "lodash/{{member}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputFileTracingRoot": "/Users/kirukib/Desktop/Ghion Finance",
|
||||||
|
"experimental": {
|
||||||
|
"useSkewCookie": false,
|
||||||
|
"cacheLife": {
|
||||||
|
"default": {
|
||||||
|
"stale": 300,
|
||||||
|
"revalidate": 900,
|
||||||
|
"expire": 4294967294
|
||||||
|
},
|
||||||
|
"seconds": {
|
||||||
|
"stale": 30,
|
||||||
|
"revalidate": 1,
|
||||||
|
"expire": 60
|
||||||
|
},
|
||||||
|
"minutes": {
|
||||||
|
"stale": 300,
|
||||||
|
"revalidate": 60,
|
||||||
|
"expire": 3600
|
||||||
|
},
|
||||||
|
"hours": {
|
||||||
|
"stale": 300,
|
||||||
|
"revalidate": 3600,
|
||||||
|
"expire": 86400
|
||||||
|
},
|
||||||
|
"days": {
|
||||||
|
"stale": 300,
|
||||||
|
"revalidate": 86400,
|
||||||
|
"expire": 604800
|
||||||
|
},
|
||||||
|
"weeks": {
|
||||||
|
"stale": 300,
|
||||||
|
"revalidate": 604800,
|
||||||
|
"expire": 2592000
|
||||||
|
},
|
||||||
|
"max": {
|
||||||
|
"stale": 300,
|
||||||
|
"revalidate": 2592000,
|
||||||
|
"expire": 4294967294
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cacheHandlers": {},
|
||||||
|
"cssChunking": true,
|
||||||
|
"multiZoneDraftMode": false,
|
||||||
|
"appNavFailHandling": false,
|
||||||
|
"prerenderEarlyExit": true,
|
||||||
|
"serverMinification": true,
|
||||||
|
"serverSourceMaps": false,
|
||||||
|
"linkNoTouchStart": false,
|
||||||
|
"caseSensitiveRoutes": false,
|
||||||
|
"clientSegmentCache": false,
|
||||||
|
"clientParamParsing": false,
|
||||||
|
"dynamicOnHover": false,
|
||||||
|
"preloadEntriesOnStart": true,
|
||||||
|
"clientRouterFilter": true,
|
||||||
|
"clientRouterFilterRedirects": false,
|
||||||
|
"fetchCacheKeyPrefix": "",
|
||||||
|
"middlewarePrefetch": "flexible",
|
||||||
|
"optimisticClientCache": true,
|
||||||
|
"manualClientBasePath": false,
|
||||||
|
"cpus": 7,
|
||||||
|
"memoryBasedWorkersCount": false,
|
||||||
|
"imgOptConcurrency": null,
|
||||||
|
"imgOptTimeoutInSeconds": 7,
|
||||||
|
"imgOptMaxInputPixels": 268402689,
|
||||||
|
"imgOptSequentialRead": null,
|
||||||
|
"imgOptSkipMetadata": null,
|
||||||
|
"isrFlushToDisk": true,
|
||||||
|
"workerThreads": false,
|
||||||
|
"optimizeCss": false,
|
||||||
|
"nextScriptWorkers": false,
|
||||||
|
"scrollRestoration": false,
|
||||||
|
"externalDir": false,
|
||||||
|
"disableOptimizedLoading": false,
|
||||||
|
"gzipSize": true,
|
||||||
|
"craCompat": false,
|
||||||
|
"esmExternals": true,
|
||||||
|
"fullySpecified": false,
|
||||||
|
"swcTraceProfiling": false,
|
||||||
|
"forceSwcTransforms": false,
|
||||||
|
"largePageDataBytes": 128000,
|
||||||
|
"typedEnv": false,
|
||||||
|
"parallelServerCompiles": false,
|
||||||
|
"parallelServerBuildTraces": false,
|
||||||
|
"ppr": false,
|
||||||
|
"authInterrupts": false,
|
||||||
|
"webpackMemoryOptimizations": false,
|
||||||
|
"optimizeServerReact": true,
|
||||||
|
"viewTransition": false,
|
||||||
|
"routerBFCache": false,
|
||||||
|
"removeUncaughtErrorAndRejectionListeners": false,
|
||||||
|
"validateRSCRequestHeaders": false,
|
||||||
|
"staleTimes": {
|
||||||
|
"dynamic": 0,
|
||||||
|
"static": 300
|
||||||
|
},
|
||||||
|
"serverComponentsHmrCache": true,
|
||||||
|
"staticGenerationMaxConcurrency": 8,
|
||||||
|
"staticGenerationMinPagesPerWorker": 25,
|
||||||
|
"cacheComponents": false,
|
||||||
|
"inlineCss": false,
|
||||||
|
"useCache": false,
|
||||||
|
"globalNotFound": false,
|
||||||
|
"devtoolSegmentExplorer": true,
|
||||||
|
"browserDebugInfoInTerminal": false,
|
||||||
|
"optimizeRouterScrolling": false,
|
||||||
|
"middlewareClientMaxBodySize": 10485760,
|
||||||
|
"optimizePackageImports": [
|
||||||
|
"lucide-react",
|
||||||
|
"date-fns",
|
||||||
|
"lodash-es",
|
||||||
|
"ramda",
|
||||||
|
"antd",
|
||||||
|
"react-bootstrap",
|
||||||
|
"ahooks",
|
||||||
|
"@ant-design/icons",
|
||||||
|
"@headlessui/react",
|
||||||
|
"@headlessui-float/react",
|
||||||
|
"@heroicons/react/20/solid",
|
||||||
|
"@heroicons/react/24/solid",
|
||||||
|
"@heroicons/react/24/outline",
|
||||||
|
"@visx/visx",
|
||||||
|
"@tremor/react",
|
||||||
|
"rxjs",
|
||||||
|
"@mui/material",
|
||||||
|
"@mui/icons-material",
|
||||||
|
"recharts",
|
||||||
|
"react-use",
|
||||||
|
"effect",
|
||||||
|
"@effect/schema",
|
||||||
|
"@effect/platform",
|
||||||
|
"@effect/platform-node",
|
||||||
|
"@effect/platform-browser",
|
||||||
|
"@effect/platform-bun",
|
||||||
|
"@effect/sql",
|
||||||
|
"@effect/sql-mssql",
|
||||||
|
"@effect/sql-mysql2",
|
||||||
|
"@effect/sql-pg",
|
||||||
|
"@effect/sql-sqlite-node",
|
||||||
|
"@effect/sql-sqlite-bun",
|
||||||
|
"@effect/sql-sqlite-wasm",
|
||||||
|
"@effect/sql-sqlite-react-native",
|
||||||
|
"@effect/rpc",
|
||||||
|
"@effect/rpc-http",
|
||||||
|
"@effect/typeclass",
|
||||||
|
"@effect/experimental",
|
||||||
|
"@effect/opentelemetry",
|
||||||
|
"@material-ui/core",
|
||||||
|
"@material-ui/icons",
|
||||||
|
"@tabler/icons-react",
|
||||||
|
"mui-core",
|
||||||
|
"react-icons/ai",
|
||||||
|
"react-icons/bi",
|
||||||
|
"react-icons/bs",
|
||||||
|
"react-icons/cg",
|
||||||
|
"react-icons/ci",
|
||||||
|
"react-icons/di",
|
||||||
|
"react-icons/fa",
|
||||||
|
"react-icons/fa6",
|
||||||
|
"react-icons/fc",
|
||||||
|
"react-icons/fi",
|
||||||
|
"react-icons/gi",
|
||||||
|
"react-icons/go",
|
||||||
|
"react-icons/gr",
|
||||||
|
"react-icons/hi",
|
||||||
|
"react-icons/hi2",
|
||||||
|
"react-icons/im",
|
||||||
|
"react-icons/io",
|
||||||
|
"react-icons/io5",
|
||||||
|
"react-icons/lia",
|
||||||
|
"react-icons/lib",
|
||||||
|
"react-icons/lu",
|
||||||
|
"react-icons/md",
|
||||||
|
"react-icons/pi",
|
||||||
|
"react-icons/ri",
|
||||||
|
"react-icons/rx",
|
||||||
|
"react-icons/si",
|
||||||
|
"react-icons/sl",
|
||||||
|
"react-icons/tb",
|
||||||
|
"react-icons/tfi",
|
||||||
|
"react-icons/ti",
|
||||||
|
"react-icons/vsc",
|
||||||
|
"react-icons/wi"
|
||||||
|
],
|
||||||
|
"trustHostHeader": false,
|
||||||
|
"isExperimentalCompile": false
|
||||||
|
},
|
||||||
|
"htmlLimitedBots": "[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight",
|
||||||
|
"bundlePagesRouterDependencies": false,
|
||||||
|
"configFileName": "next.config.ts",
|
||||||
|
"turbopack": {
|
||||||
|
"root": "/Users/kirukib/Desktop/Ghion Finance"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"appDir": "/Users/kirukib/Desktop/Ghion Finance",
|
||||||
|
"relativeAppDir": "",
|
||||||
|
"files": [
|
||||||
|
".next/routes-manifest.json",
|
||||||
|
".next/server/pages-manifest.json",
|
||||||
|
".next/build-manifest.json",
|
||||||
|
".next/prerender-manifest.json",
|
||||||
|
".next/server/functions-config-manifest.json",
|
||||||
|
".next/server/middleware-manifest.json",
|
||||||
|
".next/server/middleware-build-manifest.js",
|
||||||
|
".next/server/middleware-react-loadable-manifest.js",
|
||||||
|
".next/react-loadable-manifest.json",
|
||||||
|
".next/server/app-paths-manifest.json",
|
||||||
|
".next/app-path-routes-manifest.json",
|
||||||
|
".next/app-build-manifest.json",
|
||||||
|
".next/server/server-reference-manifest.js",
|
||||||
|
".next/server/server-reference-manifest.json",
|
||||||
|
".next/BUILD_ID",
|
||||||
|
".next/server/next-font-manifest.js",
|
||||||
|
".next/server/next-font-manifest.json",
|
||||||
|
".next/required-server-files.json"
|
||||||
|
],
|
||||||
|
"ignore": [
|
||||||
|
"node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"pages404": true,
|
||||||
|
"caseSensitive": false,
|
||||||
|
"basePath": "",
|
||||||
|
"redirects": [
|
||||||
|
{
|
||||||
|
"source": "/:path+/",
|
||||||
|
"destination": "/:path+",
|
||||||
|
"internal": true,
|
||||||
|
"statusCode": 308,
|
||||||
|
"regex": "^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headers": [],
|
||||||
|
"rewrites": {
|
||||||
|
"beforeFiles": [],
|
||||||
|
"afterFiles": [],
|
||||||
|
"fallback": []
|
||||||
|
},
|
||||||
|
"dynamicRoutes": [],
|
||||||
|
"staticRoutes": [
|
||||||
|
{
|
||||||
|
"page": "/",
|
||||||
|
"regex": "^/(?:/)?$",
|
||||||
|
"routeKeys": {},
|
||||||
|
"namedRegex": "^/(?:/)?$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"page": "/_not-found",
|
||||||
|
"regex": "^/_not\\-found(?:/)?$",
|
||||||
|
"routeKeys": {},
|
||||||
|
"namedRegex": "^/_not\\-found(?:/)?$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"page": "/appointment",
|
||||||
|
"regex": "^/appointment(?:/)?$",
|
||||||
|
"routeKeys": {},
|
||||||
|
"namedRegex": "^/appointment(?:/)?$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"page": "/contact",
|
||||||
|
"regex": "^/contact(?:/)?$",
|
||||||
|
"routeKeys": {},
|
||||||
|
"namedRegex": "^/contact(?:/)?$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"page": "/favicon.ico",
|
||||||
|
"regex": "^/favicon\\.ico(?:/)?$",
|
||||||
|
"routeKeys": {},
|
||||||
|
"namedRegex": "^/favicon\\.ico(?:/)?$"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dataRoutes": [],
|
||||||
|
"rsc": {
|
||||||
|
"header": "rsc",
|
||||||
|
"varyHeader": "rsc, next-router-state-tree, next-router-prefetch, next-router-segment-prefetch",
|
||||||
|
"prefetchHeader": "next-router-prefetch",
|
||||||
|
"didPostponeHeader": "x-nextjs-postponed",
|
||||||
|
"contentTypeHeader": "text/x-component",
|
||||||
|
"suffix": ".rsc",
|
||||||
|
"prefetchSuffix": ".prefetch.rsc",
|
||||||
|
"prefetchSegmentHeader": "next-router-segment-prefetch",
|
||||||
|
"prefetchSegmentSuffix": ".segment.rsc",
|
||||||
|
"prefetchSegmentDirSuffix": ".segments"
|
||||||
|
},
|
||||||
|
"rewriteHeaders": {
|
||||||
|
"pathHeader": "x-nextjs-rewritten-path",
|
||||||
|
"queryHeader": "x-nextjs-rewritten-query"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"/_not-found/page": "app/_not-found/page.js",
|
||||||
|
"/favicon.ico/route": "app/favicon.ico/route.js",
|
||||||
|
"/appointment/page": "app/appointment/page.js",
|
||||||
|
"/contact/page": "app/contact/page.js",
|
||||||
|
"/page": "app/page.js"
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user