@prisma/cli-init
Version:
Init CLI for Prisma
222 lines (215 loc) • 7.34 kB
JavaScript
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
import {
Engine,
apiKeyValidator,
array,
handleEngineError,
integer,
literal,
looseObject,
minLength,
minValue,
number,
object,
optional,
pipe,
safeParse,
string,
union
} from "./chunk-ASMCGOOW.js";
import "./chunk-YX4UTTNJ.js";
// ../../dev/server/src/accelerate.ts
import { Hono } from "hono/tiny";
import { validator } from "hono/validator";
// ../../dev/server/src/caching.ts
var invalidateInputSchema = object({
tags: union([pipe(array(string()), minLength(1)), literal("all")])
});
async function assertInvalidateInput(ctx) {
const { output, success } = safeParse(invalidateInputSchema, await ctx.req.json(), { abortEarly: true });
if (!success) {
return ctx.text("Invalid input", 400);
}
return output;
}
// ../../dev/server/src/schema.ts
import { Buffer } from "buffer";
var SCHEMAS_BY_HASH = /* @__PURE__ */ new Map();
async function hashSchema(base64Schema) {
const encoder = new TextEncoder();
const data = encoder.encode(base64Schema);
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
return hashHex;
}
function assertSchema(ctx) {
const schemaHash = ctx.req.param("schemaHash");
const schemas = SCHEMAS_BY_HASH.get(schemaHash);
if (schemas == null) {
return ctx.json({ EngineNotStarted: { reason: "SchemaMissing" } }, 404);
}
return { schemaHash, schemas };
}
var datasourceBlockRegex = /datasource\s+db\s+\{\s*provider\s*=\s*"postgres(!?ql)?"\s+url\s*=\s*.+\s*\}/;
async function overrideDatasource(base64Schema, connectionString) {
const schema = Buffer.from(base64Schema, "base64").toString("utf8");
const override = `datasource db {
provider = "postgresql"
url = "${connectionString.toString()}"
}`;
const schemaWithOverride = schema.replace(datasourceBlockRegex, override);
const overrideHash = await hashSchema(schemaWithOverride);
return {
base64Override: Buffer.from(schemaWithOverride, "utf8").toString("base64"),
overrideHash
};
}
// ../../dev/server/src/tracing.ts
function getTracingHeaders(ctx) {
const { req } = ctx;
return {
traceparent: req.header("traceparent"),
["X-capture-telemetry"]: req.header("X-capture-telemetry")
};
}
// ../../dev/server/src/transaction.ts
var transactionOptionsSchema = object({
isolation_level: optional(string()),
max_wait: pipe(number(), integer(), minValue(0)),
timeout: pipe(number(), integer(), minValue(0))
});
async function assertTransactionOptions(ctx) {
const { issues, output, success } = safeParse(transactionOptionsSchema, await ctx.req.json(), { abortEarly: true });
if (!success) {
return ctx.json({ EngineNotStarted: { reason: "InvalidRequest", issues } }, 400);
}
return output;
}
var transactionSchema = looseObject({
id: union([string(), number()])
});
function assertTransaction(thing, ctx) {
const { output, success } = safeParse(transactionSchema, thing);
if (!success) {
return ctx.json({ EngineMalfunction: {} }, 500);
}
return output;
}
// ../../dev/server/src/accelerate.ts
var accelerateRoute = new Hono();
accelerateRoute.post("/invalidate", validator("header", apiKeyValidator), async (ctx) => {
const invlidateInput = await assertInvalidateInput(ctx);
if (invlidateInput instanceof Response) {
return invlidateInput;
}
return ctx.body(null);
});
var SCHEMAFUL_BASE_PATH = "/:clientVersion/:schemaHash";
var schemafulRoute = accelerateRoute.basePath(SCHEMAFUL_BASE_PATH);
accelerateRoute.route("/", schemafulRoute);
var GRAPHQL_PATHS = ["/graphql", "/itx/:transactionId/graphql"];
schemafulRoute.on("POST", [...GRAPHQL_PATHS], validator("header", apiKeyValidator), async (ctx) => {
const { req } = ctx;
try {
const engine = await getEngine(ctx);
if (engine instanceof Response) {
return engine;
}
const query = await req.text();
const transactionId = req.param("transactionId");
const results = await engine.request(query, {
...getTracingHeaders(ctx),
["X-transaction-id"]: transactionId
});
return ctx.text(results);
} catch (error) {
return handleEngineError(error, ctx);
}
});
schemafulRoute.basePath("/itx/:transactionId").on("POST", ["/commit", "/rollback"], validator("header", apiKeyValidator), async (ctx) => {
const { req } = ctx;
try {
const engine = await getEngine(ctx);
if (engine instanceof Response) {
return engine;
}
const action = req.routePath.split("/").filter(Boolean).at(-1);
const method = `${action}Transaction`;
const transactionId = req.param("transactionId");
const response = await engine[method](transactionId, getTracingHeaders(ctx));
return ctx.json(response);
} catch (error) {
return handleEngineError(error, ctx);
}
});
schemafulRoute.put("/schema", validator("header", apiKeyValidator), async (ctx) => {
const { req } = ctx;
const base64Schema = await req.text();
if (!base64Schema) {
return ctx.text("Missing schema", 400);
}
const schemaHash = req.param("schemaHash");
const schemas = SCHEMAS_BY_HASH.get(schemaHash);
if (schemas == null) {
if (schemaHash !== await hashSchema(base64Schema)) {
return ctx.text("Schema hash mismatch", 400);
}
const override = await overrideDatasource(base64Schema, ctx.get("db").prismaORMConnectionString);
SCHEMAS_BY_HASH.set(schemaHash, { base64Original: base64Schema, ...override });
return ctx.text(schemaHash);
}
if (base64Schema !== schemas.base64Original) {
return ctx.text("Schema mismatch", 400);
}
return ctx.text(schemaHash);
});
schemafulRoute.post("/transaction/start", validator("header", apiKeyValidator), async (ctx) => {
const { req } = ctx;
const transactionOptions = await assertTransactionOptions(ctx);
if (transactionOptions instanceof Response) {
return transactionOptions;
}
try {
const engine = await getEngine(ctx);
if (engine instanceof Response) {
return engine;
}
const response = await engine.startTransaction(transactionOptions, getTracingHeaders(ctx));
const transaction = assertTransaction(response, ctx);
if (transaction instanceof Response) {
return transaction;
}
const { id } = transaction;
const clientVersion = req.param("clientVersion");
const port = ctx.get("port");
const protocol = ctx.get("protocol");
const schemaHash = req.param("schemaHash");
return ctx.json({
...response,
"data-proxy": {
endpoint: `${protocol}://localhost:${port}/${clientVersion}/${schemaHash}/itx/${id}`
}
});
} catch (error) {
return handleEngineError(error, ctx);
}
});
async function getEngine(ctx) {
const { req } = ctx;
const schema = assertSchema(ctx);
if (schema instanceof Response) {
return schema;
}
const { base64Override, overrideHash } = schema.schemas;
return await Engine.get({
base64Schema: base64Override,
clientVersion: process.env.PRISMA_DEV_FORCE_CLIENT_VERSION || req.param("clientVersion"),
debug: ctx.get("debug"),
platform: ctx.get("platform"),
schemaHash: overrideHash
});
}
export {
accelerateRoute
};