@fitzzero/quickdraw-core 5.1.1 → 5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1308 -219
- package/dist/{admin-DKwkIh5i.d.ts → admin-CS7JB_UH.d.ts} +2 -2
- package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-29cGgrg5.d.ts} +6 -4
- package/dist/{auth-BhWqdyb-.d.ts → auth-DtdYjrZ9.d.ts} +51 -21
- package/dist/{caller-CXTFswBO.d.ts → caller-BTwGl7vm.d.ts} +296 -33
- package/dist/chunk-2FDSKLBO.js +82 -0
- package/dist/chunk-2FDSKLBO.js.map +1 -0
- package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
- package/dist/chunk-4D2DOGAW.js.map +1 -0
- package/dist/{chunk-OECZPRPW.js → chunk-64I6MYBC.js} +162 -775
- package/dist/chunk-64I6MYBC.js.map +1 -0
- package/dist/chunk-7473HK24.js +17 -0
- package/dist/chunk-7473HK24.js.map +1 -0
- package/dist/chunk-7Y5ROPXL.js +33 -0
- package/dist/chunk-7Y5ROPXL.js.map +1 -0
- package/dist/chunk-A2RBQD66.js +7 -0
- package/dist/chunk-A2RBQD66.js.map +1 -0
- package/dist/chunk-AK23XSWD.js +16 -0
- package/dist/chunk-AK23XSWD.js.map +1 -0
- package/dist/chunk-ASAMUGHG.js +651 -0
- package/dist/chunk-ASAMUGHG.js.map +1 -0
- package/dist/{chunk-B2P7AZ25.js → chunk-CYE4UBOB.js} +6 -4
- package/dist/chunk-CYE4UBOB.js.map +1 -0
- package/dist/chunk-DKE6QO26.js +136 -0
- package/dist/chunk-DKE6QO26.js.map +1 -0
- package/dist/chunk-DNP65TD5.js +832 -0
- package/dist/chunk-DNP65TD5.js.map +1 -0
- package/dist/{chunk-H23KEFBA.js → chunk-DUBU3BB3.js} +30 -1
- package/dist/chunk-DUBU3BB3.js.map +1 -0
- package/dist/chunk-GYLWEJHW.js +19 -0
- package/dist/chunk-GYLWEJHW.js.map +1 -0
- package/dist/{chunk-SHEGLZEP.js → chunk-I3JCFS7H.js} +34 -13
- package/dist/chunk-I3JCFS7H.js.map +1 -0
- package/dist/{chunk-X5CWPX7H.js → chunk-IIQ3WMJK.js} +13 -2
- package/dist/chunk-IIQ3WMJK.js.map +1 -0
- package/dist/{chunk-RZTP4IEW.js → chunk-JVTONQFI.js} +6339 -4226
- package/dist/chunk-JVTONQFI.js.map +1 -0
- package/dist/{chunk-QEKVYG5F.js → chunk-KKQANRLG.js} +2 -2
- package/dist/chunk-KKQANRLG.js.map +1 -0
- package/dist/{chunk-CDKG4TFA.js → chunk-MPQAT55F.js} +38 -205
- package/dist/chunk-MPQAT55F.js.map +1 -0
- package/dist/chunk-NO4M6PO5.js +101 -0
- package/dist/chunk-NO4M6PO5.js.map +1 -0
- package/dist/{chunk-TBMKJ26R.js → chunk-NW6U45HX.js} +3 -1
- package/dist/chunk-NW6U45HX.js.map +1 -0
- package/dist/chunk-NX2V6SIL.js +202 -0
- package/dist/chunk-NX2V6SIL.js.map +1 -0
- package/dist/{chunk-ZIVPHYRG.js → chunk-NZHA4TZD.js} +72 -175
- package/dist/chunk-NZHA4TZD.js.map +1 -0
- package/dist/{chunk-2PWMUVC7.js → chunk-OCZJ4EYV.js} +518 -27
- package/dist/chunk-OCZJ4EYV.js.map +1 -0
- package/dist/{chunk-REX5YPHX.js → chunk-PHCURHC7.js} +76 -21
- package/dist/chunk-PHCURHC7.js.map +1 -0
- package/dist/{chunk-4YO5H5ON.js → chunk-Q4OGQM5I.js} +4 -10
- package/dist/chunk-Q4OGQM5I.js.map +1 -0
- package/dist/chunk-QSU47XEX.js +13 -0
- package/dist/chunk-QSU47XEX.js.map +1 -0
- package/dist/{chunk-DD4SKCNO.js → chunk-RZXJTDH5.js} +13 -2
- package/dist/chunk-RZXJTDH5.js.map +1 -0
- package/dist/{chunk-Z2LZ7IZ7.js → chunk-SN3OZVEQ.js} +5 -31
- package/dist/chunk-SN3OZVEQ.js.map +1 -0
- package/dist/{chunk-4DIQHASK.js → chunk-SQ5VUG77.js} +28 -8
- package/dist/chunk-SQ5VUG77.js.map +1 -0
- package/dist/chunk-STH5DLQP.js +1192 -0
- package/dist/chunk-STH5DLQP.js.map +1 -0
- package/dist/{chunk-QCHKWIRS.js → chunk-VZFJTKIW.js} +13 -13
- package/dist/{chunk-QCHKWIRS.js.map → chunk-VZFJTKIW.js.map} +1 -1
- package/dist/{chunk-VSQBHPWH.js → chunk-X4ZU4QH5.js} +54 -22
- package/dist/chunk-X4ZU4QH5.js.map +1 -0
- package/dist/chunk-XD7SRDUY.js +188 -0
- package/dist/chunk-XD7SRDUY.js.map +1 -0
- package/dist/chunk-XH2IZVLT.js +62 -0
- package/dist/chunk-XH2IZVLT.js.map +1 -0
- package/dist/chunk-Z7I6SONO.js +825 -0
- package/dist/chunk-Z7I6SONO.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +132 -112
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/core.d.ts +387 -0
- package/dist/client/core.js +109 -0
- package/dist/client/index.d.ts +52 -203
- package/dist/client/index.js +59 -218
- package/dist/client/index.js.map +1 -1
- package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-CUUNJwWs.d.ts} +3 -3
- package/dist/{connection-Cr1BU07W.d.ts → connection-2EeQ_Et0.d.ts} +22 -11
- package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Bx5HOcYK.d.ts} +67 -17
- package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-DAMANT79.d.ts} +46 -13
- package/dist/{envelope-Cp3YcVxC.d.ts → envelope-BMBaxppV.d.ts} +216 -10
- package/dist/{http-Djj2Inuu.d.ts → http-YzLAar3w.d.ts} +76 -60
- package/dist/index.d.ts +8 -7
- package/dist/index.js +82 -25
- package/dist/index.js.map +1 -1
- package/dist/{infer-Teo1xpsd.d.ts → infer-Br62cnyW.d.ts} +82 -11
- package/dist/logger-Yz93KzdV.d.ts +30 -0
- package/dist/{metrics-BdBu5o8G.d.ts → metrics-CTVpw0gu.d.ts} +2 -2
- package/dist/origins-kvpxnVcW.d.ts +8 -0
- package/dist/parser.js +2 -1
- package/dist/prisma/index.d.ts +14 -7
- package/dist/prisma/index.js +279 -70
- package/dist/prisma/index.js.map +1 -1
- package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
- package/dist/rateLimit-5RKBFLUR.js.map +1 -0
- package/dist/remote-N7OUAGOW.js +15 -0
- package/dist/remote-N7OUAGOW.js.map +1 -0
- package/dist/server/auth/index.d.ts +82 -33
- package/dist/server/auth/index.js +277 -270
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/express/index.d.ts +9 -2
- package/dist/server/express/index.js +1 -1
- package/dist/server/index.d.ts +268 -84
- package/dist/server/index.js +664 -418
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +89 -27
- package/dist/server/mcp/index.js +281 -62
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-DVa8W-yR.d.ts → sharing-BrsmlDv_.d.ts} +3 -3
- package/dist/testing/client.d.ts +14 -14
- package/dist/testing/client.js +19 -10
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts +50 -13
- package/dist/testing/index.js +113 -21
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +17 -9
- package/dist/tracked-BR5b2O-U.d.ts +43 -0
- package/dist/{types-Cu0vmx7c.d.ts → types-CLRCQGnO.d.ts} +4 -3
- package/dist/types-tMagHbjy.d.ts +151 -0
- package/dist/utils/index.d.ts +16 -4
- package/dist/utils/index.js +6 -3
- package/package.json +5 -1
- package/dist/chunk-2PWMUVC7.js.map +0 -1
- package/dist/chunk-4DIQHASK.js.map +0 -1
- package/dist/chunk-4YO5H5ON.js.map +0 -1
- package/dist/chunk-B2P7AZ25.js.map +0 -1
- package/dist/chunk-CDKG4TFA.js.map +0 -1
- package/dist/chunk-DD4SKCNO.js.map +0 -1
- package/dist/chunk-H23KEFBA.js.map +0 -1
- package/dist/chunk-OECZPRPW.js.map +0 -1
- package/dist/chunk-QEKVYG5F.js.map +0 -1
- package/dist/chunk-REX5YPHX.js.map +0 -1
- package/dist/chunk-RT6OILOI.js.map +0 -1
- package/dist/chunk-RZTP4IEW.js.map +0 -1
- package/dist/chunk-SHEGLZEP.js.map +0 -1
- package/dist/chunk-TBMKJ26R.js.map +0 -1
- package/dist/chunk-VSQBHPWH.js.map +0 -1
- package/dist/chunk-X5CWPX7H.js.map +0 -1
- package/dist/chunk-YSWH776Y.js +0 -13
- package/dist/chunk-YSWH776Y.js.map +0 -1
- package/dist/chunk-Z2LZ7IZ7.js.map +0 -1
- package/dist/chunk-ZIVPHYRG.js.map +0 -1
- package/dist/logger-BY28acW-.d.ts +0 -16
- /package/dist/{rateLimit-ZMIZJUZF.js.map → client/core.js.map} +0 -0
package/dist/prisma/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/prisma/nested.ts","../../src/prisma/operations.ts","../../src/prisma/trackPrisma.ts"],"sourcesContent":["// Nested writes (RFC 0003 section 5.2): a `data` value that writes a related\n// row, such as `{ labels: { create: [...] } }`, reaches Prisma's query hook\n// only as the parent operation, so the related rows' writes are not tracked.\n// They are found by shape and reported as a development warning; the lint\n// rule `no-nested-write` catches them before they run.\n//\n// The check reads shapes, not the schema, so it also looks at each key's\n// value: a relation operation takes rows (an object or a list), and `delete`\n// and `disconnect` on a to-one relation take `true`. A JSON column's value\n// such as `{ create: true, update: false, delete: false }` is therefore not a\n// nested write; one whose keys hold objects still is.\n\n/** The keys of a relation operation, in the order a warning names them. */\nconst NESTED_KEYS = [\n \"create\",\n \"createMany\",\n \"connect\",\n \"connectOrCreate\",\n \"disconnect\",\n \"set\",\n \"update\",\n \"updateMany\",\n \"upsert\",\n \"delete\",\n \"deleteMany\",\n] as const;\n\n/** Relation operations that also take `true` (a to-one relation); the rest take rows. */\nconst FLAG_KEYS: ReadonlySet<string> = new Set([\"delete\", \"disconnect\"]);\n\nfunction isPlainObject(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction isRows(value: unknown): boolean {\n return Array.isArray(value) || isPlainObject(value);\n}\n\n/**\n * `set` also sets a scalar (`{ title: { set: \"x\" } }`) or a scalar list; on a\n * relation it takes the rows to connect, which are objects.\n */\nfunction isRelationSet(value: unknown): boolean {\n return Array.isArray(value) ? value.some(isPlainObject) : isPlainObject(value);\n}\n\n/**\n * Whether `value[key]` is a relation operation, judged by what the key\n * holds: rows (an object or a list) for every operation, `true` for\n * `delete` and `disconnect`, rows given as objects for `set`.\n */\nfunction writesRelation(value: Readonly<Record<string, unknown>>, key: string): boolean {\n if (!Object.hasOwn(value, key)) {\n return false;\n }\n const operand = value[key];\n if (key === \"set\") {\n return isRelationSet(operand);\n }\n return isRows(operand) || (FLAG_KEYS.has(key) && operand === true);\n}\n\nfunction nestedKey(value: unknown): string | undefined {\n if (!isPlainObject(value)) {\n return undefined;\n }\n return NESTED_KEYS.find((key) => writesRelation(value, key));\n}\n\n/** One nested write found in a write's `data`. */\nexport interface NestedWrite {\n /** The relation field, for example `\"labels\"`. */\n readonly field: string;\n /** The nested operation, for example `\"create\"`. */\n readonly operation: string;\n}\n\n/** The nested writes in `data`, one per relation field that has one. */\nexport function findNestedWrites(data: unknown): NestedWrite[] {\n if (!isPlainObject(data)) {\n return [];\n }\n const found: NestedWrite[] = [];\n for (const [field, value] of Object.entries(data)) {\n const operation = nestedKey(value);\n if (operation !== undefined) {\n found.push({ field, operation });\n }\n }\n return found;\n}\n","// The Prisma operation table (RFC 0003 section 5.2): for each write, how the\n// tracking hook learns the ids it touched, the fields it set, and the\n// interested columns' values before and after, and what that costs.\n//\n// | Operation | Recorded as | Ids and values from | Extra statements |\n// |---------------------|-------------|------------------------------------|------------------------------|\n// | create | create | the result | none |\n// | upsert | create, or | the result; old values from a read | one read, only when `update` |\n// | | update when | that also says the row existed | sets an interested column |\n// | | read found | | |\n// | update | update | the result; old values from a read | one read, only when `data` |\n// | | | | sets an interested column |\n// | delete | delete | the result (the deleted row) | none |\n// | createMany | create | rewritten to createManyAndReturn | none |\n// | updateMany | update | rewritten to updateManyAndReturn | as updateManyAndReturn |\n// | createManyAndReturn | create | the result | none |\n// | updateManyAndReturn | update | the result; old values from a read | one read, only when `data` |\n// | | | | sets an interested column |\n// | deleteMany | delete | a read with the same `where` | one read |\n//\n// `fields` are the keys of `data` (for upsert, of `update` when the row\n// existed, of `create` when it did not, and of both when no read told; such\n// a create is marked `mayHaveExisted`).\n// When a `select` (or `omit`) would hide the `id` or an interested column,\n// the hook adds it and strips it from the result again, so the caller gets\n// exactly what it asked for. Reads go through the open interactive\n// transaction's client, so they see its uncommitted rows. A `deleteMany`\n// with a `limit` deletes exactly the rows its read found.\n//\n// Inside an array-form `$transaction([...])` an operation cannot be replaced\n// by another one, so `createMany` and `updateMany` run as they are there:\n// `updateMany` reads its ids first, and `createMany` is tracked only when\n// every row it creates has an explicit `id`. A batch has no transaction\n// client, so every read made first there (`deleteMany`'s and `updateMany`'s\n// ids, an `update`'s old values) runs on the root client, outside the batch,\n// and misses what the batch's earlier statements changed: a development\n// warning says so once per model and operation.\n//\n// A write that certainly changed nothing records nothing (finding F7.2 of\n// the quickdraw-chat review), so no frame, delta, topic change,\n// `refreshEntry` or `affects` hop follows it. Only the write itself tells:\n//\n// - a write that matched no row (`updateMany`, `updateManyAndReturn` or\n// `deleteMany`; in a batch, an `updateMany` answering count 0);\n// - a `data` (or an upsert's `update`) with nothing to write, `{}` or only\n// `undefined` values, for which Prisma writes nothing at all.\n//\n// A write that sets a column to the value it held is recorded like any\n// other. Comparing the values the hook read before the write with the ones\n// it returned cannot tell: that read is not atomic with the write (in an\n// array-form batch it runs before the whole batch, and elsewhere another\n// write may land between the two), so a real change would be lost and its\n// subscribers left on a value the database no longer holds. rc.5 skipped\n// such writes; the final review of the release candidates showed both.\n//\n// An upsert whose `update` sets nothing changes a row only when it creates\n// one, and nothing it returns tells which it did. Its read replaces it:\n// `findUnique` with its `where` and selection answers for a row that exists\n// (one statement, as the upsert was), and only a missing row runs the upsert\n// after it, recorded as a create (one statement more). In a batch, where no\n// operation can be replaced, it is still recorded as a create that may have\n// found its row.\n\nimport { quietly } from \"../server/devWarnings\";\nimport type { WriteRecord } from \"../server/uow/types\";\nimport type { WriteTracker } from \"../server/uow/unitOfWork\";\nimport { findNestedWrites } from \"./nested\";\n\n/** A Prisma operation's arguments. */\nexport type Args = Readonly<Record<string, unknown>>;\n\n/** A row a Prisma operation returned. */\nexport type Row = Readonly<Record<string, unknown>>;\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** The model methods the hook's own queries use. */\nexport interface Delegate {\n findMany(args: Args): Promise<Row[]>;\n findUnique(args: Args): Promise<Row | null>;\n count(args: Args): Promise<number>;\n createManyAndReturn(args: Args): Promise<Row[]>;\n updateManyAndReturn(args: Args): Promise<Row[]>;\n}\n\n/** What every operation handler shares. */\nexport interface Runtime {\n readonly tracker: WriteTracker;\n /** The model's delegate on the open interactive transaction's client, or else the root client's. */\n delegate(model: string): Delegate;\n interestOf(model: string): readonly string[];\n /** Models whose writes run untracked: no usable `id` column. */\n readonly untracked: Set<string>;\n}\n\n/** One write operation, as the hook received it. */\nexport interface Operation {\n readonly runtime: Runtime;\n /** The model, named as the client names it: `\"task\"`. */\n readonly model: string;\n /** The Prisma operation: `\"deleteMany\"`. */\n readonly operation: string;\n readonly args: Args;\n readonly query: (args: Args) => Promise<unknown>;\n}\n\n/**\n * Thrown when the hook's own read failed validation before the write ran;\n * the hook then runs the write as the caller wrote it (`runUntracked`).\n */\nexport class Untrackable extends Error {\n override readonly name = \"Untrackable\";\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isValidationError(error: unknown): boolean {\n return error instanceof Error && error.name === \"PrismaClientValidationError\";\n}\n\n/** Stops tracking `model` for the life of the process, and says why once. */\nfunction untrack(op: Operation, reason: string): void {\n if (op.runtime.untracked.has(op.model)) {\n return;\n }\n op.runtime.untracked.add(op.model);\n op.runtime.tracker.logger.warn(\n `Writes to ${op.model} are not tracked: ${reason}. Tracked models need a string id column named \"id\"`,\n { category: \"quickdraw.writes\", model: op.model },\n );\n}\n\n/**\n * Runs the operation as the caller wrote it, after a query the hook built\n * failed validation (a model without an `id` column, or an interested column\n * it does not have). The hook stops tracking the model only when the\n * caller's own query then works: an error in the caller's arguments is\n * theirs, and reaches them.\n */\nexport async function runUntracked(op: Operation, reason: string): Promise<unknown> {\n const result = await op.query(op.args);\n untrack(op, reason);\n return result;\n}\n\nfunction idOf(row: Row): string | undefined {\n const { id } = row;\n if (typeof id === \"string\") {\n return id;\n }\n return typeof id === \"number\" || typeof id === \"bigint\" ? String(id) : undefined;\n}\n\nfunction pick(row: Row, columns: readonly string[]): Values | undefined {\n const present = columns.filter((column) => Object.hasOwn(row, column));\n return present.length === 0\n ? undefined\n : Object.fromEntries(present.map((column) => [column, row[column]]));\n}\n\nfunction keysOf(data: unknown): string[] {\n if (Array.isArray(data)) {\n return [...new Set(data.flatMap((item) => keysOf(item)))];\n }\n return isRecord(data) ? Object.keys(data) : [];\n}\n\nfunction rowsOf(result: unknown): Row[] {\n if (Array.isArray(result)) {\n return result.filter(isRecord);\n }\n return isRecord(result) ? [result] : [];\n}\n\n/** The keys of `data` Prisma writes: those whose value is not `undefined`. */\nfunction writtenKeys(data: unknown): string[] {\n return isRecord(data)\n ? Object.entries(data)\n .filter(([, value]) => value !== undefined)\n .map(([key]) => key)\n : [];\n}\n\n/** True for a `data` Prisma writes nothing for: an object with no key whose value is set. */\nexport function writesNothing(data: unknown): boolean {\n return isRecord(data) && writtenKeys(data).length === 0;\n}\n\n/** Counts a statement the hook runs past itself (`op.query`), and hands it to the development checks. */\nfunction countOwn(op: Operation, operation: string, args: Args): void {\n op.runtime.tracker.countStatement();\n op.runtime.tracker.observe({ model: op.model, operation, args });\n}\n\nfunction warnNested(op: Operation, data: unknown): void {\n for (const { field, operation } of findNestedWrites(data)) {\n op.runtime.tracker.warn({\n kind: \"nested-write\",\n subject: `${op.model}.${field}.${operation}`,\n message: `A nested write (${op.model}.${field}: { ${operation} }) is not tracked; only the ${op.model} row is. Write related rows through their own model`,\n meta: { model: op.model, field, operation },\n });\n }\n}\n\n/** The interested columns `data` sets. */\nfunction touchedInterest(op: Operation, data: unknown): string[] {\n const keys = new Set(keysOf(data));\n return op.runtime.interestOf(op.model).filter((column) => keys.has(column));\n}\n\n/** `args` with `columns` added to its `select`, or no longer omitted, and the columns that were added. */\nfunction widen(args: Args, columns: readonly string[]): { args: Args; added: string[] } {\n const { select, omit } = args;\n if (isRecord(select)) {\n const added = columns.filter((column) => select[column] !== true);\n const widened = { ...select, ...Object.fromEntries(added.map((column) => [column, true])) };\n return { args: added.length === 0 ? args : { ...args, select: widened }, added };\n }\n if (isRecord(omit)) {\n const added = columns.filter((column) => omit[column] === true);\n const widened = { ...omit, ...Object.fromEntries(added.map((column) => [column, false])) };\n return { args: added.length === 0 ? args : { ...args, omit: widened }, added };\n }\n return { args, added: [] };\n}\n\nfunction strip(result: unknown, added: readonly string[]): unknown {\n const without = (row: unknown): unknown =>\n isRecord(row)\n ? Object.fromEntries(Object.entries(row).filter(([key]) => !added.includes(key)))\n : row;\n return Array.isArray(result) ? result.map(without) : without(result);\n}\n\n/**\n * Runs the operation with the `id` and interested columns in its result,\n * and returns the caller's result plus the rows to record. When adding them\n * fails validation (a model without an `id` column), the operation runs as\n * the caller wrote it and its rows are not recorded.\n */\nasync function runWidened(op: Operation): Promise<{ result: unknown; rows: Row[] }> {\n const { args, added } = widen(op.args, [\"id\", ...op.runtime.interestOf(op.model)]);\n if (added.length === 0) {\n const result = await op.query(op.args);\n return { result, rows: rowsOf(result) };\n }\n let result: unknown;\n try {\n result = await op.query(args);\n } catch (error) {\n if (!isValidationError(error)) {\n throw error;\n }\n return { result: await runUntracked(op, \"selecting its id failed\"), rows: [] };\n }\n return { result: strip(result, added), rows: rowsOf(result) };\n}\n\n/**\n * Warns once per model and operation that a read made first inside an\n * array-form `$transaction` runs on the root client: an array-form batch\n * has no transaction client to read through, so the read does not see what\n * the batch's earlier statements changed.\n */\nfunction warnBatchRead(op: Operation): void {\n if (!op.runtime.tracker.inBatch()) {\n return;\n }\n op.runtime.tracker.warn({\n kind: \"batch-read\",\n subject: `${op.model}.${op.operation}`,\n message: `${op.operation} on ${op.model} inside an array-form $transaction reads its rows first on the root client, outside the batch, so rows the batch's earlier statements changed may be missed; use an interactive transaction to read inside it`,\n meta: { model: op.model, operation: op.operation },\n });\n}\n\n/**\n * Reads `columns` of the rows `where` matches, by id, through the transaction\n * when one is open. The read is the tracker's own, not the app's, so the\n * development checks of statements leave it alone.\n */\nasync function readBefore(\n op: Operation,\n where: unknown,\n columns: readonly string[],\n options: { readonly unique: boolean; readonly take?: unknown },\n): Promise<Map<string, Values>> {\n warnBatchRead(op);\n const select = Object.fromEntries([\"id\", ...columns].map((column) => [column, true]));\n const delegate = op.runtime.delegate(op.model);\n let rows: Row[];\n try {\n if (options.unique) {\n const row = await quietly(() => delegate.findUnique({ where, select }));\n rows = row === null ? [] : [row];\n } else {\n rows = await quietly(() =>\n delegate.findMany({\n where,\n select,\n ...(options.take === undefined ? {} : { take: options.take }),\n }),\n );\n }\n } catch (error) {\n if (isValidationError(error)) {\n throw new Untrackable(\"reading its id failed\", { cause: error });\n }\n throw error;\n }\n const before = new Map<string, Values>();\n for (const row of rows) {\n const id = idOf(row);\n if (id !== undefined) {\n before.set(id, pick(row, columns) ?? {});\n }\n }\n return before;\n}\n\nfunction writesOf(\n op: Operation,\n kind: WriteRecord[\"op\"],\n rows: readonly Row[],\n fields: readonly string[],\n before?: ReadonlyMap<string, Values>,\n): WriteRecord[] {\n const interest = op.runtime.interestOf(op.model);\n const writes: WriteRecord[] = [];\n for (const row of rows) {\n const id = idOf(row);\n if (id === undefined) {\n untrack(op, \"its rows have no id\");\n return [];\n }\n const values = pick(row, interest);\n const old = kind === \"delete\" ? values : before?.get(id);\n const after = kind === \"delete\" ? undefined : values;\n writes.push({\n model: op.model,\n id,\n op: kind,\n fields,\n ...(old === undefined || Object.keys(old).length === 0 ? {} : { before: old }),\n ...(after === undefined ? {} : { after }),\n });\n }\n return writes;\n}\n\nfunction record(op: Operation, writes: readonly WriteRecord[]): void {\n op.runtime.tracker.record(writes);\n}\n\nasync function create(op: Operation): Promise<unknown> {\n warnNested(op, op.args.data);\n const { result, rows } = await runWidened(op);\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.data)));\n return result;\n}\n\n/** The selection of a read that returns what `args` (an upsert's) would: its `select`, `include` and `omit`. */\nfunction selectionOf(args: Args): Args {\n return Object.fromEntries(\n [\"select\", \"include\", \"omit\"]\n .filter((key) => args[key] !== undefined)\n .map((key) => [key, args[key]]),\n );\n}\n\n/**\n * An upsert whose `update` sets nothing (see the top of this file): the\n * read that tells whether its row exists takes its place, and answers it\n * when the row is there; only a missing row runs the upsert.\n */\nasync function upsertWithoutUpdate(op: Operation): Promise<unknown> {\n warnNested(op, op.args.create);\n const { args, added } = widen(op.args, [\"id\", ...op.runtime.interestOf(op.model)]);\n let found: Row | null;\n try {\n // Through the hook, which counts it as this call's one statement.\n found = await op.runtime\n .delegate(op.model)\n .findUnique({ where: op.args.where, ...selectionOf(args) });\n } catch (error) {\n if (!isValidationError(error)) {\n throw error;\n }\n // The hook counted the read that failed; the upsert runs in its place.\n return runUntracked(op, \"reading its id failed\");\n }\n if (found !== null) {\n // Prisma writes nothing to a row that exists when `update` sets nothing: no change.\n return strip(found, added);\n }\n countOwn(op, op.operation, op.args);\n const { result, rows } = await runWidened(op);\n // Created, unless another transaction created the row in between: then it may have existed.\n const writes = writesOf(op, \"create\", rows, keysOf(op.args.create));\n record(\n op,\n writes.map((write) => ({ ...write, mayHaveExisted: true as const })),\n );\n return result;\n}\n\nasync function upsert(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.update) && !op.runtime.tracker.inBatch()) {\n return upsertWithoutUpdate(op);\n }\n warnNested(op, op.args.create);\n warnNested(op, op.args.update);\n const touched = touchedInterest(op, op.args.update);\n // Reading the interested columns first also tells whether the row existed.\n const before =\n touched.length === 0\n ? undefined\n : await readBefore(op, op.args.where, touched, { unique: true });\n const { result, rows } = await runWidened(op);\n if (before !== undefined && before.size > 0) {\n record(op, writesOf(op, \"update\", rows, keysOf(op.args.update), before));\n } else if (before === undefined) {\n // Nothing read: the row may have existed, and been updated.\n const writes = writesOf(op, \"create\", rows, keysOf([op.args.create, op.args.update]));\n record(\n op,\n writes.map((write) => ({ ...write, mayHaveExisted: true as const })),\n );\n } else {\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.create)));\n }\n return result;\n}\n\nasync function update(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.data)) {\n // Prisma only reads the row (and answers NOT_FOUND without one): nothing to record.\n return op.query(op.args);\n }\n warnNested(op, op.args.data);\n const touched = touchedInterest(op, op.args.data);\n const before =\n touched.length === 0\n ? undefined\n : await readBefore(op, op.args.where, touched, { unique: true });\n const { result, rows } = await runWidened(op);\n record(op, writesOf(op, \"update\", rows, keysOf(op.args.data), before));\n return result;\n}\n\nasync function remove(op: Operation): Promise<unknown> {\n const { result, rows } = await runWidened(op);\n record(op, writesOf(op, \"delete\", rows, []));\n return result;\n}\n\nasync function createManyAndReturn(op: Operation): Promise<unknown> {\n const { result, rows } = await runWidened(op);\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.data)));\n return result;\n}\n\nasync function updateManyAndReturn(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.data)) {\n // Prisma only reads the rows `where` matches: nothing to record.\n return op.query(op.args);\n }\n const touched = touchedInterest(op, op.args.data);\n const before =\n touched.length === 0\n ? undefined\n : await readBefore(op, op.args.where, touched, { unique: false });\n const { result, rows } = await runWidened(op);\n // Matching no row, it returns none, and records nothing.\n record(op, writesOf(op, \"update\", rows, keysOf(op.args.data), before));\n return result;\n}\n\n/** `createMany` inside an array-form transaction: tracked when every row names its id. */\nasync function createManyInBatch(op: Operation): Promise<unknown> {\n const items = (Array.isArray(op.args.data) ? op.args.data : [op.args.data]).filter(isRecord);\n const result = await op.query(op.args);\n const rows = items.filter((item) => idOf(item) !== undefined);\n if (rows.length === items.length) {\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.data)));\n } else {\n op.runtime.tracker.warn({\n kind: \"batch-create-many\",\n subject: op.model,\n message: `createMany on ${op.model} inside an array-form $transaction cannot report the rows it created, so they are not tracked; give each row an id, or use an interactive transaction`,\n meta: { model: op.model },\n });\n }\n return result;\n}\n\n/**\n * `updateMany` inside an array-form transaction: its ids are read first,\n * before the batch runs. With a `limit`, every row the read found is\n * recorded, which may be more rows than were updated.\n */\nasync function updateManyInBatch(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.data)) {\n return op.query(op.args);\n }\n const before = await readBefore(op, op.args.where, touchedInterest(op, op.args.data), {\n unique: false,\n });\n const result = await op.query(op.args);\n // Only a count comes back: 0 means it updated nothing, whatever the read found.\n if (isRecord(result) && result.count === 0) {\n return result;\n }\n const rows = [...before.keys()].map((id) => ({ id }));\n record(op, writesOf(op, \"update\", rows, keysOf(op.args.data), before));\n return result;\n}\n\n/**\n * `createMany` and `updateMany` outside a batch: the `...AndReturn` form,\n * through the transaction's client when one is open, which the hook then\n * records like any other call of it.\n */\nasync function rewrite(\n op: Operation,\n run: (delegate: Delegate, args: Args) => Promise<Row[]>,\n): Promise<unknown> {\n let rows: Row[];\n try {\n rows = await run(op.runtime.delegate(op.model), { ...op.args, select: { id: true } });\n } catch (error) {\n if (!isValidationError(error)) {\n throw error;\n }\n op.runtime.tracker.countStatement();\n return runUntracked(op, \"selecting its id failed\");\n }\n return { count: rows.length };\n}\n\nfunction createMany(op: Operation): Promise<unknown> {\n if (op.runtime.tracker.inBatch()) {\n return createManyInBatch(op);\n }\n return rewrite(op, (delegate, args) => delegate.createManyAndReturn(args));\n}\n\nfunction updateMany(op: Operation): Promise<unknown> {\n if (op.runtime.tracker.inBatch()) {\n return updateManyInBatch(op);\n }\n if (writesNothing(op.args.data)) {\n // As it is: Prisma writes nothing and answers count 0, which the rewrite would not.\n return op.query(op.args);\n }\n return rewrite(op, (delegate, args) => delegate.updateManyAndReturn(args));\n}\n\nasync function deleteMany(op: Operation): Promise<unknown> {\n const { where, limit } = op.args;\n const interest = op.runtime.interestOf(op.model);\n const before = await readBefore(op, where, interest, { unique: false, take: limit });\n const ids = [...before.keys()];\n // With a limit, which rows go is up to the database: delete the rows read.\n const args =\n limit === undefined\n ? op.args\n : { ...op.args, where: { AND: [where ?? {}, { id: { in: ids } }] } };\n const result = await op.query(args);\n const rows = ids.map((id) => ({ id, ...before.get(id) }));\n record(op, writesOf(op, \"delete\", rows, []));\n return result;\n}\n\n/**\n * The write operations the hook tracks, by Prisma operation name. Every\n * other operation passes through untouched.\n */\nexport const WRITE_OPERATIONS: Readonly<Record<string, (op: Operation) => Promise<unknown>>> =\n Object.freeze({\n create,\n upsert,\n update,\n delete: remove,\n createMany,\n createManyAndReturn,\n updateMany,\n updateManyAndReturn,\n deleteMany,\n });\n\n/**\n * Whether a tracked operation hands its work to another one, which then\n * counts the statement (`createMany` and `updateMany` outside a batch, an\n * `upsert` whose `update` sets nothing outside a batch: its read): the hook\n * counts every other operation itself.\n */\nexport function delegates(runtime: Runtime, operation: string, args: Args | undefined): boolean {\n if (runtime.tracker.inBatch()) {\n return false;\n }\n switch (operation) {\n case \"createMany\":\n return true;\n case \"updateMany\":\n return !writesNothing(args?.data);\n case \"upsert\":\n return writesNothing(args?.update);\n default:\n return false;\n }\n}\n","// `trackPrisma` (RFC 0003 sections 5.2 and 5.4): wraps an app's Prisma\n// client so every write made through it is recorded into the unit of work it\n// runs in. In 4.1 only `BaseService.create/update/delete` were observed\n// (4.1 `src/server/BaseService.ts:769-827`); a raw `prisma.task.update`\n// was invisible, and every live update needed a hand-written emit.\n//\n// Two client extensions, both public Prisma API:\n//\n// 1. a `query` hook on every operation records writes (`operations.ts`) and\n// counts statements;\n// 2. a `client` extension replaces `$transaction`, so writes inside a\n// transaction are buffered and join the unit of work only once it commits.\n// It calls the `$transaction` of the client from step 1, so the\n// transaction's client carries the hook. Transactions are found through\n// that wrapper and `AsyncLocalStorage`, never through Prisma internals.\n//\n// Make it the last extension applied: an extension added after it still\n// runs outside transactions, but not on a transaction's client.\n\nimport { consoleLogger, type Logger } from \"../contract/logger\";\nimport { quietly } from \"../server/devWarnings\";\nimport {\n createInterestRegistry,\n modelKey,\n STORAGE_KEY,\n storageOf,\n type CountArgs,\n type FindManyArgs,\n type StorageAdapter,\n} from \"../server/storage\";\nimport { createWriteTracker, type WriteTracker } from \"../server/uow/unitOfWork\";\nimport {\n delegates,\n runUntracked,\n Untrackable,\n WRITE_OPERATIONS,\n type Args,\n type Delegate,\n type Operation,\n type Runtime,\n} from \"./operations\";\n\n/** Options of {@link trackPrisma}. */\nexport interface TrackPrismaOptions {\n /**\n * Interested columns per model, whose values writes report in `before`\n * and `after`: `{ task: [\"projectId\", \"status\"] }`. The framework adds the\n * columns its collections and access policies need with\n * `storage.registerInterest`; this is for the app's own sinks.\n */\n readonly interest?: Readonly<Record<string, readonly string[]>>;\n /**\n * Receives warnings until a dispatcher is created with this client; then\n * the dispatcher's logger does. Default: the console logger.\n */\n readonly logger?: Logger;\n /**\n * Warn about writes outside any unit of work and about nested writes.\n * Default: on unless `NODE_ENV` is `\"production\"`.\n */\n readonly development?: boolean;\n}\n\n/** The part of a Prisma client `trackPrisma` relies on: client extensions. */\nexport interface PrismaClientLike {\n $extends(extension: never): unknown;\n}\n\n/** The client as `trackPrisma` calls it. */\ninterface ExtendableClient {\n $extends(extension: object): ExtendedClient;\n}\n\ninterface ExtendedClient extends ExtendableClient {\n $transaction(arg: unknown, options?: unknown): Promise<unknown>;\n}\n\n/** What a query extension's `$allOperations` hook receives. */\ninterface QueryHookArgs {\n readonly model?: string;\n readonly operation: string;\n readonly args: Args | undefined;\n readonly query: (args: Args | undefined) => Promise<unknown>;\n}\n\nfunction isClient(value: unknown): value is ExtendableClient {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"$extends\") === \"function\"\n );\n}\n\nfunction delegateOf(client: unknown, model: string): Delegate {\n const delegate: unknown =\n typeof client === \"object\" && client !== null ? Reflect.get(client, model) : undefined;\n if (typeof delegate !== \"object\" || delegate === null) {\n throw new TypeError(`The tracked Prisma client has no model \"${model}\"`);\n }\n return delegate as Delegate;\n}\n\n/** Counts one statement the hook is about to run, and hands a model's to the development checks. */\nfunction count(\n runtime: Runtime,\n model: string | undefined,\n operation: string,\n args: Args | undefined,\n): void {\n runtime.tracker.countStatement();\n if (model !== undefined) {\n runtime.tracker.observe({ model: modelKey(model), operation, args });\n }\n}\n\nfunction createHook(runtime: Runtime) {\n return async function track({ model, operation, args, query }: QueryHookArgs): Promise<unknown> {\n const handler = model === undefined ? undefined : WRITE_OPERATIONS[operation];\n if (model === undefined || handler === undefined || runtime.untracked.has(modelKey(model))) {\n count(runtime, model, operation, args);\n return query(args);\n }\n if (!delegates(runtime, operation, args)) {\n count(runtime, model, operation, args);\n }\n const op: Operation = { runtime, model: modelKey(model), operation, args: args ?? {}, query };\n try {\n return await handler(op);\n } catch (error) {\n if (error instanceof Untrackable) {\n return runUntracked(op, error.message);\n }\n throw error;\n }\n };\n}\n\n/** `$transaction`, in both forms, inside a transaction frame of the tracker. */\nasync function transaction(\n tracker: WriteTracker,\n hooked: ExtendedClient,\n arg: unknown,\n options: unknown,\n): Promise<unknown> {\n const interactive = typeof arg === \"function\";\n const frame = tracker.openTransaction(interactive ? \"interactive\" : \"batch\");\n try {\n const result = interactive\n ? await hooked.$transaction((client: unknown) => {\n frame.setClient(client);\n return frame.run(() => (arg as (client: unknown) => unknown)(client));\n }, options)\n : await frame.run(() => hooked.$transaction(arg, options));\n frame.commit();\n return result;\n } catch (error) {\n frame.rollback();\n throw error;\n }\n}\n\n/**\n * `StorageAdapter.nullable`: Prisma validates a filter against the schema\n * before sending it, and refuses `{ column: null }` on a required column. The\n * answer is kept for the life of the client: one statement per optional\n * column, none for a required one.\n */\nfunction createNullability(\n delegate: (model: string) => Delegate,\n): (model: string, column: string) => Promise<boolean> {\n const known = new Map<string, boolean>();\n return async (model, column) => {\n const key = `${modelKey(model)}\\u0000${column}`;\n const kept = known.get(key);\n if (kept !== undefined) {\n return kept;\n }\n let nullable = true;\n try {\n await quietly(() => delegate(modelKey(model)).count({ where: { [column]: null } }));\n } catch (error) {\n if (!(error instanceof Error && error.name === \"PrismaClientValidationError\")) {\n throw error;\n }\n nullable = false;\n }\n known.set(key, nullable);\n return nullable;\n };\n}\n\n/**\n * The adapter the framework reads through. Its reads are the framework's own\n * (access checks, subscriptions, flushes, kits), so the development checks\n * of statements leave them alone.\n */\nfunction createStorage(\n tracker: WriteTracker,\n interest: ReturnType<typeof createInterestRegistry>,\n delegate: (model: string) => Delegate,\n): StorageAdapter {\n return Object.freeze({\n findMany: (model: string, args: FindManyArgs = {}) =>\n quietly(() => delegate(modelKey(model)).findMany(args as Args)),\n count: (model: string, args: CountArgs = {}) =>\n quietly(() => delegate(modelKey(model)).count(args as Args)),\n onWrite: tracker.onWrite,\n countStatements: tracker.countStatements,\n registerInterest: interest.register,\n interestOf: interest.of,\n inTransaction: () => tracker.transactionClient() !== undefined || tracker.inBatch(),\n nullable: createNullability(delegate),\n unitOfWork: tracker.unitOfWork,\n });\n}\n\n/**\n * Wraps a Prisma client so the framework sees every write made through it:\n * `create`, `update`, `upsert`, `delete` and their `Many` forms, inside and\n * outside transactions. Pass the result as `db` to `initQuickdraw`'s app and\n * to `createServer`, which find its storage adapter on it (`storageOf`).\n * Nested writes, raw SQL and database cascades are not seen; record those\n * with `ctx.touch`.\n *\n * Prefer interactive transactions (`db.$transaction(async (tx) => ...)`). An\n * array-form `db.$transaction([...])` has no transaction client, so the rows\n * a `deleteMany` or `updateMany` there reads first (and an `update`'s old\n * values) are read on the root client, outside the batch: rows the batch's\n * earlier statements created or changed may be missed, and their frames\n * with them. A development warning names the model and operation once.\n *\n * @example\n * export const db = trackPrisma(new PrismaClient({ adapter }));\n * export const qd = initQuickdraw<{ db: typeof db; principal: AppPrincipal }>();\n * const server = qd.createServer({ app, services, db, auth });\n */\nexport function trackPrisma<C extends PrismaClientLike>(\n client: C,\n options: TrackPrismaOptions = {},\n): C {\n if (!isClient(client)) {\n throw new TypeError(\"trackPrisma: client must be a Prisma client\");\n }\n if (storageOf(client) !== undefined) {\n throw new TypeError(\"trackPrisma: this client is tracked already; pass the untracked client\");\n }\n const tracker = createWriteTracker({\n logger: options.logger ?? consoleLogger,\n development: options.development,\n });\n const interest = createInterestRegistry(options.interest);\n // The client with the hook; the hook's own reads use it outside transactions.\n let root: ExtendedClient | undefined;\n const delegate = (model: string): Delegate =>\n delegateOf(tracker.transactionClient() ?? root, model);\n const runtime: Runtime = { tracker, delegate, interestOf: interest.of, untracked: new Set() };\n const hooked = client.$extends({\n name: \"quickdraw-tracking\",\n query: { $allOperations: createHook(runtime) },\n });\n root = hooked;\n const tracked = hooked.$extends({\n name: \"quickdraw-transactions\",\n client: {\n $transaction: (arg: unknown, txOptions?: unknown) =>\n transaction(tracker, hooked, arg, txOptions),\n [STORAGE_KEY]: createStorage(tracker, interest, delegate),\n },\n });\n return tracked as unknown as C;\n}\n"],"mappings":"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","names":["result"]}
|
|
1
|
+
{"version":3,"sources":["../../src/prisma/links.ts","../../src/prisma/operations.ts","../../src/prisma/schemaText.ts","../../src/prisma/trackPrisma.ts"],"sourcesContent":["// The junction links a tracked delete of a via entry model reads first (RFC\n// 0003 sections 5.2 and 7.2; the 5.1 audit's COLL-3). A `via` collection\n// registers its junction as its entries' links (`registerLinks`); a `delete`\n// or `deleteMany` of an entry then reads the junction rows that link the\n// rows it deletes, through the open transaction, and records them in each\n// write's `links`, possibly none, so its flush tells only the scopes a\n// deleted entry was linked to. A junction the client does not have, or a\n// read that fails validation (a column it does not have), leaves the links\n// unknown, and warns once: such a delete's collections are told as for a\n// row nobody can place, and the model stays tracked.\n//\n// The links are read in a statement of their own just before the delete,\n// as `deleteMany` reads its ids: under the database's default isolation\n// (read committed), and always outside an interactive transaction, a link\n// another unit commits in between is removed by the delete's cascade\n// without being read, so the scope it put the entry in keeps the entry\n// until that scope is read again.\n\nimport { quietly } from \"../server/devWarnings\";\nimport type { WriteRecord } from \"../server/uow/types\";\nimport type { Delegate, Row, Runtime } from \"./operations\";\n\n/** Per entry id, per junction model: the junction rows linking it. */\nexport type Links = ReadonlyMap<string, Record<string, Row[]>>;\n\nconst UNREAD = new WeakMap<Runtime, Set<string>>();\n\n/** Says once per model and junction that a delete's links could not be read. */\nfunction warnUnread(runtime: Runtime, model: string, junction: string): void {\n const warned = UNREAD.get(runtime) ?? new Set<string>();\n UNREAD.set(runtime, warned);\n const key = `${model}\\u0000${junction}`;\n if (warned.has(key)) {\n return;\n }\n warned.add(key);\n runtime.tracker.logger.warn(\n `Reading the ${junction} rows that link a deleted ${model} failed, so its deletes tell every subscribed scope of its via lists, as for a row nobody can place`,\n { category: \"quickdraw.writes\", model, junction },\n );\n}\n\n/**\n * The junction rows that link each of `ids`, rows of `model` about to be\n * deleted: per id, per registered junction, possibly none. One statement\n * per junction. `undefined` when `model` has no links or `ids` is empty\n * (nothing is read), or when a read failed validation.\n */\nexport async function readLinks(\n runtime: Runtime,\n model: string,\n ids: readonly string[],\n): Promise<Links | undefined> {\n const links = runtime.linksOf(model);\n if (links.length === 0 || ids.length === 0) {\n return undefined;\n }\n const byId = new Map(\n ids.map((id) => [id, Object.fromEntries(links.map((link) => [link.model, [] as Row[]]))]),\n );\n for (const link of links) {\n const select = Object.fromEntries(\n [link.entry, ...link.columns].map((column) => [column, true]),\n );\n let delegate: Delegate;\n try {\n delegate = runtime.delegate(link.model);\n } catch {\n // A junction model the client does not have.\n warnUnread(runtime, model, link.model);\n return undefined;\n }\n let rows: Row[];\n try {\n rows = await quietly(() =>\n delegate.findMany({ where: { [link.entry]: { in: [...ids] } }, select }),\n );\n } catch (error) {\n if (error instanceof Error && error.name === \"PrismaClientValidationError\") {\n warnUnread(runtime, model, link.model);\n return undefined;\n }\n throw error;\n }\n for (const row of rows) {\n const entry = row[link.entry];\n if (typeof entry === \"string\") {\n byId.get(entry)?.[link.model]?.push(row);\n }\n }\n }\n return byId;\n}\n\n/** `writes`, each with its row's links when they were read. */\nexport function withLinks(writes: readonly WriteRecord[], links: Links | undefined): WriteRecord[] {\n return writes.map((write) => {\n const own = links?.get(write.id);\n return own === undefined ? write : { ...write, links: own };\n });\n}\n","// The Prisma operation table (RFC 0003 section 5.2): for each write, how the\n// tracking hook learns the ids it touched, the fields it set, and the\n// interested columns' values before and after, and what that costs.\n//\n// | Operation | Recorded as | Ids and values from | Extra statements |\n// |---------------------|-------------|------------------------------------|------------------------------|\n// | create | create | the result | none |\n// | upsert | create, or | the result; old values from a read | one read, only when `update` |\n// | | update when | that also says the row existed | sets an interested column or |\n// | | read found | | holds a nested write |\n// | update | update | the result; old values from a read | one read, only when `data` |\n// | | | | sets an interested column or |\n// | | | | holds a nested write |\n// | delete | delete | the result (the deleted row) | none; for a via entry model, |\n// | | | | one read per junction, and |\n// | | | | one for the id when `where` |\n// | | | | names no `id` |\n// | createMany | create | rewritten to createManyAndReturn | none |\n// | updateMany | update | rewritten to updateManyAndReturn | as updateManyAndReturn |\n// | createManyAndReturn | create | the result | none |\n// | updateManyAndReturn | update | the result; old values from a read | one read, only when `data` |\n// | | | | sets an interested column |\n// | deleteMany | delete | a read with the same `where` | one read; for a via entry |\n// | | | | model, one per junction more |\n// | | | | when the read found rows |\n//\n// A `delete` or `deleteMany` of a via entry model (one whose junction a\n// `via` collection registered: `registerLinks`) reads the junction rows that\n// link the rows it deletes first, through the open transaction, and records\n// them in each write's `links` (possibly none), so its flush tells only the\n// scopes the row was linked to (the 5.1 audit's COLL-3; `links.ts`).\n//\n// `fields` are the keys of `data` (for upsert, of `update` when the row\n// existed, of `create` when it did not, and of both when no read told; such\n// a create is marked `mayHaveExisted`). An `update` (or an upsert's\n// `update`) whose `data` holds a nested write may set a foreign key through\n// a relation (`project: { connect }`, `parent: { disconnect: true }`), which\n// its keys do not name: it reads every interested column first and lists\n// them all in `fields`, so an access change it makes is seen (the 5.1\n// audit's DATA-1). The rows the nested write itself creates, changes or\n// deletes are not seen.\n// When a `select` (or `omit`) would hide the `id` or an interested column,\n// the hook adds it and strips it from the result again, so the caller gets\n// exactly what it asked for. Reads go through the open interactive\n// transaction's client, so they see its uncommitted rows. A `deleteMany`\n// with a `limit` deletes exactly the rows its read found.\n//\n// Inside an array-form `$transaction([...])` an operation cannot be replaced\n// by another one, so `createMany` and `updateMany` run as they are there:\n// `updateMany` reads its ids first, and `createMany` is tracked only when\n// every row it creates has an explicit `id`. A batch has no transaction\n// client, so every read made first there (`deleteMany`'s and `updateMany`'s\n// ids, an `update`'s old values) runs on the root client, outside the batch,\n// and misses what the batch's earlier statements changed: a development\n// warning says so once per model and operation.\n//\n// A write that certainly changed nothing records nothing (finding F7.2 of\n// the quickdraw-chat review), so no frame, delta, topic change,\n// `refreshEntry` or `affects` hop follows it. Only the write itself tells:\n//\n// - a write that matched no row (`updateMany`, `updateManyAndReturn` or\n// `deleteMany`; in a batch, an `updateMany` answering count 0);\n// - a `data` (or an upsert's `update`) with nothing to write, `{}` or only\n// `undefined` values, for which Prisma writes nothing at all.\n//\n// A write that sets a column to the value it held is recorded like any\n// other. Comparing the values the hook read before the write with the ones\n// it returned cannot tell: that read is not atomic with the write (in an\n// array-form batch it runs before the whole batch, and elsewhere another\n// write may land between the two), so a real change would be lost and its\n// subscribers left on a value the database no longer holds. rc.5 skipped\n// such writes; the final review of the release candidates showed both.\n//\n// An upsert whose `update` sets nothing changes a row only when it creates\n// one, and nothing it returns tells which it did. Its read replaces it:\n// `findUnique` with its `where` and selection answers for a row that exists\n// (one statement, as the upsert was), and only a missing row runs the upsert\n// after it, recorded as a create (one statement more). In a batch, where no\n// operation can be replaced, it is still recorded as a create that may have\n// found its row.\n\nimport { quietly } from \"../server/devWarnings\";\nimport type { LinkInterest } from \"../server/storage\";\nimport type { WriteRecord } from \"../server/uow/types\";\nimport type { WriteTracker } from \"../server/uow/unitOfWork\";\nimport { readLinks, withLinks, type Links } from \"./links\";\nimport { findNestedWrites } from \"./nested\";\n\n/** A Prisma operation's arguments. */\nexport type Args = Readonly<Record<string, unknown>>;\n\n/** A row a Prisma operation returned. */\nexport type Row = Readonly<Record<string, unknown>>;\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** The model methods the hook's own queries use. */\nexport interface Delegate {\n findMany(args: Args): Promise<Row[]>;\n findUnique(args: Args): Promise<Row | null>;\n count(args: Args): Promise<number>;\n createManyAndReturn(args: Args): Promise<Row[]>;\n updateManyAndReturn(args: Args): Promise<Row[]>;\n}\n\n/** What every operation handler shares. */\nexport interface Runtime {\n readonly tracker: WriteTracker;\n /** The model's delegate on the open interactive transaction's client, or else the root client's. */\n delegate(model: string): Delegate;\n interestOf(model: string): readonly string[];\n /** The junctions whose links a delete of `model` reads first (`registerLinks`). */\n linksOf(model: string): readonly LinkInterest[];\n /** Models whose writes run untracked: no usable `id` column. */\n readonly untracked: Set<string>;\n}\n\n/** One write operation, as the hook received it. */\nexport interface Operation {\n readonly runtime: Runtime;\n /** The model, named as the client names it: `\"task\"`. */\n readonly model: string;\n /** The Prisma operation: `\"deleteMany\"`. */\n readonly operation: string;\n readonly args: Args;\n readonly query: (args: Args) => Promise<unknown>;\n}\n\n/**\n * Thrown when the hook's own read failed validation before the write ran;\n * the hook then runs the write as the caller wrote it (`runUntracked`).\n */\nexport class Untrackable extends Error {\n override readonly name = \"Untrackable\";\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isValidationError(error: unknown): boolean {\n return error instanceof Error && error.name === \"PrismaClientValidationError\";\n}\n\n/** Stops tracking `model` for the life of the process, and says why once. */\nfunction untrack(op: Operation, reason: string): void {\n if (op.runtime.untracked.has(op.model)) {\n return;\n }\n op.runtime.untracked.add(op.model);\n op.runtime.tracker.logger.warn(\n `Writes to ${op.model} are not tracked: ${reason}. Tracked models need a string id column named \"id\"`,\n { category: \"quickdraw.writes\", model: op.model },\n );\n}\n\n/**\n * Runs the operation as the caller wrote it, after a query the hook built\n * failed validation (a model without an `id` column, or an interested column\n * it does not have). The hook stops tracking the model only when the\n * caller's own query then works: an error in the caller's arguments is\n * theirs, and reaches them.\n */\nexport async function runUntracked(op: Operation, reason: string): Promise<unknown> {\n const result = await op.query(op.args);\n untrack(op, reason);\n return result;\n}\n\n/** A row's id as the tracker keys it: a string, or a number or bigint as a string. */\nexport function idOf(row: Row): string | undefined {\n const { id } = row;\n if (typeof id === \"string\") {\n return id;\n }\n return typeof id === \"number\" || typeof id === \"bigint\" ? String(id) : undefined;\n}\n\nfunction pick(row: Row, columns: readonly string[]): Values | undefined {\n const present = columns.filter((column) => Object.hasOwn(row, column));\n return present.length === 0\n ? undefined\n : Object.fromEntries(present.map((column) => [column, row[column]]));\n}\n\nfunction keysOf(data: unknown): string[] {\n if (Array.isArray(data)) {\n return [...new Set(data.flatMap((item) => keysOf(item)))];\n }\n return isRecord(data) ? Object.keys(data) : [];\n}\n\nfunction rowsOf(result: unknown): Row[] {\n if (Array.isArray(result)) {\n return result.filter(isRecord);\n }\n return isRecord(result) ? [result] : [];\n}\n\n/** The keys of `data` Prisma writes: those whose value is not `undefined`. */\nfunction writtenKeys(data: unknown): string[] {\n return isRecord(data)\n ? Object.entries(data)\n .filter(([, value]) => value !== undefined)\n .map(([key]) => key)\n : [];\n}\n\n/** True for a `data` Prisma writes nothing for: an object with no key whose value is set. */\nexport function writesNothing(data: unknown): boolean {\n return isRecord(data) && writtenKeys(data).length === 0;\n}\n\n/** Counts a statement the hook runs past itself (`op.query`), and hands it to the development checks. */\nfunction countOwn(op: Operation, operation: string, args: Args): void {\n op.runtime.tracker.countStatement();\n op.runtime.tracker.observe({ model: op.model, operation, args });\n}\n\n/**\n * Whether `data` holds a nested write, warning (in development) once per\n * write that the related rows are not tracked. It is found in every\n * environment: such a `data` may set a foreign key the tracker must read.\n */\nfunction warnNested(op: Operation, data: unknown): boolean {\n const nested = findNestedWrites(data);\n for (const { field, operation } of nested) {\n op.runtime.tracker.warn({\n kind: \"nested-write\",\n subject: `${op.model}.${field}.${operation}`,\n message: `A nested write (${op.model}.${field}: { ${operation} }) is not tracked: the related rows it creates, changes or deletes send no frames and revoke nothing. The ${op.model} row is tracked, and an update of it reads its access and scope columns first, so a foreign key a to-one connect or disconnect sets on it is seen. Write related rows through their own model, or set the foreign key column`,\n meta: { model: op.model, field, operation },\n });\n }\n return nested.length > 0;\n}\n\n/** The keys of `data` and `columns`, each once: the fields of a write that holds a nested write. */\nfunction withColumns(data: unknown, columns: readonly string[]): string[] {\n return [...new Set([...keysOf(data), ...columns])];\n}\n\n/** The interested columns `data` sets. */\nfunction touchedInterest(op: Operation, data: unknown): string[] {\n const keys = new Set(keysOf(data));\n return op.runtime.interestOf(op.model).filter((column) => keys.has(column));\n}\n\n/** `args` with `columns` added to its `select`, or no longer omitted, and the columns that were added. */\nfunction widen(args: Args, columns: readonly string[]): { args: Args; added: string[] } {\n const { select, omit } = args;\n if (isRecord(select)) {\n const added = columns.filter((column) => select[column] !== true);\n const widened = { ...select, ...Object.fromEntries(added.map((column) => [column, true])) };\n return { args: added.length === 0 ? args : { ...args, select: widened }, added };\n }\n if (isRecord(omit)) {\n const added = columns.filter((column) => omit[column] === true);\n const widened = { ...omit, ...Object.fromEntries(added.map((column) => [column, false])) };\n return { args: added.length === 0 ? args : { ...args, omit: widened }, added };\n }\n return { args, added: [] };\n}\n\nfunction strip(result: unknown, added: readonly string[]): unknown {\n const without = (row: unknown): unknown =>\n isRecord(row)\n ? Object.fromEntries(Object.entries(row).filter(([key]) => !added.includes(key)))\n : row;\n return Array.isArray(result) ? result.map(without) : without(result);\n}\n\n/**\n * Runs the operation with the `id` and interested columns in its result,\n * and returns the caller's result plus the rows to record. When adding them\n * fails validation (a model without an `id` column), the operation runs as\n * the caller wrote it and its rows are not recorded.\n */\nasync function runWidened(op: Operation): Promise<{ result: unknown; rows: Row[] }> {\n const { args, added } = widen(op.args, [\"id\", ...op.runtime.interestOf(op.model)]);\n if (added.length === 0) {\n const result = await op.query(op.args);\n return { result, rows: rowsOf(result) };\n }\n let result: unknown;\n try {\n result = await op.query(args);\n } catch (error) {\n if (!isValidationError(error)) {\n throw error;\n }\n return { result: await runUntracked(op, \"selecting its id failed\"), rows: [] };\n }\n return { result: strip(result, added), rows: rowsOf(result) };\n}\n\n/**\n * Warns once per model and operation that a read made first inside an\n * array-form `$transaction` runs on the root client: an array-form batch\n * has no transaction client to read through, so the read does not see what\n * the batch's earlier statements changed.\n */\nfunction warnBatchRead(op: Operation): void {\n if (!op.runtime.tracker.inBatch()) {\n return;\n }\n op.runtime.tracker.warn({\n kind: \"batch-read\",\n subject: `${op.model}.${op.operation}`,\n message: `${op.operation} on ${op.model} inside an array-form $transaction reads its rows first on the root client, outside the batch, so rows the batch's earlier statements changed may be missed; use an interactive transaction to read inside it`,\n meta: { model: op.model, operation: op.operation },\n });\n}\n\n/**\n * Reads `columns` of the rows `where` matches, by id, through the transaction\n * when one is open. The read is the tracker's own, not the app's, so the\n * development checks of statements leave it alone.\n */\nasync function readBefore(\n op: Operation,\n where: unknown,\n columns: readonly string[],\n options: { readonly unique: boolean; readonly take?: unknown },\n): Promise<Map<string, Values>> {\n warnBatchRead(op);\n const select = Object.fromEntries([\"id\", ...columns].map((column) => [column, true]));\n const delegate = op.runtime.delegate(op.model);\n let rows: Row[];\n try {\n if (options.unique) {\n const row = await quietly(() => delegate.findUnique({ where, select }));\n rows = row === null ? [] : [row];\n } else {\n rows = await quietly(() =>\n delegate.findMany({\n where,\n select,\n ...(options.take === undefined ? {} : { take: options.take }),\n }),\n );\n }\n } catch (error) {\n if (isValidationError(error)) {\n throw new Untrackable(\"reading its id failed\", { cause: error });\n }\n throw error;\n }\n const before = new Map<string, Values>();\n for (const row of rows) {\n const id = idOf(row);\n if (id !== undefined) {\n before.set(id, pick(row, columns) ?? {});\n }\n }\n return before;\n}\n\nfunction writesOf(\n op: Operation,\n kind: WriteRecord[\"op\"],\n rows: readonly Row[],\n fields: readonly string[],\n before?: ReadonlyMap<string, Values>,\n): WriteRecord[] {\n const interest = op.runtime.interestOf(op.model);\n const writes: WriteRecord[] = [];\n for (const row of rows) {\n const id = idOf(row);\n if (id === undefined) {\n untrack(op, \"its rows have no id\");\n return [];\n }\n const values = pick(row, interest);\n const old = kind === \"delete\" ? values : before?.get(id);\n const after = kind === \"delete\" ? undefined : values;\n writes.push({\n model: op.model,\n id,\n op: kind,\n fields,\n ...(old === undefined || Object.keys(old).length === 0 ? {} : { before: old }),\n ...(after === undefined ? {} : { after }),\n });\n }\n return writes;\n}\n\nfunction record(op: Operation, writes: readonly WriteRecord[]): void {\n op.runtime.tracker.record(writes);\n}\n\nasync function create(op: Operation): Promise<unknown> {\n warnNested(op, op.args.data);\n const { result, rows } = await runWidened(op);\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.data)));\n return result;\n}\n\n/** The selection of a read that returns what `args` (an upsert's) would: its `select`, `include` and `omit`. */\nfunction selectionOf(args: Args): Args {\n return Object.fromEntries(\n [\"select\", \"include\", \"omit\"]\n .filter((key) => args[key] !== undefined)\n .map((key) => [key, args[key]]),\n );\n}\n\n/**\n * An upsert whose `update` sets nothing (see the top of this file): the\n * read that tells whether its row exists takes its place, and answers it\n * when the row is there; only a missing row runs the upsert.\n */\nasync function upsertWithoutUpdate(op: Operation): Promise<unknown> {\n warnNested(op, op.args.create);\n const { args, added } = widen(op.args, [\"id\", ...op.runtime.interestOf(op.model)]);\n let found: Row | null;\n try {\n // Through the hook, which counts it as this call's one statement.\n found = await op.runtime\n .delegate(op.model)\n .findUnique({ where: op.args.where, ...selectionOf(args) });\n } catch (error) {\n if (!isValidationError(error)) {\n throw error;\n }\n // The hook counted the read that failed; the upsert runs in its place.\n return runUntracked(op, \"reading its id failed\");\n }\n if (found !== null) {\n // Prisma writes nothing to a row that exists when `update` sets nothing: no change.\n return strip(found, added);\n }\n countOwn(op, op.operation, op.args);\n const { result, rows } = await runWidened(op);\n // Created, unless another transaction created the row in between: then it may have existed.\n const writes = writesOf(op, \"create\", rows, keysOf(op.args.create));\n record(\n op,\n writes.map((write) => ({ ...write, mayHaveExisted: true as const })),\n );\n return result;\n}\n\nasync function upsert(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.update) && !op.runtime.tracker.inBatch()) {\n return upsertWithoutUpdate(op);\n }\n warnNested(op, op.args.create);\n // A nested write may set a foreign key through a relation: read every interested column.\n const nested = warnNested(op, op.args.update);\n const touched = nested\n ? [...op.runtime.interestOf(op.model)]\n : touchedInterest(op, op.args.update);\n // Reading the interested columns first also tells whether the row existed.\n const before =\n touched.length === 0\n ? undefined\n : await readBefore(op, op.args.where, touched, { unique: true });\n const { result, rows } = await runWidened(op);\n if (before !== undefined && before.size > 0) {\n const fields = nested ? withColumns(op.args.update, touched) : keysOf(op.args.update);\n record(op, writesOf(op, \"update\", rows, fields, before));\n } else if (before === undefined) {\n // Nothing read: the row may have existed, and been updated.\n const writes = writesOf(op, \"create\", rows, keysOf([op.args.create, op.args.update]));\n record(\n op,\n writes.map((write) => ({ ...write, mayHaveExisted: true as const })),\n );\n } else {\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.create)));\n }\n return result;\n}\n\nasync function update(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.data)) {\n // Prisma only reads the row (and answers NOT_FOUND without one): nothing to record.\n return op.query(op.args);\n }\n // A nested write may set a foreign key through a relation: read every interested column.\n const nested = warnNested(op, op.args.data);\n const touched = nested ? [...op.runtime.interestOf(op.model)] : touchedInterest(op, op.args.data);\n const before =\n touched.length === 0\n ? undefined\n : await readBefore(op, op.args.where, touched, { unique: true });\n const { result, rows } = await runWidened(op);\n const fields = nested ? withColumns(op.args.data, touched) : keysOf(op.args.data);\n record(op, writesOf(op, \"update\", rows, fields, before));\n return result;\n}\n\n/** The links of the row a `delete` names (`readLinks`): by its `where.id`, or a read of its id first. */\nasync function linksOfDelete(op: Operation): Promise<Links | undefined> {\n if (op.runtime.linksOf(op.model).length === 0) {\n return undefined;\n }\n warnBatchRead(op);\n const { where } = op.args;\n const ids =\n isRecord(where) && typeof where.id === \"string\"\n ? [where.id]\n : [...(await readBefore(op, where, [], { unique: true })).keys()];\n return await readLinks(op.runtime, op.model, ids);\n}\n\nasync function remove(op: Operation): Promise<unknown> {\n const links = await linksOfDelete(op);\n const { result, rows } = await runWidened(op);\n record(op, withLinks(writesOf(op, \"delete\", rows, []), links));\n return result;\n}\n\nasync function createManyAndReturn(op: Operation): Promise<unknown> {\n const { result, rows } = await runWidened(op);\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.data)));\n return result;\n}\n\nasync function updateManyAndReturn(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.data)) {\n // Prisma only reads the rows `where` matches: nothing to record.\n return op.query(op.args);\n }\n const touched = touchedInterest(op, op.args.data);\n const before =\n touched.length === 0\n ? undefined\n : await readBefore(op, op.args.where, touched, { unique: false });\n const { result, rows } = await runWidened(op);\n // Matching no row, it returns none, and records nothing.\n record(op, writesOf(op, \"update\", rows, keysOf(op.args.data), before));\n return result;\n}\n\n/** `createMany` inside an array-form transaction: tracked when every row names its id. */\nasync function createManyInBatch(op: Operation): Promise<unknown> {\n const items = (Array.isArray(op.args.data) ? op.args.data : [op.args.data]).filter(isRecord);\n const result = await op.query(op.args);\n const rows = items.filter((item) => idOf(item) !== undefined);\n if (rows.length === items.length) {\n record(op, writesOf(op, \"create\", rows, keysOf(op.args.data)));\n } else {\n op.runtime.tracker.warn({\n kind: \"batch-create-many\",\n subject: op.model,\n message: `createMany on ${op.model} inside an array-form $transaction cannot report the rows it created, so they are not tracked; give each row an id, or use an interactive transaction`,\n meta: { model: op.model },\n });\n }\n return result;\n}\n\n/**\n * `updateMany` inside an array-form transaction: its ids are read first,\n * before the batch runs. With a `limit`, every row the read found is\n * recorded, which may be more rows than were updated.\n */\nasync function updateManyInBatch(op: Operation): Promise<unknown> {\n if (writesNothing(op.args.data)) {\n return op.query(op.args);\n }\n const before = await readBefore(op, op.args.where, touchedInterest(op, op.args.data), {\n unique: false,\n });\n const result = await op.query(op.args);\n // Only a count comes back: 0 means it updated nothing, whatever the read found.\n if (isRecord(result) && result.count === 0) {\n return result;\n }\n const rows = [...before.keys()].map((id) => ({ id }));\n record(op, writesOf(op, \"update\", rows, keysOf(op.args.data), before));\n return result;\n}\n\n/**\n * `createMany` and `updateMany` outside a batch: the `...AndReturn` form,\n * through the transaction's client when one is open, which the hook then\n * records like any other call of it.\n */\nasync function rewrite(\n op: Operation,\n run: (delegate: Delegate, args: Args) => Promise<Row[]>,\n): Promise<unknown> {\n let rows: Row[];\n try {\n rows = await run(op.runtime.delegate(op.model), { ...op.args, select: { id: true } });\n } catch (error) {\n if (!isValidationError(error)) {\n throw error;\n }\n op.runtime.tracker.countStatement();\n return runUntracked(op, \"selecting its id failed\");\n }\n return { count: rows.length };\n}\n\nfunction createMany(op: Operation): Promise<unknown> {\n if (op.runtime.tracker.inBatch()) {\n return createManyInBatch(op);\n }\n return rewrite(op, (delegate, args) => delegate.createManyAndReturn(args));\n}\n\nfunction updateMany(op: Operation): Promise<unknown> {\n if (op.runtime.tracker.inBatch()) {\n return updateManyInBatch(op);\n }\n if (writesNothing(op.args.data)) {\n // As it is: Prisma writes nothing and answers count 0, which the rewrite would not.\n return op.query(op.args);\n }\n return rewrite(op, (delegate, args) => delegate.updateManyAndReturn(args));\n}\n\nasync function deleteMany(op: Operation): Promise<unknown> {\n const { where, limit } = op.args;\n const interest = op.runtime.interestOf(op.model);\n const before = await readBefore(op, where, interest, { unique: false, take: limit });\n const ids = [...before.keys()];\n const links = await readLinks(op.runtime, op.model, ids);\n // With a limit, which rows go is up to the database: delete the rows read.\n const args =\n limit === undefined\n ? op.args\n : { ...op.args, where: { AND: [where ?? {}, { id: { in: ids } }] } };\n const result = await op.query(args);\n const rows = ids.map((id) => ({ id, ...before.get(id) }));\n record(op, withLinks(writesOf(op, \"delete\", rows, []), links));\n return result;\n}\n\n/**\n * The write operations the hook tracks, by Prisma operation name. Every\n * other operation passes through untouched.\n */\nexport const WRITE_OPERATIONS: Readonly<Record<string, (op: Operation) => Promise<unknown>>> =\n Object.freeze({\n create,\n upsert,\n update,\n delete: remove,\n createMany,\n createManyAndReturn,\n updateMany,\n updateManyAndReturn,\n deleteMany,\n });\n\n/**\n * Whether a tracked operation hands its work to another one, which then\n * counts the statement (`createMany` and `updateMany` outside a batch, an\n * `upsert` whose `update` sets nothing outside a batch: its read): the hook\n * counts every other operation itself.\n */\nexport function delegates(runtime: Runtime, operation: string, args: Args | undefined): boolean {\n if (runtime.tracker.inBatch()) {\n return false;\n }\n switch (operation) {\n case \"createMany\":\n return true;\n case \"updateMany\":\n return !writesNothing(args?.data);\n case \"upsert\":\n return writesNothing(args?.update);\n default:\n return false;\n }\n}\n","// What a Prisma client's own schema says about its models' fields, for the\n// storage adapter's `nullable` and `trackable` (`trackPrisma.ts`). Prisma 7's\n// generated client carries the schema's text (`config.inlineSchema`), which\n// its runtime keeps on every client, extended ones included, as\n// `_engineConfig.inlineSchema`. Its runtime data model (`_runtimeDataModel`)\n// names each field's kind but not whether the field is optional, and there is\n// no runtime DMMF. Reading the text answers with no statement; the probes it\n// replaces send a filter or select Prisma refuses, which a client created\n// with `log: [\"error\"]` prints as a `prisma:error` line. Whatever the text\n// does not answer (no text, or a model or field it does not declare) is left\n// to those probes.\n//\n// Only what the answers need is read: the field lines of `model` and `view`\n// blocks (`name Type`, `Type?` optional, `Type[]` a list), the names of\n// `enum`s, and `@ignore`. Comments, block attributes (`@@id`, `@@map`) and\n// the other field attributes (`@map`, `@default`) are skipped: the answers\n// are by Prisma field name, as the probes ask.\n\nimport { modelKey } from \"../server/storage\";\n\n/** What a client's schema says, by model (either spelling) and Prisma field name. */\nexport interface PrismaSchemaFacts {\n /** Whether `column` of `model` may hold null; `undefined` when the schema does not say. */\n nullable(model: string, column: string): boolean | undefined;\n /**\n * Whether the tracker can key `model`'s rows by an `id` field: false when\n * the model has none (a composite `@@id`), true for a required `String`,\n * `Int`, `BigInt`, `Float` or enum `id`; `undefined` when the schema does\n * not say, or the answer depends on the rows (an optional `id`).\n */\n trackable(model: string): boolean | undefined;\n}\n\n/** One scalar field of a model, as its schema declares it. */\ninterface SchemaField {\n readonly type: string;\n readonly optional: boolean;\n readonly list: boolean;\n}\n\ninterface SchemaModel {\n readonly fields: ReadonlyMap<string, SchemaField>;\n readonly trackable: boolean | undefined;\n}\n\ninterface Block {\n readonly kind: string;\n readonly name: string;\n readonly lines: string[];\n}\n\n/** The runtime data model's field kinds of one model: `scalar`, `enum`, `object` (a relation). */\ntype FieldKinds = ReadonlyMap<string, string>;\n\nconst BLOCK_START = /^(\\w+)\\s+([A-Za-z_]\\w*)\\s*\\{/;\n\nconst FIELD = /^([A-Za-z_]\\w*)\\s+([A-Za-z_]\\w*)(\\([^)]*\\))?(\\[\\])?(\\?)?(?=\\s|$)/;\n\nconst IGNORED = /(?:^|\\s)@ignore(?=\\s|$|\\()/;\n\n/** The `id` types whose values the tracker keys rows by (`idOf`). */\nconst KEY_TYPES: ReadonlySet<string> = new Set([\"String\", \"Int\", \"BigInt\", \"Float\"]);\n\nconst COLUMN_KINDS: ReadonlySet<string> = new Set([\"scalar\", \"enum\"]);\n\nfunction isObject(value: unknown): value is object {\n return (typeof value === \"object\" || typeof value === \"function\") && value !== null;\n}\n\n/** `line` without its `//` or `///` comment, which never starts inside a string. */\nfunction withoutComment(line: string): string {\n let inString = false;\n for (let index = 0; index < line.length; index += 1) {\n const char = line[index];\n if (char === '\"' && line[index - 1] !== \"\\\\\") {\n inString = !inString;\n } else if (!inString && char === \"/\" && line[index + 1] === \"/\") {\n return line.slice(0, index);\n }\n }\n return line;\n}\n\n/** The schema's top-level blocks, each with its lines, comments and blank lines dropped. */\nfunction blocksOf(text: string): Block[] {\n const blocks: Block[] = [];\n let open: Block | undefined;\n for (const raw of text.split(/\\r?\\n/)) {\n const line = withoutComment(raw).trim();\n if (line === \"\") {\n continue;\n }\n if (open !== undefined) {\n if (line === \"}\") {\n open = undefined;\n } else {\n open.lines.push(line);\n }\n continue;\n }\n const start = BLOCK_START.exec(line);\n if (start !== null) {\n const block: Block = { kind: start[1] ?? \"\", name: start[2] ?? \"\", lines: [] };\n blocks.push(block);\n // `model X {}` closes on the line it opens.\n open = line.slice(start[0].length).trim() === \"}\" ? undefined : block;\n }\n }\n return blocks;\n}\n\n/** The field kinds the runtime data model lists for `model`, or `undefined`. */\nfunction kindsOf(runtimeDataModel: unknown, model: string): FieldKinds | undefined {\n const models: unknown = isObject(runtimeDataModel)\n ? Reflect.get(runtimeDataModel, \"models\")\n : undefined;\n const entry: unknown =\n isObject(models) && Object.hasOwn(models, model) ? Reflect.get(models, model) : undefined;\n const fields: unknown = isObject(entry) ? Reflect.get(entry, \"fields\") : undefined;\n if (!Array.isArray(fields)) {\n return undefined;\n }\n const kinds = new Map<string, string>();\n for (const field of fields as unknown[]) {\n const name: unknown = isObject(field) ? Reflect.get(field, \"name\") : undefined;\n const kind: unknown = isObject(field) ? Reflect.get(field, \"kind\") : undefined;\n if (typeof name === \"string\" && typeof kind === \"string\") {\n kinds.set(name, kind);\n }\n }\n return kinds;\n}\n\n/**\n * Whether the field `name` of type `type` is a column: as the runtime data\n * model says when it lists the model (a relation is `object`), else unless\n * its type names a model, view or composite type, or is `Unsupported`.\n */\nfunction isColumn(\n name: string,\n type: string,\n kinds: FieldKinds | undefined,\n records: ReadonlySet<string>,\n): boolean {\n if (kinds !== undefined) {\n return COLUMN_KINDS.has(kinds.get(name) ?? \"\");\n }\n return type !== \"Unsupported\" && !records.has(type);\n}\n\nfunction trackableOf(\n fields: ReadonlyMap<string, SchemaField>,\n kinds: FieldKinds | undefined,\n enums: ReadonlySet<string>,\n): boolean | undefined {\n const id = fields.get(\"id\");\n if (id === undefined) {\n // The runtime knows an `id` column the text did not show: let the probe say.\n return kinds !== undefined && COLUMN_KINDS.has(kinds.get(\"id\") ?? \"\") ? undefined : false;\n }\n if (id.optional || id.list) {\n return undefined;\n }\n return KEY_TYPES.has(id.type) || enums.has(id.type) ? true : undefined;\n}\n\nfunction modelOf(\n block: Block,\n kinds: FieldKinds | undefined,\n records: ReadonlySet<string>,\n enums: ReadonlySet<string>,\n): SchemaModel {\n const fields = new Map<string, SchemaField>();\n for (const line of block.lines) {\n const field = FIELD.exec(line);\n const [, name = \"\", type = \"\", , list, optional] = field ?? [];\n if (field !== null && !IGNORED.test(line) && isColumn(name, type, kinds, records)) {\n fields.set(name, { type, optional: optional !== undefined, list: list !== undefined });\n }\n }\n return { fields, trackable: trackableOf(fields, kinds, enums) };\n}\n\n/**\n * Reads a Prisma schema's text: what each model's fields say about null, and\n * whether the model has an `id` the tracker can key. A relation field is not\n * a column: the runtime data model's kinds say so when given (a client's\n * `_runtimeDataModel`), else a field whose type is a model. A model the text\n * does not declare, or marks `@@ignore`, is not answered.\n */\nexport function parsePrismaSchema(text: string, runtimeDataModel?: unknown): PrismaSchemaFacts {\n const blocks = blocksOf(text);\n const named = (...kinds: string[]): Set<string> =>\n new Set(blocks.filter((block) => kinds.includes(block.kind)).map((block) => block.name));\n const enums = named(\"enum\");\n const records = named(\"model\", \"view\", \"type\");\n const models = new Map<string, SchemaModel>();\n for (const block of blocks) {\n const ignored = block.lines.some((line) => /^@@ignore\\b/.test(line));\n if ((block.kind === \"model\" || block.kind === \"view\") && !ignored) {\n const kinds = kindsOf(runtimeDataModel, block.name);\n models.set(modelKey(block.name), modelOf(block, kinds, records, enums));\n }\n }\n return Object.freeze({\n nullable(model: string, column: string): boolean | undefined {\n const field = models.get(modelKey(model))?.fields.get(column);\n return field === undefined ? undefined : field.optional && !field.list;\n },\n trackable: (model: string): boolean | undefined => models.get(modelKey(model))?.trackable,\n });\n}\n\n/**\n * The schema text a Prisma client carries (`_engineConfig.inlineSchema`, on\n * an extended client too), or `undefined`. Never throws.\n */\nexport function schemaTextOf(client: unknown): string | undefined {\n try {\n const config: unknown = isObject(client) ? Reflect.get(client, \"_engineConfig\") : undefined;\n const text: unknown = isObject(config) ? Reflect.get(config, \"inlineSchema\") : undefined;\n return typeof text === \"string\" && text !== \"\" ? text : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The runtime data model a Prisma client carries, or `undefined`. Never throws. */\nfunction runtimeDataModelOf(client: unknown): unknown {\n try {\n const own: unknown = isObject(client) ? Reflect.get(client, \"_runtimeDataModel\") : undefined;\n if (own !== undefined) {\n return own;\n }\n const config: unknown = isObject(client) ? Reflect.get(client, \"_engineConfig\") : undefined;\n return isObject(config) ? Reflect.get(config, \"runtimeDataModel\") : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** What `client`'s own schema says, or `undefined` when it carries no schema text. */\nexport function prismaSchemaOf(client: unknown): PrismaSchemaFacts | undefined {\n const text = schemaTextOf(client);\n return text === undefined ? undefined : parsePrismaSchema(text, runtimeDataModelOf(client));\n}\n","// `trackPrisma` (RFC 0003 sections 5.2 and 5.4): wraps an app's Prisma\n// client so every write made through it is recorded into the unit of work it\n// runs in. In 4.1 only `BaseService.create/update/delete` were observed\n// (4.1 `src/server/BaseService.ts:769-827`); a raw `prisma.task.update`\n// was invisible, and every live update needed a hand-written emit.\n//\n// Two client extensions, both public Prisma API:\n//\n// 1. a `query` hook on every operation records writes (`operations.ts`) and\n// counts statements;\n// 2. a `client` extension replaces `$transaction`, so writes inside a\n// transaction are buffered and join the unit of work only once it commits.\n// It calls the `$transaction` of the client from step 1, so the\n// transaction's client carries the hook. Transactions are found through\n// that wrapper and `AsyncLocalStorage`, never through Prisma internals.\n//\n// Make it the last extension applied: an extension added after it still\n// runs outside transactions, but not on a transaction's client.\n//\n// The storage adapter's `nullable` and `trackable` read the one Prisma\n// internal used here, the schema text the client keeps\n// (`_engineConfig.inlineSchema`, `schemaText.ts`). Without it they ask the\n// database, as before: a statement Prisma refuses, which it logs as an error.\n\nimport { consoleLogger, type Logger } from \"../contract/logger\";\nimport { quietly } from \"../server/devWarnings\";\nimport {\n createInterestRegistry,\n createLinkRegistry,\n modelKey,\n STORAGE_KEY,\n storageOf,\n type CountArgs,\n type FindManyArgs,\n type StorageAdapter,\n} from \"../server/storage\";\nimport { createWriteTracker, type WriteTracker } from \"../server/uow/unitOfWork\";\nimport {\n delegates,\n idOf,\n runUntracked,\n Untrackable,\n WRITE_OPERATIONS,\n type Args,\n type Delegate,\n type Operation,\n type Runtime,\n} from \"./operations\";\nimport { prismaSchemaOf, type PrismaSchemaFacts } from \"./schemaText\";\nimport type { Tracked } from \"./tracked\";\n\n/** Options of {@link trackPrisma}. */\nexport interface TrackPrismaOptions {\n /**\n * Interested columns per model, whose values writes report in `before`\n * and `after`: `{ task: [\"projectId\", \"status\"] }`. The framework adds the\n * columns its collections and access policies need with\n * `storage.registerInterest`; this is for the app's own sinks.\n */\n readonly interest?: Readonly<Record<string, readonly string[]>>;\n /**\n * Receives warnings until a dispatcher is created with this client; then\n * the dispatcher's logger does. Default: the console logger.\n */\n readonly logger?: Logger;\n /**\n * Warn about writes outside any unit of work and about nested writes.\n * Default: on unless `NODE_ENV` is `\"production\"`.\n */\n readonly development?: boolean;\n}\n\n/** The part of a Prisma client `trackPrisma` relies on: client extensions. */\nexport interface PrismaClientLike {\n $extends(extension: never): unknown;\n}\n\n/** The client as `trackPrisma` calls it. */\ninterface ExtendableClient {\n $extends(extension: object): ExtendedClient;\n}\n\ninterface ExtendedClient extends ExtendableClient {\n $transaction(arg: unknown, options?: unknown): Promise<unknown>;\n}\n\n/** What a query extension's `$allOperations` hook receives. */\ninterface QueryHookArgs {\n readonly model?: string;\n readonly operation: string;\n readonly args: Args | undefined;\n readonly query: (args: Args | undefined) => Promise<unknown>;\n}\n\nfunction isClient(value: unknown): value is ExtendableClient {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"$extends\") === \"function\"\n );\n}\n\nfunction delegateOf(client: unknown, model: string): Delegate {\n const delegate: unknown =\n typeof client === \"object\" && client !== null ? Reflect.get(client, model) : undefined;\n if (typeof delegate !== \"object\" || delegate === null) {\n throw new TypeError(`The tracked Prisma client has no model \"${model}\"`);\n }\n return delegate as Delegate;\n}\n\n/** Counts one statement the hook is about to run, and hands a model's to the development checks. */\nfunction count(\n runtime: Runtime,\n model: string | undefined,\n operation: string,\n args: Args | undefined,\n): void {\n runtime.tracker.countStatement();\n if (model !== undefined) {\n runtime.tracker.observe({ model: modelKey(model), operation, args });\n }\n}\n\nfunction createHook(runtime: Runtime) {\n return async function track({ model, operation, args, query }: QueryHookArgs): Promise<unknown> {\n const handler = model === undefined ? undefined : WRITE_OPERATIONS[operation];\n if (model === undefined || handler === undefined || runtime.untracked.has(modelKey(model))) {\n count(runtime, model, operation, args);\n return query(args);\n }\n if (!delegates(runtime, operation, args)) {\n count(runtime, model, operation, args);\n }\n const op: Operation = { runtime, model: modelKey(model), operation, args: args ?? {}, query };\n try {\n return await handler(op);\n } catch (error) {\n if (error instanceof Untrackable) {\n return runUntracked(op, error.message);\n }\n throw error;\n }\n };\n}\n\n/** `$transaction`, in both forms, inside a transaction frame of the tracker. */\nasync function transaction(\n tracker: WriteTracker,\n hooked: ExtendedClient,\n arg: unknown,\n options: unknown,\n): Promise<unknown> {\n const interactive = typeof arg === \"function\";\n const frame = tracker.openTransaction(interactive ? \"interactive\" : \"batch\");\n try {\n const result = interactive\n ? await hooked.$transaction((client: unknown) => {\n frame.setClient(client);\n return frame.run(() => (arg as (client: unknown) => unknown)(client));\n }, options)\n : await frame.run(() => hooked.$transaction(arg, options));\n frame.commit();\n return result;\n } catch (error) {\n frame.rollback();\n throw error;\n }\n}\n\n/**\n * `StorageAdapter.nullable`: what the client's schema says (`Type?`), with\n * no statement (`schemaText.ts`). A column the schema does not answer for is\n * probed: Prisma validates a filter against the schema before sending it,\n * and refuses `{ column: null }` on a required column (a client that logs\n * errors prints that refusal). The probe's answer is kept for the life of the\n * client: one statement per optional column, none for a required one.\n */\nfunction createNullability(\n delegate: (model: string) => Delegate,\n schema: PrismaSchemaFacts | undefined,\n): (model: string, column: string) => Promise<boolean> {\n const known = new Map<string, boolean>();\n return async (model, column) => {\n const declared = schema?.nullable(model, column);\n if (declared !== undefined) {\n return declared;\n }\n const key = `${modelKey(model)}\\u0000${column}`;\n const kept = known.get(key);\n if (kept !== undefined) {\n return kept;\n }\n let nullable = true;\n try {\n await quietly(() => delegate(modelKey(model)).count({ where: { [column]: null } }));\n } catch (error) {\n if (!(error instanceof Error && error.name === \"PrismaClientValidationError\")) {\n throw error;\n }\n nullable = false;\n }\n known.set(key, nullable);\n return nullable;\n };\n}\n\n/**\n * `StorageAdapter.trackable`: whether the tracker can key `model`'s writes,\n * that is whether its rows have an `id`, as the client's schema says, with no\n * statement (`schemaText.ts`). A model the schema does not answer for is\n * probed: one read of one row's id per model, kept for the life of the\n * client, which Prisma refuses for a model without an `id` column (a\n * composite `@@id`). Any other failure (the database down) is thrown, and\n * asked again next time.\n */\nfunction createTrackability(\n delegate: (model: string) => Delegate,\n schema: PrismaSchemaFacts | undefined,\n): (model: string) => Promise<boolean> {\n const known = new Map<string, Promise<boolean>>();\n const probe = async (key: string): Promise<boolean> => {\n try {\n const rows = await quietly(() => delegate(key).findMany({ select: { id: true }, take: 1 }));\n const [row] = Array.isArray(rows) ? (rows as Readonly<Record<string, unknown>>[]) : [];\n return row === undefined || idOf(row) !== undefined;\n } catch (error) {\n if (error instanceof Error && error.name === \"PrismaClientValidationError\") {\n return false;\n }\n throw error;\n }\n };\n return async (model) => {\n const declared = schema?.trackable(model);\n if (declared !== undefined) {\n return declared;\n }\n const key = modelKey(model);\n let answer = known.get(key);\n if (answer === undefined) {\n answer = probe(key);\n known.set(key, answer);\n answer.catch(() => {\n known.delete(key);\n });\n }\n return await answer;\n };\n}\n\n/**\n * The adapter the framework reads through. Its reads are the framework's own\n * (access checks, subscriptions, flushes, kits), so the development checks\n * of statements leave them alone.\n */\nfunction createStorage(\n tracker: WriteTracker,\n [interest, links]: readonly [\n ReturnType<typeof createInterestRegistry>,\n ReturnType<typeof createLinkRegistry>,\n ],\n delegate: (model: string) => Delegate,\n schema: PrismaSchemaFacts | undefined,\n): StorageAdapter {\n return Object.freeze({\n findMany: (model: string, args: FindManyArgs = {}) =>\n quietly(() => delegate(modelKey(model)).findMany(args as Args)),\n count: (model: string, args: CountArgs = {}) =>\n quietly(() => delegate(modelKey(model)).count(args as Args)),\n onWrite: tracker.onWrite,\n countStatements: tracker.countStatements,\n registerInterest: interest.register,\n interestOf: interest.of,\n registerLinks: links.register,\n linksOf: links.of,\n inTransaction: () => tracker.transactionClient() !== undefined || tracker.inBatch(),\n nullable: createNullability(delegate, schema),\n trackable: createTrackability(delegate, schema),\n unitOfWork: tracker.unitOfWork,\n });\n}\n\n/**\n * Wraps a Prisma client so the framework sees every write made through it:\n * `create`, `update`, `upsert`, `delete` and their `Many` forms, inside and\n * outside transactions. Pass the result as `db` to `initQuickdraw`'s app and\n * to `createServer`, which find its storage adapter on it (`storageOf`).\n * Nested writes, raw SQL and database cascades are not seen; record those\n * with `ctx.touch`.\n *\n * The result is a `Tracked<C>` (`tracked.ts`): still a `C`, but the\n * untracked client is no `Tracked<C>`, so a helper that writes takes\n * `db: Tracked<Db>` (or `TrackedTransaction<Db>`, which a transaction's `tx`\n * is too) and the compiler refuses the untracked client there.\n *\n * Prefer interactive transactions (`db.$transaction(async (tx) => ...)`). An\n * array-form `db.$transaction([...])` has no transaction client, so the rows\n * a `deleteMany` or `updateMany` there reads first (and an `update`'s old\n * values) are read on the root client, outside the batch: rows the batch's\n * earlier statements created or changed may be missed, and their frames\n * with them. A development warning names the model and operation once.\n *\n * @example\n * export const db = trackPrisma(new PrismaClient({ adapter }));\n * export const qd = initQuickdraw<{ db: typeof db; principal: AppPrincipal }>();\n * const server = qd.createServer({ app, services, db, auth });\n */\nexport function trackPrisma<C extends PrismaClientLike>(\n client: C,\n options: TrackPrismaOptions = {},\n): Tracked<C> {\n if (!isClient(client)) {\n throw new TypeError(\"trackPrisma: client must be a Prisma client\");\n }\n if (storageOf(client) !== undefined) {\n throw new TypeError(\"trackPrisma: this client is tracked already; pass the untracked client\");\n }\n const tracker = createWriteTracker({\n logger: options.logger ?? consoleLogger,\n development: options.development,\n });\n const interest = createInterestRegistry(options.interest);\n // The client with the hook; the hook's own reads use it outside transactions.\n let root: ExtendedClient | undefined;\n const delegate = (model: string): Delegate =>\n delegateOf(tracker.transactionClient() ?? root, model);\n const links = createLinkRegistry();\n const runtime: Runtime = {\n tracker,\n delegate,\n interestOf: interest.of,\n linksOf: links.of,\n untracked: new Set(),\n };\n const hooked = client.$extends({\n name: \"quickdraw-tracking\",\n query: { $allOperations: createHook(runtime) },\n });\n root = hooked;\n const tracked = hooked.$extends({\n name: \"quickdraw-transactions\",\n client: {\n $transaction: (arg: unknown, txOptions?: unknown) =>\n transaction(tracker, hooked, arg, txOptions),\n [STORAGE_KEY]: createStorage(tracker, [interest, links], delegate, prismaSchemaOf(client)),\n },\n });\n // `Tracked<C>` is a type: the client carries no mark at run time.\n return tracked as unknown as Tracked<C>;\n}\n"],"mappings":"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","names":["result"]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
createPublicApiLimiter,
|
|
8
8
|
createWebhookLimiter,
|
|
9
9
|
stripIp
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NW6U45HX.js";
|
|
11
11
|
export {
|
|
12
12
|
bearerOrIp,
|
|
13
13
|
createAuthLimiter,
|
|
@@ -18,4 +18,4 @@ export {
|
|
|
18
18
|
createWebhookLimiter,
|
|
19
19
|
stripIp
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=rateLimit-
|
|
21
|
+
//# sourceMappingURL=rateLimit-5RKBFLUR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPeerLink
|
|
3
|
+
} from "./chunk-DNP65TD5.js";
|
|
4
|
+
import {
|
|
5
|
+
controlOf
|
|
6
|
+
} from "./chunk-ASAMUGHG.js";
|
|
7
|
+
import "./chunk-2FDSKLBO.js";
|
|
8
|
+
import "./chunk-X4ZU4QH5.js";
|
|
9
|
+
import "./chunk-7Y5ROPXL.js";
|
|
10
|
+
import "./chunk-QSU47XEX.js";
|
|
11
|
+
export {
|
|
12
|
+
controlOf,
|
|
13
|
+
createPeerLink
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=remote-N7OUAGOW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { L as Logger } from '../../logger-
|
|
1
|
+
import { L as Logger } from '../../logger-Yz93KzdV.js';
|
|
2
2
|
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
-
import { M as MaybePromise, P as Principal } from '../../types-
|
|
4
|
-
import {
|
|
5
|
-
import '../../
|
|
3
|
+
import { M as MaybePromise, P as Principal } from '../../types-CLRCQGnO.js';
|
|
4
|
+
import { A as AllowedOrigin } from '../../origins-kvpxnVcW.js';
|
|
5
|
+
import { b as AuthenticateRequest, H as HttpRequest } from '../../auth-DtdYjrZ9.js';
|
|
6
|
+
import '../../infer-Br62cnyW.js';
|
|
6
7
|
import 'socket.io';
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -60,10 +61,11 @@ interface SessionCookieOptions {
|
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Sets the session cookie, under the name {@link sessionCookieNameFor} gives
|
|
63
|
-
* the response's request, so `socketAuth` and the HTTP transport read it
|
|
64
|
+
* the response's request, so `socketAuth` and the HTTP transport read it,
|
|
65
|
+
* and clears a stale `__Host-session` that would shadow it.
|
|
64
66
|
*/
|
|
65
67
|
declare function setSessionCookie(res: CookieResponse, jwt: string, options?: SessionCookieOptions): void;
|
|
66
|
-
/** Clears the session cookie `setSessionCookie` sets on the same request. */
|
|
68
|
+
/** Clears the session cookie `setSessionCookie` sets on the same request, and a stale `__Host-session` beside it. */
|
|
67
69
|
declare function clearSessionCookie(res: CookieResponse, options?: SessionCookieOptions): void;
|
|
68
70
|
|
|
69
71
|
interface JWTPayload {
|
|
@@ -86,7 +88,13 @@ interface JWTPayload {
|
|
|
86
88
|
*/
|
|
87
89
|
declare function createJWT(payload: Omit<JWTPayload, "exp" | "iat">, secret: string, expiresIn?: string): Promise<string>;
|
|
88
90
|
/**
|
|
89
|
-
* Verify and decode a JWT token.
|
|
91
|
+
* Verify and decode a JWT token: its signature and expiry, nothing more.
|
|
92
|
+
* It is never a session check: a token of a session that was signed out,
|
|
93
|
+
* logged out everywhere or revoked still verifies until the JWT expires (7
|
|
94
|
+
* days by default). Check a session token with `liveSession({ sessions,
|
|
95
|
+
* jwtSecret }, token)`, `bearerAuth(...)` or `socketAuth(...)`, which ask the
|
|
96
|
+
* session store on every call. In development it warns once per process
|
|
97
|
+
* when it verifies a token that carries a session (`sid`).
|
|
90
98
|
*
|
|
91
99
|
* @param token - The JWT token to verify
|
|
92
100
|
* @param secret - The secret key for verification
|
|
@@ -190,10 +198,12 @@ declare const googleProvider: OAuthProvider<GoogleUser>;
|
|
|
190
198
|
* via `registerMockOAuthProvider`. Users are supplied by the app (typically
|
|
191
199
|
* seeded demo accounts); no real credentials are involved.
|
|
192
200
|
*
|
|
193
|
-
*
|
|
194
|
-
* "
|
|
195
|
-
* NODE_ENV
|
|
196
|
-
*
|
|
201
|
+
* Development only: routes are mounted only when ENABLE_MOCK_OAUTH is
|
|
202
|
+
* "true" and NODE_ENV is "development" or "test" (an allowlist: an unset
|
|
203
|
+
* NODE_ENV, "prod" or "staging" mount nothing, the 5.1 audit's AUTH-3), every
|
|
204
|
+
* handler re-checks NODE_ENV at request time, and mounting them logs a
|
|
205
|
+
* warning. Apps should add a third layer and refuse to boot outside
|
|
206
|
+
* development with the flag set.
|
|
197
207
|
*/
|
|
198
208
|
|
|
199
209
|
interface MockOAuthUser {
|
|
@@ -203,6 +213,7 @@ interface MockOAuthUser {
|
|
|
203
213
|
picture?: string | null;
|
|
204
214
|
}
|
|
205
215
|
declare const DEFAULT_MOCK_PATH_PREFIX = "/auth/mock/provider";
|
|
216
|
+
/** True when ENABLE_MOCK_OAUTH is "true" and NODE_ENV is "development" or "test". */
|
|
206
217
|
declare function isMockOAuthEnabled(): boolean;
|
|
207
218
|
interface MockOAuthProviderOptions {
|
|
208
219
|
/**
|
|
@@ -259,8 +270,9 @@ interface RegisterMockOAuthOptions {
|
|
|
259
270
|
* Mount the mock OAuth provider endpoints (authorize, token, userinfo) on an
|
|
260
271
|
* Express-compatible router.
|
|
261
272
|
*
|
|
262
|
-
* No-ops (returning false) unless `isMockOAuthEnabled()` — i.e.
|
|
263
|
-
*
|
|
273
|
+
* No-ops (returning false) unless `isMockOAuthEnabled()` — i.e. without
|
|
274
|
+
* ENABLE_MOCK_OAUTH=true, or unless NODE_ENV is development or test, the
|
|
275
|
+
* routes are never mounted. Mounting them logs a warning.
|
|
264
276
|
*/
|
|
265
277
|
declare function registerMockOAuthProvider(router: MockOAuthRouter, options: RegisterMockOAuthOptions): boolean;
|
|
266
278
|
|
|
@@ -351,8 +363,8 @@ interface RequireAuthOptions {
|
|
|
351
363
|
/**
|
|
352
364
|
* Cookie to read the JWT from. Default: the names `setSessionCookie` and
|
|
353
365
|
* the auth routes set on the same request (`sessionCookieNamesFor`):
|
|
354
|
-
* `__Host-session` over HTTPS, `session`
|
|
355
|
-
*
|
|
366
|
+
* `__Host-session` over HTTPS, `__Host-session` then `session` over plain
|
|
367
|
+
* HTTP or when `COOKIE_DOMAIN` is set.
|
|
356
368
|
*/
|
|
357
369
|
cookieName?: string;
|
|
358
370
|
}
|
|
@@ -385,13 +397,6 @@ interface AuthRouteRequest extends IncomingMessage {
|
|
|
385
397
|
/** The response the routes answer: Express's, which also sets cookies. */
|
|
386
398
|
type AuthRouteResponse = ServerResponse & CookieResponse;
|
|
387
399
|
|
|
388
|
-
/**
|
|
389
|
-
* An allowed origin: exact (`"https://app.example.com"`), or a pattern over
|
|
390
|
-
* whole origins, anchored at both ends
|
|
391
|
-
* (`/^https:\/\/[a-z0-9-]+\.preview\.example\.com$/`).
|
|
392
|
-
*/
|
|
393
|
-
type AllowedOrigin = string | RegExp;
|
|
394
|
-
|
|
395
400
|
/** The cookie that carries a sign-in in progress, on a request that is not secure. */
|
|
396
401
|
declare const OAUTH_STATE_COOKIE = "qd_oauth";
|
|
397
402
|
/**
|
|
@@ -607,7 +612,8 @@ declare namespace discord {
|
|
|
607
612
|
* The development sign-in: a picker of the app's demo users, served by the
|
|
608
613
|
* routes through `registerMockOAuthProvider`. Left out (its routes answer
|
|
609
614
|
* nothing) unless `isMockOAuthEnabled()`: `ENABLE_MOCK_OAUTH=true` and
|
|
610
|
-
* `NODE_ENV`
|
|
615
|
+
* `NODE_ENV` `development` or `test` (an unset `NODE_ENV` leaves it out: set
|
|
616
|
+
* `NODE_ENV=development`). Mounting it logs a warning.
|
|
611
617
|
*/
|
|
612
618
|
declare function mock(options: MockSignInOptions): MockSignInProvider;
|
|
613
619
|
|
|
@@ -767,8 +773,8 @@ interface SocketAuthOptions<P extends Principal = Principal> {
|
|
|
767
773
|
* The session cookie's name. Default: the name the auth routes set on the
|
|
768
774
|
* same handshake: `"session"` when `COOKIE_DOMAIN` gives the cookie a
|
|
769
775
|
* domain; else `"__Host-session"` over HTTPS, where the plain name a
|
|
770
|
-
* sibling site could plant is never read, and `"session"`
|
|
771
|
-
* `"__Host-session"`
|
|
776
|
+
* sibling site could plant is never read, and `"session"` over plain HTTP,
|
|
777
|
+
* where `"__Host-session"` is read first all the same. A name given here is the only one
|
|
772
778
|
* read, on any handshake: give the routes' `cookie.name` here, or
|
|
773
779
|
* `"session"` when their `cookie.domain` is set without `COOKIE_DOMAIN`. A
|
|
774
780
|
* name the handshake repeats counts as no credential.
|
|
@@ -785,9 +791,11 @@ interface SocketAuthOptions<P extends Principal = Principal> {
|
|
|
785
791
|
* Development sign-in without a session: a socket whose handshake carries
|
|
786
792
|
* `auth: { userId }` and no token is that user, as this function answers:
|
|
787
793
|
* their principal (its `userId` the one named), or `null` to refuse the
|
|
788
|
-
* handshake (an unknown id). For a game editor or load-test bots.
|
|
789
|
-
*
|
|
790
|
-
*
|
|
794
|
+
* handshake (an unknown id). For a game editor or load-test bots. Only
|
|
795
|
+
* while `NODE_ENV` is `development` or `test`: `socketAuth` throws when it
|
|
796
|
+
* is given otherwise (an unset `NODE_ENV` included: set
|
|
797
|
+
* `NODE_ENV=development`), refuses such a handshake once `NODE_ENV` says
|
|
798
|
+
* otherwise, and `createServer` warns at startup while it is on. HTTP calls
|
|
791
799
|
* never use it. Pass it only when the app's own flag is on:
|
|
792
800
|
* `devCredentials: env.ENABLE_DEV_CREDENTIALS ? findDevUser : undefined`.
|
|
793
801
|
*/
|
|
@@ -813,13 +821,19 @@ interface CookieOriginRequest {
|
|
|
813
821
|
* `Sec-Fetch-Site` names another site, and a socket handshake only when
|
|
814
822
|
* `Sec-Fetch-Site` is `same-origin` or with `allowMissingOrigin`. A bearer
|
|
815
823
|
* token is not ambient: check only a credential that came from the cookie
|
|
816
|
-
* (`request.
|
|
824
|
+
* (`request.sessionCookie` on an HTTP `authenticate` request, where the
|
|
825
|
+
* transport hands an `authenticate` other than socketAuth's the cookie; it is
|
|
826
|
+
* in `auth.token` only for socketAuth's). Then check the session against the
|
|
827
|
+
* store, on every call (`liveSession`).
|
|
817
828
|
*
|
|
818
829
|
* @example
|
|
819
830
|
* authenticate: async (request) => {
|
|
820
|
-
* if (request.transport === "http" && request.
|
|
821
|
-
*
|
|
822
|
-
*
|
|
831
|
+
* if (request.transport === "http" && request.sessionCookie !== undefined) {
|
|
832
|
+
* if (!cookieOriginAllowed(request, allowedOrigins)) {
|
|
833
|
+
* throw new QuickdrawError("FORBIDDEN", "This page may not use the session cookie");
|
|
834
|
+
* }
|
|
835
|
+
* const session = await liveSession({ sessions, jwtSecret }, request.sessionCookie);
|
|
836
|
+
* // ...
|
|
823
837
|
* }
|
|
824
838
|
* // ...
|
|
825
839
|
* }
|
|
@@ -836,6 +850,41 @@ declare function socketAuth<P extends Principal>(options: SocketAuthOptions<P> &
|
|
|
836
850
|
}): SessionAuthenticate<P>;
|
|
837
851
|
declare function socketAuth(options: SocketAuthOptions): SessionAuthenticate<Principal>;
|
|
838
852
|
|
|
853
|
+
/** Options of {@link bearerAuth}: the auth routes' session store and secret, and how a principal is built. */
|
|
854
|
+
interface BearerAuthOptions<P extends Principal = Principal> extends SessionKeys {
|
|
855
|
+
/**
|
|
856
|
+
* Builds the principal of a session's user, for example `kind: "agent"`
|
|
857
|
+
* for an MCP caller; its `userId` must be the session's. Default
|
|
858
|
+
* `{ userId, kind: "user" }`.
|
|
859
|
+
*/
|
|
860
|
+
readonly loadPrincipal?: PrincipalLoader<P>;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* What {@link bearerAuth} returns: the principal a bearer token signs in,
|
|
864
|
+
* `null` for no token, and a rejection (`UNAUTHENTICATED`) for a token that
|
|
865
|
+
* is not a live session's.
|
|
866
|
+
*/
|
|
867
|
+
type BearerAuthenticate<P extends Principal> = (token: unknown) => Promise<P | null>;
|
|
868
|
+
/**
|
|
869
|
+
* Checks bearer tokens against the auth routes' sessions, on every call: no
|
|
870
|
+
* token (anything but a non-empty string) is anonymous (`null`); a token
|
|
871
|
+
* whose session was signed out, revoked or has expired, or a JWT without a
|
|
872
|
+
* session, is refused with `UNAUTHENTICATED`; a live session's token is its
|
|
873
|
+
* user's principal, built as `socketAuth` builds it. It records no socket
|
|
874
|
+
* session: for `createServer`'s `authenticate` use `socketAuth`.
|
|
875
|
+
*
|
|
876
|
+
* @example
|
|
877
|
+
* const verifySession = bearerAuth({ sessions, jwtSecret, loadPrincipal: (userId) => ({ userId, kind: "agent" }) });
|
|
878
|
+
* // the MCP bridge's principal hook
|
|
879
|
+
* createMcpRegistry({ ..., principal: (request) => verifySession(request.transport === "http" ? request.token : process.env.AGENT_TOKEN) });
|
|
880
|
+
* // an authenticate that takes bearer tokens only
|
|
881
|
+
* createHttpRouter({ dispatcher, auth: { authenticate: ({ auth }) => verifySession(auth.token) } });
|
|
882
|
+
*/
|
|
883
|
+
declare function bearerAuth<P extends Principal>(options: BearerAuthOptions<P> & {
|
|
884
|
+
readonly loadPrincipal: PrincipalLoader<P>;
|
|
885
|
+
}): BearerAuthenticate<P>;
|
|
886
|
+
declare function bearerAuth(options: BearerAuthOptions): BearerAuthenticate<Principal>;
|
|
887
|
+
|
|
839
888
|
/** Options of {@link requireSession}. */
|
|
840
889
|
interface RequireSessionOptions<P extends Principal = Principal> {
|
|
841
890
|
/**
|
|
@@ -927,4 +976,4 @@ declare function requireSession(keys: SessionKeys, options?: RequireSessionOptio
|
|
|
927
976
|
*/
|
|
928
977
|
declare function sessionOf<P extends Principal = Principal>(req: object): RequestSession<P>;
|
|
929
978
|
|
|
930
|
-
export {
|
|
979
|
+
export { AllowedOrigin, type AuthCookieOptions, type AuthMiddleware, type AuthProfile, type AuthProvider, type AuthProviderInfo, type AuthRateLimits, type AuthRequest, type AuthResponse, type AuthRouteRequest, type AuthRouteResponse, type AuthRoutes, type AuthRoutesOptions, type AuthSession, type BearerAuthOptions, type BearerAuthenticate, type CookieOriginRequest, type CookieResponse, type CookieSettings, DEFAULT_MOCK_PATH_PREFIX, DEFAULT_SESSION_TTL_MS, type DevCredentials, type DiscordUser, GUEST_MAX_BODY_BYTES, type GoogleUser, type GuestOptions, type GuestProvider, type GuestUser, HOST_OAUTH_STATE_COOKIE, HOST_SESSION_COOKIE, type IssuedSession, type JWTPayload, MIN_JWT_SECRET_LENGTH, type MemorySessionStore, type MockOAuthProviderOptions, type MockOAuthRouter, type MockOAuthUser, type MockSignInOptions, type MockSignInProvider, OAUTH_RETURN_ORIGIN_COOKIE, OAUTH_STATE_COOKIE, OAUTH_STATE_TTL_MS, type OAuthClientOptions, type OAuthConfig, type OAuthProvider, type OAuthSignInProvider, type OAuthTokenResponse, type OptionalClientOptions, type PrincipalLoader, type RegisterMockOAuthOptions, type RequestSession, type RequireAuthOptions, type RequireSessionOptions, SESSION_COOKIE, type SessionAuthenticate, type SessionCookieOptions, type SessionKeys, type SessionMeta, type SessionMiddleware, type SessionRequest, type SessionStore, type SocketAuthOptions, type ValidateOriginOptions, bearerAuth, clearSessionCookie, cookieOriginAllowed, createAuthRoutes, createJWT, createMemorySessionStore, createMockOAuthProvider, createOAuthURL, createRequireAuth, discord, discordProvider, exchangeOAuthCode, extractBearerOrCookieToken, getDiscordAvatarUrl, google, googleProvider, guest, isMockOAuthEnabled, issueSession, liveSession, mock, registerMockOAuthProvider, requireSession, sessionOf, setSessionCookie, socketAuth, validateRedirectOrigin, verifyJWT };
|