This commit implements the core admin dashboard functionality including NextAuth authentication, Cloudflare D1 database integration with complete schema, and Cloudflare R2 file upload system for portfolio images. Features include artist management, appointment scheduling, and data migration capabilities.
123 lines
4.7 KiB
JavaScript
123 lines
4.7 KiB
JavaScript
/**
|
|
* 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__;
|
|
}
|
|
}
|