@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.
Files changed (152) hide show
  1. package/README.md +1308 -219
  2. package/dist/{admin-DKwkIh5i.d.ts → admin-CS7JB_UH.d.ts} +2 -2
  3. package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-29cGgrg5.d.ts} +6 -4
  4. package/dist/{auth-BhWqdyb-.d.ts → auth-DtdYjrZ9.d.ts} +51 -21
  5. package/dist/{caller-CXTFswBO.d.ts → caller-BTwGl7vm.d.ts} +296 -33
  6. package/dist/chunk-2FDSKLBO.js +82 -0
  7. package/dist/chunk-2FDSKLBO.js.map +1 -0
  8. package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
  9. package/dist/chunk-4D2DOGAW.js.map +1 -0
  10. package/dist/{chunk-OECZPRPW.js → chunk-64I6MYBC.js} +162 -775
  11. package/dist/chunk-64I6MYBC.js.map +1 -0
  12. package/dist/chunk-7473HK24.js +17 -0
  13. package/dist/chunk-7473HK24.js.map +1 -0
  14. package/dist/chunk-7Y5ROPXL.js +33 -0
  15. package/dist/chunk-7Y5ROPXL.js.map +1 -0
  16. package/dist/chunk-A2RBQD66.js +7 -0
  17. package/dist/chunk-A2RBQD66.js.map +1 -0
  18. package/dist/chunk-AK23XSWD.js +16 -0
  19. package/dist/chunk-AK23XSWD.js.map +1 -0
  20. package/dist/chunk-ASAMUGHG.js +651 -0
  21. package/dist/chunk-ASAMUGHG.js.map +1 -0
  22. package/dist/{chunk-B2P7AZ25.js → chunk-CYE4UBOB.js} +6 -4
  23. package/dist/chunk-CYE4UBOB.js.map +1 -0
  24. package/dist/chunk-DKE6QO26.js +136 -0
  25. package/dist/chunk-DKE6QO26.js.map +1 -0
  26. package/dist/chunk-DNP65TD5.js +832 -0
  27. package/dist/chunk-DNP65TD5.js.map +1 -0
  28. package/dist/{chunk-H23KEFBA.js → chunk-DUBU3BB3.js} +30 -1
  29. package/dist/chunk-DUBU3BB3.js.map +1 -0
  30. package/dist/chunk-GYLWEJHW.js +19 -0
  31. package/dist/chunk-GYLWEJHW.js.map +1 -0
  32. package/dist/{chunk-SHEGLZEP.js → chunk-I3JCFS7H.js} +34 -13
  33. package/dist/chunk-I3JCFS7H.js.map +1 -0
  34. package/dist/{chunk-X5CWPX7H.js → chunk-IIQ3WMJK.js} +13 -2
  35. package/dist/chunk-IIQ3WMJK.js.map +1 -0
  36. package/dist/{chunk-RZTP4IEW.js → chunk-JVTONQFI.js} +6339 -4226
  37. package/dist/chunk-JVTONQFI.js.map +1 -0
  38. package/dist/{chunk-QEKVYG5F.js → chunk-KKQANRLG.js} +2 -2
  39. package/dist/chunk-KKQANRLG.js.map +1 -0
  40. package/dist/{chunk-CDKG4TFA.js → chunk-MPQAT55F.js} +38 -205
  41. package/dist/chunk-MPQAT55F.js.map +1 -0
  42. package/dist/chunk-NO4M6PO5.js +101 -0
  43. package/dist/chunk-NO4M6PO5.js.map +1 -0
  44. package/dist/{chunk-TBMKJ26R.js → chunk-NW6U45HX.js} +3 -1
  45. package/dist/chunk-NW6U45HX.js.map +1 -0
  46. package/dist/chunk-NX2V6SIL.js +202 -0
  47. package/dist/chunk-NX2V6SIL.js.map +1 -0
  48. package/dist/{chunk-ZIVPHYRG.js → chunk-NZHA4TZD.js} +72 -175
  49. package/dist/chunk-NZHA4TZD.js.map +1 -0
  50. package/dist/{chunk-2PWMUVC7.js → chunk-OCZJ4EYV.js} +518 -27
  51. package/dist/chunk-OCZJ4EYV.js.map +1 -0
  52. package/dist/{chunk-REX5YPHX.js → chunk-PHCURHC7.js} +76 -21
  53. package/dist/chunk-PHCURHC7.js.map +1 -0
  54. package/dist/{chunk-4YO5H5ON.js → chunk-Q4OGQM5I.js} +4 -10
  55. package/dist/chunk-Q4OGQM5I.js.map +1 -0
  56. package/dist/chunk-QSU47XEX.js +13 -0
  57. package/dist/chunk-QSU47XEX.js.map +1 -0
  58. package/dist/{chunk-DD4SKCNO.js → chunk-RZXJTDH5.js} +13 -2
  59. package/dist/chunk-RZXJTDH5.js.map +1 -0
  60. package/dist/{chunk-Z2LZ7IZ7.js → chunk-SN3OZVEQ.js} +5 -31
  61. package/dist/chunk-SN3OZVEQ.js.map +1 -0
  62. package/dist/{chunk-4DIQHASK.js → chunk-SQ5VUG77.js} +28 -8
  63. package/dist/chunk-SQ5VUG77.js.map +1 -0
  64. package/dist/chunk-STH5DLQP.js +1192 -0
  65. package/dist/chunk-STH5DLQP.js.map +1 -0
  66. package/dist/{chunk-QCHKWIRS.js → chunk-VZFJTKIW.js} +13 -13
  67. package/dist/{chunk-QCHKWIRS.js.map → chunk-VZFJTKIW.js.map} +1 -1
  68. package/dist/{chunk-VSQBHPWH.js → chunk-X4ZU4QH5.js} +54 -22
  69. package/dist/chunk-X4ZU4QH5.js.map +1 -0
  70. package/dist/chunk-XD7SRDUY.js +188 -0
  71. package/dist/chunk-XD7SRDUY.js.map +1 -0
  72. package/dist/chunk-XH2IZVLT.js +62 -0
  73. package/dist/chunk-XH2IZVLT.js.map +1 -0
  74. package/dist/chunk-Z7I6SONO.js +825 -0
  75. package/dist/chunk-Z7I6SONO.js.map +1 -0
  76. package/dist/cli/quickdraw-docs.js +132 -112
  77. package/dist/cli/quickdraw-docs.js.map +1 -1
  78. package/dist/client/core.d.ts +387 -0
  79. package/dist/client/core.js +109 -0
  80. package/dist/client/index.d.ts +52 -203
  81. package/dist/client/index.js +59 -218
  82. package/dist/client/index.js.map +1 -1
  83. package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-CUUNJwWs.d.ts} +3 -3
  84. package/dist/{connection-Cr1BU07W.d.ts → connection-2EeQ_Et0.d.ts} +22 -11
  85. package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Bx5HOcYK.d.ts} +67 -17
  86. package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-DAMANT79.d.ts} +46 -13
  87. package/dist/{envelope-Cp3YcVxC.d.ts → envelope-BMBaxppV.d.ts} +216 -10
  88. package/dist/{http-Djj2Inuu.d.ts → http-YzLAar3w.d.ts} +76 -60
  89. package/dist/index.d.ts +8 -7
  90. package/dist/index.js +82 -25
  91. package/dist/index.js.map +1 -1
  92. package/dist/{infer-Teo1xpsd.d.ts → infer-Br62cnyW.d.ts} +82 -11
  93. package/dist/logger-Yz93KzdV.d.ts +30 -0
  94. package/dist/{metrics-BdBu5o8G.d.ts → metrics-CTVpw0gu.d.ts} +2 -2
  95. package/dist/origins-kvpxnVcW.d.ts +8 -0
  96. package/dist/parser.js +2 -1
  97. package/dist/prisma/index.d.ts +14 -7
  98. package/dist/prisma/index.js +279 -70
  99. package/dist/prisma/index.js.map +1 -1
  100. package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
  101. package/dist/rateLimit-5RKBFLUR.js.map +1 -0
  102. package/dist/remote-N7OUAGOW.js +15 -0
  103. package/dist/remote-N7OUAGOW.js.map +1 -0
  104. package/dist/server/auth/index.d.ts +82 -33
  105. package/dist/server/auth/index.js +277 -270
  106. package/dist/server/auth/index.js.map +1 -1
  107. package/dist/server/express/index.d.ts +9 -2
  108. package/dist/server/express/index.js +1 -1
  109. package/dist/server/index.d.ts +268 -84
  110. package/dist/server/index.js +664 -418
  111. package/dist/server/index.js.map +1 -1
  112. package/dist/server/mcp/index.d.ts +89 -27
  113. package/dist/server/mcp/index.js +281 -62
  114. package/dist/server/mcp/index.js.map +1 -1
  115. package/dist/server/otel.d.ts +3 -3
  116. package/dist/{sharing-DVa8W-yR.d.ts → sharing-BrsmlDv_.d.ts} +3 -3
  117. package/dist/testing/client.d.ts +14 -14
  118. package/dist/testing/client.js +19 -10
  119. package/dist/testing/client.js.map +1 -1
  120. package/dist/testing/index.d.ts +50 -13
  121. package/dist/testing/index.js +113 -21
  122. package/dist/testing/index.js.map +1 -1
  123. package/dist/testing/mock.d.ts +5 -5
  124. package/dist/testing/mock.js +17 -9
  125. package/dist/tracked-BR5b2O-U.d.ts +43 -0
  126. package/dist/{types-Cu0vmx7c.d.ts → types-CLRCQGnO.d.ts} +4 -3
  127. package/dist/types-tMagHbjy.d.ts +151 -0
  128. package/dist/utils/index.d.ts +16 -4
  129. package/dist/utils/index.js +6 -3
  130. package/package.json +5 -1
  131. package/dist/chunk-2PWMUVC7.js.map +0 -1
  132. package/dist/chunk-4DIQHASK.js.map +0 -1
  133. package/dist/chunk-4YO5H5ON.js.map +0 -1
  134. package/dist/chunk-B2P7AZ25.js.map +0 -1
  135. package/dist/chunk-CDKG4TFA.js.map +0 -1
  136. package/dist/chunk-DD4SKCNO.js.map +0 -1
  137. package/dist/chunk-H23KEFBA.js.map +0 -1
  138. package/dist/chunk-OECZPRPW.js.map +0 -1
  139. package/dist/chunk-QEKVYG5F.js.map +0 -1
  140. package/dist/chunk-REX5YPHX.js.map +0 -1
  141. package/dist/chunk-RT6OILOI.js.map +0 -1
  142. package/dist/chunk-RZTP4IEW.js.map +0 -1
  143. package/dist/chunk-SHEGLZEP.js.map +0 -1
  144. package/dist/chunk-TBMKJ26R.js.map +0 -1
  145. package/dist/chunk-VSQBHPWH.js.map +0 -1
  146. package/dist/chunk-X5CWPX7H.js.map +0 -1
  147. package/dist/chunk-YSWH776Y.js +0 -13
  148. package/dist/chunk-YSWH776Y.js.map +0 -1
  149. package/dist/chunk-Z2LZ7IZ7.js.map +0 -1
  150. package/dist/chunk-ZIVPHYRG.js.map +0 -1
  151. package/dist/logger-BY28acW-.d.ts +0 -16
  152. /package/dist/{rateLimit-ZMIZJUZF.js.map → client/core.js.map} +0 -0
@@ -1,75 +1,84 @@
1
+ import {
2
+ findNestedWrites
3
+ } from "../chunk-XH2IZVLT.js";
1
4
  import {
2
5
  createWriteTracker,
3
6
  quietly
4
- } from "../chunk-4DIQHASK.js";
5
- import "../chunk-DD4SKCNO.js";
7
+ } from "../chunk-SQ5VUG77.js";
8
+ import "../chunk-RZXJTDH5.js";
6
9
  import {
7
10
  STORAGE_KEY,
8
11
  createInterestRegistry,
12
+ createLinkRegistry,
9
13
  modelKey,
10
14
  storageOf
11
- } from "../chunk-H23KEFBA.js";
15
+ } from "../chunk-DUBU3BB3.js";
12
16
  import {
13
17
  consoleLogger
14
- } from "../chunk-YSWH776Y.js";
15
- import "../chunk-4YO5H5ON.js";
18
+ } from "../chunk-DKE6QO26.js";
19
+ import "../chunk-Q4OGQM5I.js";
20
+ import "../chunk-QSU47XEX.js";
16
21
 
17
- // src/prisma/nested.ts
18
- var NESTED_KEYS = [
19
- "create",
20
- "createMany",
21
- "connect",
22
- "connectOrCreate",
23
- "disconnect",
24
- "set",
25
- "update",
26
- "updateMany",
27
- "upsert",
28
- "delete",
29
- "deleteMany"
30
- ];
31
- var FLAG_KEYS = /* @__PURE__ */ new Set(["delete", "disconnect"]);
32
- function isPlainObject(value) {
33
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
34
- return false;
35
- }
36
- const prototype = Object.getPrototypeOf(value);
37
- return prototype === Object.prototype || prototype === null;
38
- }
39
- function isRows(value) {
40
- return Array.isArray(value) || isPlainObject(value);
41
- }
42
- function isRelationSet(value) {
43
- return Array.isArray(value) ? value.some(isPlainObject) : isPlainObject(value);
44
- }
45
- function writesRelation(value, key) {
46
- if (!Object.hasOwn(value, key)) {
47
- return false;
48
- }
49
- const operand = value[key];
50
- if (key === "set") {
51
- return isRelationSet(operand);
22
+ // src/prisma/links.ts
23
+ var UNREAD = /* @__PURE__ */ new WeakMap();
24
+ function warnUnread(runtime, model, junction) {
25
+ const warned = UNREAD.get(runtime) ?? /* @__PURE__ */ new Set();
26
+ UNREAD.set(runtime, warned);
27
+ const key = `${model}\0${junction}`;
28
+ if (warned.has(key)) {
29
+ return;
52
30
  }
53
- return isRows(operand) || FLAG_KEYS.has(key) && operand === true;
31
+ warned.add(key);
32
+ runtime.tracker.logger.warn(
33
+ `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`,
34
+ { category: "quickdraw.writes", model, junction }
35
+ );
54
36
  }
55
- function nestedKey(value) {
56
- if (!isPlainObject(value)) {
37
+ async function readLinks(runtime, model, ids) {
38
+ const links = runtime.linksOf(model);
39
+ if (links.length === 0 || ids.length === 0) {
57
40
  return void 0;
58
41
  }
59
- return NESTED_KEYS.find((key) => writesRelation(value, key));
60
- }
61
- function findNestedWrites(data) {
62
- if (!isPlainObject(data)) {
63
- return [];
64
- }
65
- const found = [];
66
- for (const [field, value] of Object.entries(data)) {
67
- const operation = nestedKey(value);
68
- if (operation !== void 0) {
69
- found.push({ field, operation });
42
+ const byId = new Map(
43
+ ids.map((id) => [id, Object.fromEntries(links.map((link) => [link.model, []]))])
44
+ );
45
+ for (const link of links) {
46
+ const select = Object.fromEntries(
47
+ [link.entry, ...link.columns].map((column) => [column, true])
48
+ );
49
+ let delegate;
50
+ try {
51
+ delegate = runtime.delegate(link.model);
52
+ } catch {
53
+ warnUnread(runtime, model, link.model);
54
+ return void 0;
55
+ }
56
+ let rows;
57
+ try {
58
+ rows = await quietly(
59
+ () => delegate.findMany({ where: { [link.entry]: { in: [...ids] } }, select })
60
+ );
61
+ } catch (error) {
62
+ if (error instanceof Error && error.name === "PrismaClientValidationError") {
63
+ warnUnread(runtime, model, link.model);
64
+ return void 0;
65
+ }
66
+ throw error;
67
+ }
68
+ for (const row of rows) {
69
+ const entry = row[link.entry];
70
+ if (typeof entry === "string") {
71
+ byId.get(entry)?.[link.model]?.push(row);
72
+ }
70
73
  }
71
74
  }
72
- return found;
75
+ return byId;
76
+ }
77
+ function withLinks(writes, links) {
78
+ return writes.map((write) => {
79
+ const own = links?.get(write.id);
80
+ return own === void 0 ? write : { ...write, links: own };
81
+ });
73
82
  }
74
83
 
75
84
  // src/prisma/operations.ts
@@ -131,14 +140,19 @@ function countOwn(op, operation, args) {
131
140
  op.runtime.tracker.observe({ model: op.model, operation, args });
132
141
  }
133
142
  function warnNested(op, data) {
134
- for (const { field, operation } of findNestedWrites(data)) {
143
+ const nested = findNestedWrites(data);
144
+ for (const { field, operation } of nested) {
135
145
  op.runtime.tracker.warn({
136
146
  kind: "nested-write",
137
147
  subject: `${op.model}.${field}.${operation}`,
138
- message: `A nested write (${op.model}.${field}: { ${operation} }) is not tracked; only the ${op.model} row is. Write related rows through their own model`,
148
+ 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`,
139
149
  meta: { model: op.model, field, operation }
140
150
  });
141
151
  }
152
+ return nested.length > 0;
153
+ }
154
+ function withColumns(data, columns) {
155
+ return [.../* @__PURE__ */ new Set([...keysOf(data), ...columns])];
142
156
  }
143
157
  function touchedInterest(op, data) {
144
158
  const keys = new Set(keysOf(data));
@@ -289,12 +303,13 @@ async function upsert(op) {
289
303
  return upsertWithoutUpdate(op);
290
304
  }
291
305
  warnNested(op, op.args.create);
292
- warnNested(op, op.args.update);
293
- const touched = touchedInterest(op, op.args.update);
306
+ const nested = warnNested(op, op.args.update);
307
+ const touched = nested ? [...op.runtime.interestOf(op.model)] : touchedInterest(op, op.args.update);
294
308
  const before = touched.length === 0 ? void 0 : await readBefore(op, op.args.where, touched, { unique: true });
295
309
  const { result, rows } = await runWidened(op);
296
310
  if (before !== void 0 && before.size > 0) {
297
- record(op, writesOf(op, "update", rows, keysOf(op.args.update), before));
311
+ const fields = nested ? withColumns(op.args.update, touched) : keysOf(op.args.update);
312
+ record(op, writesOf(op, "update", rows, fields, before));
298
313
  } else if (before === void 0) {
299
314
  const writes = writesOf(op, "create", rows, keysOf([op.args.create, op.args.update]));
300
315
  record(
@@ -310,16 +325,27 @@ async function update(op) {
310
325
  if (writesNothing(op.args.data)) {
311
326
  return op.query(op.args);
312
327
  }
313
- warnNested(op, op.args.data);
314
- const touched = touchedInterest(op, op.args.data);
328
+ const nested = warnNested(op, op.args.data);
329
+ const touched = nested ? [...op.runtime.interestOf(op.model)] : touchedInterest(op, op.args.data);
315
330
  const before = touched.length === 0 ? void 0 : await readBefore(op, op.args.where, touched, { unique: true });
316
331
  const { result, rows } = await runWidened(op);
317
- record(op, writesOf(op, "update", rows, keysOf(op.args.data), before));
332
+ const fields = nested ? withColumns(op.args.data, touched) : keysOf(op.args.data);
333
+ record(op, writesOf(op, "update", rows, fields, before));
318
334
  return result;
319
335
  }
336
+ async function linksOfDelete(op) {
337
+ if (op.runtime.linksOf(op.model).length === 0) {
338
+ return void 0;
339
+ }
340
+ warnBatchRead(op);
341
+ const { where } = op.args;
342
+ const ids = isRecord(where) && typeof where.id === "string" ? [where.id] : [...(await readBefore(op, where, [], { unique: true })).keys()];
343
+ return await readLinks(op.runtime, op.model, ids);
344
+ }
320
345
  async function remove(op) {
346
+ const links = await linksOfDelete(op);
321
347
  const { result, rows } = await runWidened(op);
322
- record(op, writesOf(op, "delete", rows, []));
348
+ record(op, withLinks(writesOf(op, "delete", rows, []), links));
323
349
  return result;
324
350
  }
325
351
  async function createManyAndReturn(op) {
@@ -401,10 +427,11 @@ async function deleteMany(op) {
401
427
  const interest = op.runtime.interestOf(op.model);
402
428
  const before = await readBefore(op, where, interest, { unique: false, take: limit });
403
429
  const ids = [...before.keys()];
430
+ const links = await readLinks(op.runtime, op.model, ids);
404
431
  const args = limit === void 0 ? op.args : { ...op.args, where: { AND: [where ?? {}, { id: { in: ids } }] } };
405
432
  const result = await op.query(args);
406
433
  const rows = ids.map((id) => ({ id, ...before.get(id) }));
407
- record(op, writesOf(op, "delete", rows, []));
434
+ record(op, withLinks(writesOf(op, "delete", rows, []), links));
408
435
  return result;
409
436
  }
410
437
  var WRITE_OPERATIONS = Object.freeze({
@@ -434,6 +461,143 @@ function delegates(runtime, operation, args) {
434
461
  }
435
462
  }
436
463
 
464
+ // src/prisma/schemaText.ts
465
+ var BLOCK_START = /^(\w+)\s+([A-Za-z_]\w*)\s*\{/;
466
+ var FIELD = /^([A-Za-z_]\w*)\s+([A-Za-z_]\w*)(\([^)]*\))?(\[\])?(\?)?(?=\s|$)/;
467
+ var IGNORED = /(?:^|\s)@ignore(?=\s|$|\()/;
468
+ var KEY_TYPES = /* @__PURE__ */ new Set(["String", "Int", "BigInt", "Float"]);
469
+ var COLUMN_KINDS = /* @__PURE__ */ new Set(["scalar", "enum"]);
470
+ function isObject(value) {
471
+ return (typeof value === "object" || typeof value === "function") && value !== null;
472
+ }
473
+ function withoutComment(line) {
474
+ let inString = false;
475
+ for (let index = 0; index < line.length; index += 1) {
476
+ const char = line[index];
477
+ if (char === '"' && line[index - 1] !== "\\") {
478
+ inString = !inString;
479
+ } else if (!inString && char === "/" && line[index + 1] === "/") {
480
+ return line.slice(0, index);
481
+ }
482
+ }
483
+ return line;
484
+ }
485
+ function blocksOf(text) {
486
+ const blocks = [];
487
+ let open;
488
+ for (const raw of text.split(/\r?\n/)) {
489
+ const line = withoutComment(raw).trim();
490
+ if (line === "") {
491
+ continue;
492
+ }
493
+ if (open !== void 0) {
494
+ if (line === "}") {
495
+ open = void 0;
496
+ } else {
497
+ open.lines.push(line);
498
+ }
499
+ continue;
500
+ }
501
+ const start = BLOCK_START.exec(line);
502
+ if (start !== null) {
503
+ const block = { kind: start[1] ?? "", name: start[2] ?? "", lines: [] };
504
+ blocks.push(block);
505
+ open = line.slice(start[0].length).trim() === "}" ? void 0 : block;
506
+ }
507
+ }
508
+ return blocks;
509
+ }
510
+ function kindsOf(runtimeDataModel, model) {
511
+ const models = isObject(runtimeDataModel) ? Reflect.get(runtimeDataModel, "models") : void 0;
512
+ const entry = isObject(models) && Object.hasOwn(models, model) ? Reflect.get(models, model) : void 0;
513
+ const fields = isObject(entry) ? Reflect.get(entry, "fields") : void 0;
514
+ if (!Array.isArray(fields)) {
515
+ return void 0;
516
+ }
517
+ const kinds = /* @__PURE__ */ new Map();
518
+ for (const field of fields) {
519
+ const name = isObject(field) ? Reflect.get(field, "name") : void 0;
520
+ const kind = isObject(field) ? Reflect.get(field, "kind") : void 0;
521
+ if (typeof name === "string" && typeof kind === "string") {
522
+ kinds.set(name, kind);
523
+ }
524
+ }
525
+ return kinds;
526
+ }
527
+ function isColumn(name, type, kinds, records) {
528
+ if (kinds !== void 0) {
529
+ return COLUMN_KINDS.has(kinds.get(name) ?? "");
530
+ }
531
+ return type !== "Unsupported" && !records.has(type);
532
+ }
533
+ function trackableOf(fields, kinds, enums) {
534
+ const id = fields.get("id");
535
+ if (id === void 0) {
536
+ return kinds !== void 0 && COLUMN_KINDS.has(kinds.get("id") ?? "") ? void 0 : false;
537
+ }
538
+ if (id.optional || id.list) {
539
+ return void 0;
540
+ }
541
+ return KEY_TYPES.has(id.type) || enums.has(id.type) ? true : void 0;
542
+ }
543
+ function modelOf(block, kinds, records, enums) {
544
+ const fields = /* @__PURE__ */ new Map();
545
+ for (const line of block.lines) {
546
+ const field = FIELD.exec(line);
547
+ const [, name = "", type = "", , list, optional] = field ?? [];
548
+ if (field !== null && !IGNORED.test(line) && isColumn(name, type, kinds, records)) {
549
+ fields.set(name, { type, optional: optional !== void 0, list: list !== void 0 });
550
+ }
551
+ }
552
+ return { fields, trackable: trackableOf(fields, kinds, enums) };
553
+ }
554
+ function parsePrismaSchema(text, runtimeDataModel) {
555
+ const blocks = blocksOf(text);
556
+ const named = (...kinds) => new Set(blocks.filter((block) => kinds.includes(block.kind)).map((block) => block.name));
557
+ const enums = named("enum");
558
+ const records = named("model", "view", "type");
559
+ const models = /* @__PURE__ */ new Map();
560
+ for (const block of blocks) {
561
+ const ignored = block.lines.some((line) => /^@@ignore\b/.test(line));
562
+ if ((block.kind === "model" || block.kind === "view") && !ignored) {
563
+ const kinds = kindsOf(runtimeDataModel, block.name);
564
+ models.set(modelKey(block.name), modelOf(block, kinds, records, enums));
565
+ }
566
+ }
567
+ return Object.freeze({
568
+ nullable(model, column) {
569
+ const field = models.get(modelKey(model))?.fields.get(column);
570
+ return field === void 0 ? void 0 : field.optional && !field.list;
571
+ },
572
+ trackable: (model) => models.get(modelKey(model))?.trackable
573
+ });
574
+ }
575
+ function schemaTextOf(client) {
576
+ try {
577
+ const config = isObject(client) ? Reflect.get(client, "_engineConfig") : void 0;
578
+ const text = isObject(config) ? Reflect.get(config, "inlineSchema") : void 0;
579
+ return typeof text === "string" && text !== "" ? text : void 0;
580
+ } catch {
581
+ return void 0;
582
+ }
583
+ }
584
+ function runtimeDataModelOf(client) {
585
+ try {
586
+ const own = isObject(client) ? Reflect.get(client, "_runtimeDataModel") : void 0;
587
+ if (own !== void 0) {
588
+ return own;
589
+ }
590
+ const config = isObject(client) ? Reflect.get(client, "_engineConfig") : void 0;
591
+ return isObject(config) ? Reflect.get(config, "runtimeDataModel") : void 0;
592
+ } catch {
593
+ return void 0;
594
+ }
595
+ }
596
+ function prismaSchemaOf(client) {
597
+ const text = schemaTextOf(client);
598
+ return text === void 0 ? void 0 : parsePrismaSchema(text, runtimeDataModelOf(client));
599
+ }
600
+
437
601
  // src/prisma/trackPrisma.ts
438
602
  function isClient(value) {
439
603
  return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "$extends") === "function";
@@ -487,9 +651,13 @@ async function transaction(tracker, hooked, arg, options) {
487
651
  throw error;
488
652
  }
489
653
  }
490
- function createNullability(delegate) {
654
+ function createNullability(delegate, schema) {
491
655
  const known = /* @__PURE__ */ new Map();
492
656
  return async (model, column) => {
657
+ const declared = schema?.nullable(model, column);
658
+ if (declared !== void 0) {
659
+ return declared;
660
+ }
493
661
  const key = `${modelKey(model)}\0${column}`;
494
662
  const kept = known.get(key);
495
663
  if (kept !== void 0) {
@@ -508,7 +676,38 @@ function createNullability(delegate) {
508
676
  return nullable;
509
677
  };
510
678
  }
511
- function createStorage(tracker, interest, delegate) {
679
+ function createTrackability(delegate, schema) {
680
+ const known = /* @__PURE__ */ new Map();
681
+ const probe = async (key) => {
682
+ try {
683
+ const rows = await quietly(() => delegate(key).findMany({ select: { id: true }, take: 1 }));
684
+ const [row] = Array.isArray(rows) ? rows : [];
685
+ return row === void 0 || idOf(row) !== void 0;
686
+ } catch (error) {
687
+ if (error instanceof Error && error.name === "PrismaClientValidationError") {
688
+ return false;
689
+ }
690
+ throw error;
691
+ }
692
+ };
693
+ return async (model) => {
694
+ const declared = schema?.trackable(model);
695
+ if (declared !== void 0) {
696
+ return declared;
697
+ }
698
+ const key = modelKey(model);
699
+ let answer = known.get(key);
700
+ if (answer === void 0) {
701
+ answer = probe(key);
702
+ known.set(key, answer);
703
+ answer.catch(() => {
704
+ known.delete(key);
705
+ });
706
+ }
707
+ return await answer;
708
+ };
709
+ }
710
+ function createStorage(tracker, [interest, links], delegate, schema) {
512
711
  return Object.freeze({
513
712
  findMany: (model, args = {}) => quietly(() => delegate(modelKey(model)).findMany(args)),
514
713
  count: (model, args = {}) => quietly(() => delegate(modelKey(model)).count(args)),
@@ -516,8 +715,11 @@ function createStorage(tracker, interest, delegate) {
516
715
  countStatements: tracker.countStatements,
517
716
  registerInterest: interest.register,
518
717
  interestOf: interest.of,
718
+ registerLinks: links.register,
719
+ linksOf: links.of,
519
720
  inTransaction: () => tracker.transactionClient() !== void 0 || tracker.inBatch(),
520
- nullable: createNullability(delegate),
721
+ nullable: createNullability(delegate, schema),
722
+ trackable: createTrackability(delegate, schema),
521
723
  unitOfWork: tracker.unitOfWork
522
724
  });
523
725
  }
@@ -535,7 +737,14 @@ function trackPrisma(client, options = {}) {
535
737
  const interest = createInterestRegistry(options.interest);
536
738
  let root;
537
739
  const delegate = (model) => delegateOf(tracker.transactionClient() ?? root, model);
538
- const runtime = { tracker, delegate, interestOf: interest.of, untracked: /* @__PURE__ */ new Set() };
740
+ const links = createLinkRegistry();
741
+ const runtime = {
742
+ tracker,
743
+ delegate,
744
+ interestOf: interest.of,
745
+ linksOf: links.of,
746
+ untracked: /* @__PURE__ */ new Set()
747
+ };
539
748
  const hooked = client.$extends({
540
749
  name: "quickdraw-tracking",
541
750
  query: { $allOperations: createHook(runtime) }
@@ -545,7 +754,7 @@ function trackPrisma(client, options = {}) {
545
754
  name: "quickdraw-transactions",
546
755
  client: {
547
756
  $transaction: (arg, txOptions) => transaction(tracker, hooked, arg, txOptions),
548
- [STORAGE_KEY]: createStorage(tracker, interest, delegate)
757
+ [STORAGE_KEY]: createStorage(tracker, [interest, links], delegate, prismaSchemaOf(client))
549
758
  }
550
759
  });
551
760
  return tracked;