UNPKG

@prisma/cli-init

Version:

Init CLI for Prisma

1,287 lines (1,276 loc) • 41.8 kB
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); // ../../node_modules/.pnpm/valibot@1.1.0_typescript@5.8.3/node_modules/valibot/dist/index.js var store; // @__NO_SIDE_EFFECTS__ function getGlobalConfig(config2) { return { lang: config2?.lang ?? store?.lang, message: config2?.message, abortEarly: config2?.abortEarly ?? store?.abortEarly, abortPipeEarly: config2?.abortPipeEarly ?? store?.abortPipeEarly }; } var store2; // @__NO_SIDE_EFFECTS__ function getGlobalMessage(lang) { return store2?.get(lang); } var store3; // @__NO_SIDE_EFFECTS__ function getSchemaMessage(lang) { return store3?.get(lang); } var store4; // @__NO_SIDE_EFFECTS__ function getSpecificMessage(reference, lang) { return store4?.get(reference)?.get(lang); } // @__NO_SIDE_EFFECTS__ function _stringify(input) { const type = typeof input; if (type === "string") { return `"${input}"`; } if (type === "number" || type === "bigint" || type === "boolean") { return `${input}`; } if (type === "object" || type === "function") { return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null"; } return type; } function _addIssue(context, label, dataset, config2, other) { const input = other && "input" in other ? other.input : dataset.value; const expected = other?.expected ?? context.expects ?? null; const received = other?.received ?? /* @__PURE__ */ _stringify(input); const issue = { kind: context.kind, type: context.type, input, expected, received, message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`, requirement: context.requirement, path: other?.path, issues: other?.issues, lang: config2.lang, abortEarly: config2.abortEarly, abortPipeEarly: config2.abortPipeEarly }; const isSchema = context.kind === "schema"; const message2 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage(issue.lang) : null) ?? config2.message ?? /* @__PURE__ */ getGlobalMessage(issue.lang); if (message2 !== void 0) { issue.message = typeof message2 === "function" ? ( // @ts-expect-error message2(issue) ) : message2; } if (isSchema) { dataset.typed = false; } if (dataset.issues) { dataset.issues.push(issue); } else { dataset.issues = [issue]; } } // @__NO_SIDE_EFFECTS__ function _getStandardProps(context) { return { version: 1, vendor: "valibot", validate(value2) { return context["~run"]({ value: value2 }, /* @__PURE__ */ getGlobalConfig()); } }; } // @__NO_SIDE_EFFECTS__ function _isValidObjectKey(object2, key) { return Object.hasOwn(object2, key) && key !== "__proto__" && key !== "prototype" && key !== "constructor"; } // @__NO_SIDE_EFFECTS__ function _joinExpects(values2, separator) { const list = [...new Set(values2)]; if (list.length > 1) { return `(${list.join(` ${separator} `)})`; } return list[0] ?? "never"; } // @__NO_SIDE_EFFECTS__ function integer(message2) { return { kind: "validation", type: "integer", reference: integer, async: false, expects: null, requirement: Number.isInteger, message: message2, "~run"(dataset, config2) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, "integer", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function minLength(requirement, message2) { return { kind: "validation", type: "min_length", reference: minLength, async: false, expects: `>=${requirement}`, requirement, message: message2, "~run"(dataset, config2) { if (dataset.typed && dataset.value.length < this.requirement) { _addIssue(this, "length", dataset, config2, { received: `${dataset.value.length}` }); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function minValue(requirement, message2) { return { kind: "validation", type: "min_value", reference: minValue, async: false, expects: `>=${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`, requirement, message: message2, "~run"(dataset, config2) { if (dataset.typed && !(dataset.value >= this.requirement)) { _addIssue(this, "value", dataset, config2, { received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value) }); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function parseJson(config2, message2) { return { kind: "transformation", type: "parse_json", reference: parseJson, config: config2, message: message2, async: false, "~run"(dataset, config3) { try { dataset.value = JSON.parse(dataset.value, this.config?.reviver); } catch (error) { if (error instanceof Error) { _addIssue(this, "JSON", dataset, config3, { received: `"${error.message}"` }); dataset.typed = false; } else { throw error; } } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function regex(requirement, message2) { return { kind: "validation", type: "regex", reference: regex, async: false, expects: `${requirement}`, requirement, message: message2, "~run"(dataset, config2) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, "format", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function url(message2) { return { kind: "validation", type: "url", reference: url, async: false, expects: null, requirement(input) { try { new URL(input); return true; } catch { return false; } }, message: message2, "~run"(dataset, config2) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, "URL", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function getFallback(schema, dataset, config2) { return typeof schema.fallback === "function" ? ( // @ts-expect-error schema.fallback(dataset, config2) ) : ( // @ts-expect-error schema.fallback ); } // @__NO_SIDE_EFFECTS__ function getDefault(schema, dataset, config2) { return typeof schema.default === "function" ? ( // @ts-expect-error schema.default(dataset, config2) ) : ( // @ts-expect-error schema.default ); } // @__NO_SIDE_EFFECTS__ function array(item, message2) { return { kind: "schema", type: "array", reference: array, expects: "Array", async: false, item, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { const input = dataset.value; if (Array.isArray(input)) { dataset.typed = true; dataset.value = []; for (let key = 0; key < input.length; key++) { const value2 = input[key]; const itemDataset = this.item["~run"]({ value: value2 }, config2); if (itemDataset.issues) { const pathItem = { type: "array", origin: "value", input, key, value: value2 }; for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { issue.path = [pathItem]; } dataset.issues?.push(issue); } if (!dataset.issues) { dataset.issues = itemDataset.issues; } if (config2.abortEarly) { dataset.typed = false; break; } } if (!itemDataset.typed) { dataset.typed = false; } dataset.value.push(itemDataset.value); } } else { _addIssue(this, "type", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function literal(literal_, message2) { return { kind: "schema", type: "literal", reference: literal, expects: /* @__PURE__ */ _stringify(literal_), async: false, literal: literal_, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { if (dataset.value === this.literal) { dataset.typed = true; } else { _addIssue(this, "type", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function looseObject(entries2, message2) { return { kind: "schema", type: "loose_object", reference: looseObject, expects: "Object", async: false, entries: entries2, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { const input = dataset.value; if (input && typeof input === "object") { dataset.typed = true; dataset.value = {}; for (const key in this.entries) { const valueSchema = this.entries[key]; if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && // @ts-expect-error valueSchema.default !== void 0) { const value2 = key in input ? ( // @ts-expect-error input[key] ) : /* @__PURE__ */ getDefault(valueSchema); const valueDataset = valueSchema["~run"]({ value: value2 }, config2); if (valueDataset.issues) { const pathItem = { type: "object", origin: "value", input, key, value: value2 }; for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { issue.path = [pathItem]; } dataset.issues?.push(issue); } if (!dataset.issues) { dataset.issues = valueDataset.issues; } if (config2.abortEarly) { dataset.typed = false; break; } } if (!valueDataset.typed) { dataset.typed = false; } dataset.value[key] = valueDataset.value; } else if (valueSchema.fallback !== void 0) { dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema); } else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") { _addIssue(this, "key", dataset, config2, { input: void 0, expected: `"${key}"`, path: [ { type: "object", origin: "key", input, key, // @ts-expect-error value: input[key] } ] }); if (config2.abortEarly) { break; } } } if (!dataset.issues || !config2.abortEarly) { for (const key in input) { if (/* @__PURE__ */ _isValidObjectKey(input, key) && !(key in this.entries)) { dataset.value[key] = input[key]; } } } } else { _addIssue(this, "type", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function number(message2) { return { kind: "schema", type: "number", reference: number, expects: "number", async: false, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { if (typeof dataset.value === "number" && !isNaN(dataset.value)) { dataset.typed = true; } else { _addIssue(this, "type", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function object(entries2, message2) { return { kind: "schema", type: "object", reference: object, expects: "Object", async: false, entries: entries2, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { const input = dataset.value; if (input && typeof input === "object") { dataset.typed = true; dataset.value = {}; for (const key in this.entries) { const valueSchema = this.entries[key]; if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && // @ts-expect-error valueSchema.default !== void 0) { const value2 = key in input ? ( // @ts-expect-error input[key] ) : /* @__PURE__ */ getDefault(valueSchema); const valueDataset = valueSchema["~run"]({ value: value2 }, config2); if (valueDataset.issues) { const pathItem = { type: "object", origin: "value", input, key, value: value2 }; for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { issue.path = [pathItem]; } dataset.issues?.push(issue); } if (!dataset.issues) { dataset.issues = valueDataset.issues; } if (config2.abortEarly) { dataset.typed = false; break; } } if (!valueDataset.typed) { dataset.typed = false; } dataset.value[key] = valueDataset.value; } else if (valueSchema.fallback !== void 0) { dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema); } else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") { _addIssue(this, "key", dataset, config2, { input: void 0, expected: `"${key}"`, path: [ { type: "object", origin: "key", input, key, // @ts-expect-error value: input[key] } ] }); if (config2.abortEarly) { break; } } } } else { _addIssue(this, "type", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function optional(wrapped, default_) { return { kind: "schema", type: "optional", reference: optional, expects: `(${wrapped.expects} | undefined)`, async: false, wrapped, default: default_, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { if (dataset.value === void 0) { if (this.default !== void 0) { dataset.value = /* @__PURE__ */ getDefault(this, dataset, config2); } if (dataset.value === void 0) { dataset.typed = true; return dataset; } } return this.wrapped["~run"](dataset, config2); } }; } // @__NO_SIDE_EFFECTS__ function string(message2) { return { kind: "schema", type: "string", reference: string, expects: "string", async: false, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { if (typeof dataset.value === "string") { dataset.typed = true; } else { _addIssue(this, "type", dataset, config2); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function _subIssues(datasets) { let issues; if (datasets) { for (const dataset of datasets) { if (issues) { issues.push(...dataset.issues); } else { issues = dataset.issues; } } } return issues; } // @__NO_SIDE_EFFECTS__ function union(options, message2) { return { kind: "schema", type: "union", reference: union, expects: /* @__PURE__ */ _joinExpects( options.map((option) => option.expects), "|" ), async: false, options, message: message2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { let validDataset; let typedDatasets; let untypedDatasets; for (const schema of this.options) { const optionDataset = schema["~run"]({ value: dataset.value }, config2); if (optionDataset.typed) { if (optionDataset.issues) { if (typedDatasets) { typedDatasets.push(optionDataset); } else { typedDatasets = [optionDataset]; } } else { validDataset = optionDataset; break; } } else { if (untypedDatasets) { untypedDatasets.push(optionDataset); } else { untypedDatasets = [optionDataset]; } } } if (validDataset) { return validDataset; } if (typedDatasets) { if (typedDatasets.length === 1) { return typedDatasets[0]; } _addIssue(this, "type", dataset, config2, { issues: /* @__PURE__ */ _subIssues(typedDatasets) }); dataset.typed = true; } else if (untypedDatasets?.length === 1) { return untypedDatasets[0]; } else { _addIssue(this, "type", dataset, config2, { issues: /* @__PURE__ */ _subIssues(untypedDatasets) }); } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function pipe(...pipe2) { return { ...pipe2[0], pipe: pipe2, get "~standard"() { return /* @__PURE__ */ _getStandardProps(this); }, "~run"(dataset, config2) { for (const item of pipe2) { if (item.kind !== "metadata") { if (dataset.issues && (item.kind === "schema" || item.kind === "transformation")) { dataset.typed = false; break; } if (!dataset.issues || !config2.abortEarly && !config2.abortPipeEarly) { dataset = item["~run"](dataset, config2); } } } return dataset; } }; } // @__NO_SIDE_EFFECTS__ function safeParse(schema, input, config2) { const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config2)); return { typed: dataset.typed, success: !dataset.issues, output: dataset.value, issues: dataset.issues }; } // ../../dev/server/src/api-key.ts var POSTGRES_PROTOCOL_REGEX = /^(postgres|postgresql):\/\//; var decodedAPIKeySchema = pipe( string(), parseJson(), object({ databaseUrl: pipe(string(), url(), regex(POSTGRES_PROTOCOL_REGEX)), name: optional(pipe(string(), minLength(1))), shadowDatabaseUrl: pipe(string(), url(), regex(POSTGRES_PROTOCOL_REGEX)) }) ); function encodeAPIKey(payload) { return Buffer.from( // we sort the keys to ensure consistent encoding JSON.stringify(Object.fromEntries(Object.entries(payload).sort(([[key0], [key1]]) => key0.localeCompare(key1)))), "utf8" ).toString("base64url"); } function decodeAPIKey(apiKey) { const serialized = Buffer.from(apiKey, "base64url").toString("utf8"); const { issues, output, success } = safeParse(decodedAPIKeySchema, serialized, { abortEarly: true }); if (!success) { return [issues]; } return [null, output]; } var apiKeyValidator = async (value, ctx) => { const { authorization } = value; const { HTTPException } = await import("hono/http-exception"); if (!authorization) { throw new HTTPException(401, { message: "Missing API Key" }); } const [keyType, apiKey = "", extras] = authorization.split(" "); if (keyType !== "Bearer" || extras) { throw new HTTPException(401, { message: "Invalid API Key" }); } const [issues, decodedAPIKey] = decodeAPIKey(apiKey); if (issues) { throw new HTTPException(401, { message: "Invalid API Key", cause: issues.join(", ") }); } const { databaseUrl, name, shadowDatabaseUrl } = decodedAPIKey; const { name: expectedName } = ctx.get("serverState"); if (!name) { throw new HTTPException(401, { message: `Wrong API Key; The Prisma Dev server running at port ${ctx.get("port")} requires an API Key from a newer version of \`prisma dev\`. Check the "${expectedName}" server's output for the updated \`DATABASE_URL\` value.` }); } if (name !== expectedName) { throw new HTTPException(401, { message: `Wrong API Key; The Prisma Dev server running at port ${ctx.get("port")} is named "${expectedName}", but the API Key is for "${name}"` }); } const { hostname, port } = new URL(databaseUrl); const { port: expectedPort } = ctx.get("db"); const { hostname: shadowHostname, port: shadowPort } = new URL(shadowDatabaseUrl); const expectedShadowPort = ctx.get("shadowDBPort"); if (hostname !== "localhost" || Number(port) !== expectedPort || shadowHostname !== "localhost" || Number(shadowPort) !== expectedShadowPort) { throw new HTTPException(401, { message: "Wrong API Key; Check your Prisma schema's `provider.url` value (probably defined in `.env`'s `DATABASE_URL` environment variable) is aligned with `prisma dev`'s output" }); } return { decodedAPIKey }; }; // ../../dev/server/src/engine.ts import { spawn } from "child_process"; import { once } from "events"; import { mkdir as mkdir2 } from "fs/promises"; import { join } from "path"; import { setTimeout } from "timers/promises"; // ../../common/stuff/with-resolvers.ts function withResolvers(options) { let succeed, fail; const promise = new Promise((resolve, reject) => { succeed = resolve; fail = reject; }); let failOnce = (reason) => { failOnce = succeedOnce = null; fail(reason); options?.onRejected?.(reason); options?.onFulfilled?.(); }; let succeedOnce = (value) => { succeedOnce = failOnce = null; succeed(value); options?.onResolved?.(value); options?.onFulfilled?.(); }; return { isFulfilled: () => succeedOnce === failOnce, promise, reject: (reason) => failOnce?.(reason), resolve: (value) => succeedOnce?.(value) }; } // ../../node_modules/.pnpm/std-env@3.9.0/node_modules/std-env/dist/index.mjs var r = /* @__PURE__ */ Object.create(null); var i = (e) => globalThis.process?.env || import.meta.env || globalThis.Deno?.env.toObject() || globalThis.__env__ || (e ? r : globalThis); var o = new Proxy(r, { get(e, s) { return i()[s] ?? r[s]; }, has(e, s) { const E = i(); return s in E || s in r; }, set(e, s, E) { const B = i(true); return B[s] = E, true; }, deleteProperty(e, s) { if (!s) return false; const E = i(true); return delete E[s], true; }, ownKeys() { const e = i(true); return Object.keys(e); } }); var t = typeof process < "u" && process.env && process.env.NODE_ENV || ""; var f = [["APPVEYOR"], ["AWS_AMPLIFY", "AWS_APP_ID", { ci: true }], ["AZURE_PIPELINES", "SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"], ["AZURE_STATIC", "INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN"], ["APPCIRCLE", "AC_APPCIRCLE"], ["BAMBOO", "bamboo_planKey"], ["BITBUCKET", "BITBUCKET_COMMIT"], ["BITRISE", "BITRISE_IO"], ["BUDDY", "BUDDY_WORKSPACE_ID"], ["BUILDKITE"], ["CIRCLE", "CIRCLECI"], ["CIRRUS", "CIRRUS_CI"], ["CLOUDFLARE_PAGES", "CF_PAGES", { ci: true }], ["CLOUDFLARE_WORKERS", "WORKERS_CI", { ci: true }], ["CODEBUILD", "CODEBUILD_BUILD_ARN"], ["CODEFRESH", "CF_BUILD_ID"], ["DRONE"], ["DRONE", "DRONE_BUILD_EVENT"], ["DSARI"], ["GITHUB_ACTIONS"], ["GITLAB", "GITLAB_CI"], ["GITLAB", "CI_MERGE_REQUEST_ID"], ["GOCD", "GO_PIPELINE_LABEL"], ["LAYERCI"], ["HUDSON", "HUDSON_URL"], ["JENKINS", "JENKINS_URL"], ["MAGNUM"], ["NETLIFY"], ["NETLIFY", "NETLIFY_LOCAL", { ci: false }], ["NEVERCODE"], ["RENDER"], ["SAIL", "SAILCI"], ["SEMAPHORE"], ["SCREWDRIVER"], ["SHIPPABLE"], ["SOLANO", "TDDIUM"], ["STRIDER"], ["TEAMCITY", "TEAMCITY_VERSION"], ["TRAVIS"], ["VERCEL", "NOW_BUILDER"], ["VERCEL", "VERCEL", { ci: false }], ["VERCEL", "VERCEL_ENV", { ci: false }], ["APPCENTER", "APPCENTER_BUILD_ID"], ["CODESANDBOX", "CODESANDBOX_SSE", { ci: false }], ["CODESANDBOX", "CODESANDBOX_HOST", { ci: false }], ["STACKBLITZ"], ["STORMKIT"], ["CLEAVR"], ["ZEABUR"], ["CODESPHERE", "CODESPHERE_APP_ID", { ci: true }], ["RAILWAY", "RAILWAY_PROJECT_ID"], ["RAILWAY", "RAILWAY_SERVICE_ID"], ["DENO-DEPLOY", "DENO_DEPLOYMENT_ID"], ["FIREBASE_APP_HOSTING", "FIREBASE_APP_HOSTING", { ci: true }]]; function b() { if (globalThis.process?.env) for (const e of f) { const s = e[1] || e[0]; if (globalThis.process?.env[s]) return { name: e[0].toLowerCase(), ...e[2] }; } return globalThis.process?.env?.SHELL === "/bin/jsh" && globalThis.process?.versions?.webcontainer ? { name: "stackblitz", ci: false } : { name: "", ci: false }; } var l = b(); var p = l.name; function n(e) { return e ? e !== "false" : false; } var I = globalThis.process?.platform || ""; var T = n(o.CI) || l.ci !== false; var R = n(globalThis.process?.stdout && globalThis.process?.stdout.isTTY); var d = n(o.DEBUG); var a = t === "test" || n(o.TEST); var v = n(o.MINIMAL) || T || a || !R; var A = /^win/i.test(I); var M = /^linux/i.test(I); var m = /^darwin/i.test(I); var Y = !n(o.NO_COLOR) && (n(o.FORCE_COLOR) || (R || A) && o.TERM !== "dumb" || T); var C = (globalThis.process?.versions?.node || "").replace(/^v/, "") || null; var V = Number(C?.split(".")[0]) || null; var W = globalThis.process || /* @__PURE__ */ Object.create(null); var _ = { versions: {} }; var y = new Proxy(W, { get(e, s) { if (s === "env") return o; if (s in e) return e[s]; if (s in _) return _[s]; } }); var O = globalThis.process?.release?.name === "node"; var c = !!globalThis.Bun || !!globalThis.process?.versions?.bun; var D = !!globalThis.Deno; var L = !!globalThis.fastly; var S = !!globalThis.Netlify; var u = !!globalThis.EdgeRuntime; var N = globalThis.navigator?.userAgent === "Cloudflare-Workers"; var F = [[S, "netlify"], [u, "edge-light"], [N, "workerd"], [L, "fastly"], [D, "deno"], [c, "bun"], [O, "node"]]; function G() { const e = F.find((s) => s[0]); if (e) return { name: e[1] }; } var P = G(); var K = P?.name || ""; // ../../dev/server/src/filesystem.ts import { createWriteStream, WriteStream } from "fs"; import { access, chmod, constants, mkdir, readdir, readFile, writeFile } from "fs/promises"; import { promisify } from "util"; import { unzip } from "zlib"; // ../../node_modules/.pnpm/env-paths@3.0.0/node_modules/env-paths/index.js import path from "path"; import os from "os"; import process2 from "process"; var homedir = os.homedir(); var tmpdir = os.tmpdir(); var { env } = process2; var macos = (name) => { const library = path.join(homedir, "Library"); return { data: path.join(library, "Application Support", name), config: path.join(library, "Preferences", name), cache: path.join(library, "Caches", name), log: path.join(library, "Logs", name), temp: path.join(tmpdir, name) }; }; var windows = (name) => { const appData = env.APPDATA || path.join(homedir, "AppData", "Roaming"); const localAppData = env.LOCALAPPDATA || path.join(homedir, "AppData", "Local"); return { // Data/config/cache/log are invented by me as Windows isn't opinionated about this data: path.join(localAppData, name, "Data"), config: path.join(appData, name, "Config"), cache: path.join(localAppData, name, "Cache"), log: path.join(localAppData, name, "Log"), temp: path.join(tmpdir, name) }; }; var linux = (name) => { const username = path.basename(homedir); return { data: path.join(env.XDG_DATA_HOME || path.join(homedir, ".local", "share"), name), config: path.join(env.XDG_CONFIG_HOME || path.join(homedir, ".config"), name), cache: path.join(env.XDG_CACHE_HOME || path.join(homedir, ".cache"), name), // https://wiki.debian.org/XDGBaseDirectorySpecification#state log: path.join(env.XDG_STATE_HOME || path.join(homedir, ".local", "state"), name), temp: path.join(tmpdir, username, name) }; }; function envPaths(name, { suffix = "nodejs" } = {}) { if (typeof name !== "string") { throw new TypeError(`Expected a string, got ${typeof name}`); } if (suffix) { name += `-${suffix}`; } if (process2.platform === "darwin") { return macos(name); } if (process2.platform === "win32") { return windows(name); } return linux(name); } // ../../dev/server/src/filesystem.ts var GLOBAL_DIR_ROOT_PATH = envPaths("prisma-dev"); var unzipAsync = promisify(unzip); function getEngineCacheDirPath(version, commitHash) { return `${GLOBAL_DIR_ROOT_PATH.cache}/engine/${version}/${commitHash}`; } function getDataDirPath(name) { return `${GLOBAL_DIR_ROOT_PATH.data}/${name}`; } async function checkFileExists(filePath) { try { await access(filePath, constants.F_OK); return true; } catch (error) { if (isFileNotFoundError(error)) { return false; } throw error; } } async function writeBinaryFile(buffer, path2) { const result = await unzipAsync(buffer); await writeFile(path2, result); await chmod(path2, "755"); } async function streamAsTextTo(file, path2) { await file.stream().pipeTo(WriteStream.toWeb(createWriteStream(path2, { encoding: "utf-8" }))); } function isFileNotFoundError(error) { return error != null && typeof error === "object" && "code" in error && error.code === "ENOENT"; } async function readFileAsText(path2) { try { return await readFile(path2, { encoding: "utf-8" }); } catch (error) { if (isFileNotFoundError(error)) { return null; } throw error; } } async function ensureDirectory(path2) { await mkdir(path2, { recursive: true }); } async function readDirectoryNames(path2) { try { const dirents = await readdir(path2, { withFileTypes: true }); return dirents.reduce((names, dirent) => { if (dirent.isDirectory() && !dirent.name.startsWith(".")) { names.push(dirent.name); } return names; }, []); } catch (error) { if (isFileNotFoundError(error)) { return []; } throw error; } } // ../../dev/server/src/engine.ts var { PRISMA_DEV_FORCE_ENGINE_BINARY_DOWNLOAD, PRISMA_DEV_FORCE_ENGINE_BINARY_PATH, PRISMA_DEV_FORCE_NETWORK_DELAY_MS } = y.env; var Engine = class _Engine { static #enginesBySchemaAndClientVersion = /* @__PURE__ */ new Map(); #options; #session; constructor(options) { this.#options = options; this.#session = null; } static async get(options) { const { debug } = options; const engineId = `${options.schemaHash}:${options.clientVersion}`; try { const engine = _Engine.#enginesBySchemaAndClientVersion.get(engineId); if (engine) { return engine; } const newEngine = new _Engine(options); _Engine.#enginesBySchemaAndClientVersion.set(engineId, newEngine); if (debug) { console.debug("[Query Engine] starting...", options); } await newEngine.start(); if (debug) { console.debug("[Query Engine] started!"); } return newEngine; } finally { void _Engine.stopAll(engineId); } } static async stopAll(excludingEngineId) { const results = await Promise.allSettled( Array.from(_Engine.#enginesBySchemaAndClientVersion.entries()).filter(([engineId]) => engineId !== excludingEngineId).map(async ([engineId, engine]) => { try { await engine.stop(); } finally { _Engine.#enginesBySchemaAndClientVersion.delete(engineId); } }) ); const errors = results.filter((result) => result.status === "rejected").map((result) => result.reason); if (errors.length > 0) { throw new AggregateError(errors, "Failed to stop engines"); } } async commitTransaction(transactionId, headers) { return await this.#commitOrRollbackTransaction(transactionId, headers, "commit"); } async request(body, headers) { const { url: url2 } = await this.start(); const sanitizedHeaders = this.#sanitizeHeaders(headers); const response = await fetch(url2, { body: typeof body === "string" ? body : JSON.stringify(body), headers: { ...sanitizedHeaders, "Content-Type": "application/json" }, method: "POST" }); if (!response.ok) { throw await EngineHttpError.fromResponse(response); } return await response.text(); } async rollbackTransaction(transactionId, headers) { return await this.#commitOrRollbackTransaction(transactionId, headers, "rollback"); } async startTransaction(options, headers) { const { url: url2 } = await this.start(); const sanitizedHeaders = this.#sanitizeHeaders(headers); const response = await fetch(`${url2}/transaction/start`, { body: JSON.stringify(options), headers: { ...sanitizedHeaders, "Content-Type": "application/json" }, method: "POST" }); if (!response.ok) { throw await EngineHttpError.fromResponse(response); } return await response.json(); } async start() { if (this.#session != null) { return await this.#session; } const { promise: session, reject, resolve } = withResolvers(); this.#session = session; const engineBinaryPath = PRISMA_DEV_FORCE_ENGINE_BINARY_PATH || await this.#getEngineBinaryPath(); if (this.#options.debug) { console.debug("[Query Engine] spinning up at path...", engineBinaryPath); } const { proxySignals } = await import("foreground-child/proxy-signals"); const childProcess = spawn( engineBinaryPath, ["--enable-raw-queries", "--enable-telemetry-in-response", "--port", "0"], { env: { LOG_QUERIES: "y", PRISMA_DML: this.#options.base64Schema, QE_LOG_LEVEL: "TRACE", RUST_BACKTRACE: "1", RUST_LOG: "info" }, stdio: ["ignore", "pipe", "pipe"], windowsHide: true } ); proxySignals(childProcess); childProcess.stderr.setEncoding("utf8"); childProcess.stdout.setEncoding("utf8"); const waitForListening = (data) => { const readyMessage = data.split("\n").find((line) => line.includes("Started query engine http server")); if (!readyMessage) { return; } childProcess.stdout.removeListener("data", waitForListening); const { fields } = JSON.parse(readyMessage); if (fields == null) { return reject(new Error(`Unexpected data during initialization, "fields" are missing: ${data}`)); } const { ip, port } = fields; if (ip == null || port == null) { return reject( new Error( `This version of query-engine is not compatible with minippg, "ip" and "port" are missing in the startup log entry. Received data: ${data}` ) ); } resolve({ childProcess, url: `http://${ip}:${port}` }); }; const errorListener = (error) => { this.#session = null; reject(new EngineStartError(String(error))); childProcess.removeListener("exit", exitListener); childProcess.kill(); }; childProcess.once("error", errorListener); const exitListener = (code, signal) => { this.#session = null; reject(new EngineStartError(`Query Engine exited with code ${code} and signal ${signal}`)); }; childProcess.once("exit", exitListener); childProcess.stdout.on("data", waitForListening); if (this.#options.debug) { childProcess.stderr.on("data", console.error.bind(console, "[Query Engine]")); childProcess.stdout.on("data", console.debug.bind(console, "[Query Engine]")); } return await this.#session; } async stop() { if (this.#session == null) { return; } const { childProcess } = await this.#session; const isStillRunning = childProcess.exitCode == null && childProcess.signalCode == null; if (!isStillRunning) { return; } this.#session = null; childProcess.kill(); await once(childProcess, "exit"); } async #getEngineBinaryPath() { if (this.#options.debug) { console.debug(`[Query Engine] getting engine commit hash...`); } const commitHash = await this.#getEngineCommitHash(); if (this.#options.debug) { console.debug("[Query Engine] got engine commit hash", commitHash); } const cacheDirectoryPath = getEngineCacheDirPath(this.#options.clientVersion, commitHash); if (this.#options.debug) { console.debug("[Query Engine] cache directory path", cacheDirectoryPath); } await mkdir2(cacheDirectoryPath, { recursive: true }); const { platform } = this.#options.platform; const extension = platform === "windows" ? ".exe" : ""; const engineBinaryPath = join(cacheDirectoryPath, `query-engine-${platform}${extension}`); if (this.#options.debug) { console.debug("[Query Engine] binary path", engineBinaryPath); } const shouldDownloadEngine = PRISMA_DEV_FORCE_ENGINE_BINARY_DOWNLOAD === "1" || await checkFileExists(engineBinaryPath) === false; if (shouldDownloadEngine) { await this.#downloadEngineBinary({ commitHash, extension, engineBinaryPath }); } return engineBinaryPath; } async #getEngineCommitHash() { const response = await fetch(`https://registry.npmjs.org/@prisma/client/${this.#options.clientVersion}`); if (!response.ok) { throw new Error(`Couldn't fetch package.json from npm registry, status code: ${response.status}`); } const pkg = await response.json(); const enginesVersion = pkg.devDependencies?.["@prisma/engines-version"]; if (!enginesVersion) { throw new Error(`Couldn't find engines version in package.json`); } const commitHash = enginesVersion.split(".").at(-1); if (!commitHash) { throw new Error(`Couldn't find commit hash in engines version`); } return commitHash; } async #downloadEngineBinary(options) { const { commitHash, extension, engineBinaryPath } = options; const { binaryTarget } = this.#options.platform; const url2 = `https://binaries.prisma.sh/all_commits/${commitHash}/${binaryTarget}/query-engine${extension}.gz`; if (this.#options.debug) { console.debug("[Query Engine] downloading engine from url", url2); } const response = await fetch(url2); if (!response.ok) { throw new Error(`Couldn't download engine. URL: ${url2}, status code: ${response.status}`); } if (PRISMA_DEV_FORCE_NETWORK_DELAY_MS) { await setTimeout(Number(PRISMA_DEV_FORCE_NETWORK_DELAY_MS)); } await writeBinaryFile(await response.arrayBuffer(), engineBinaryPath); if (this.#options.debug) { console.debug("[Query Engine] downloaded and saved at", engineBinaryPath); } } #sanitizeHeaders(headers) { const sanitizedHeaders = {}; for (const [key, value] of Object.entries(headers)) { if (value != null) { sanitizedHeaders[key] = value; } } return sanitizedHeaders; } async #commitOrRollbackTransaction(transactionId, headers, action) { const { url: url2 } = await this.#session; const sanitizedHeaders = this.#sanitizeHeaders(headers); const response = await fetch(`${url2}/transaction/${transactionId}/${action}`, { headers: { ...sanitizedHeaders, "Content-Type": "application/json" }, method: "POST" }); if (!response.ok) { throw await EngineHttpError.fromResponse(response); } try { return await response.json(); } catch { return {}; } } }; function handleEngineError(error, ctx) { console.error(error); if (error instanceof EngineStartError) { return ctx.json({ EngineNotStarted: { reason: { EngineStartupError: { logs: [], msg: error.message } } } }, 500); } if (error instanceof EngineHttpError) { return ctx.text(error.responseBody, error.statusCode); } return ctx.body(null, 500); } var EngineStartError = class extends Error { name = "EngineStartError"; }; var EngineHttpError = class _EngineHttpError extends Error { constructor(action, statusCode, responseBody) { super(`${action}: Query Engine response status ${statusCode}, body: ${responseBody}`); this.action = action; this.statusCode = statusCode; this.responseBody = responseBody; } name = "EngineHttpError"; static async fromResponse(response) { const url2 = new URL(response.url); const responseBody = await response.text(); return new _EngineHttpError(url2.pathname, response.status, responseBody); } }; export { integer, minLength, minValue, parseJson, url, array, literal, looseObject, number, object, optional, string, union, pipe, safeParse, encodeAPIKey, apiKeyValidator, getDataDirPath, streamAsTextTo, readFileAsText, ensureDirectory, readDirectoryNames, withResolvers, y, Engine, handleEngineError };