@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,3 +1,7 @@
1
+ import {
2
+ ACCESS_LEVELS,
3
+ isAccessLevel
4
+ } from "./chunk-AK23XSWD.js";
1
5
  import {
2
6
  hasJsonSchema,
3
7
  isStandardSchema,
@@ -7,7 +11,389 @@ import {
7
11
  INTERNAL_MESSAGE,
8
12
  QuickdrawError,
9
13
  isErrorCode
10
- } from "./chunk-4YO5H5ON.js";
14
+ } from "./chunk-Q4OGQM5I.js";
15
+
16
+ // src/server/access/levels.ts
17
+ var RANK = Object.freeze({
18
+ Public: 0,
19
+ Read: 1,
20
+ Moderate: 2,
21
+ Admin: 3
22
+ });
23
+ function meetsLevel(level, required) {
24
+ if (level === null || level === void 0) {
25
+ return false;
26
+ }
27
+ return (RANK[level] ?? -1) >= RANK[required];
28
+ }
29
+ function maxLevel(a, b) {
30
+ const left = isAccessLevel(a) ? a : null;
31
+ const right = isAccessLevel(b) ? b : null;
32
+ if (left === null || right === null) {
33
+ return left ?? right;
34
+ }
35
+ return RANK[right] > RANK[left] ? right : left;
36
+ }
37
+ function levelsAtLeast(required) {
38
+ return ACCESS_LEVELS.filter((level) => RANK[level] >= RANK[required]);
39
+ }
40
+ function serviceGrant(principal, service) {
41
+ const grants = principal.serviceAccess;
42
+ if (grants === null || grants === void 0 || !Object.hasOwn(grants, service)) {
43
+ return void 0;
44
+ }
45
+ return grants[service];
46
+ }
47
+
48
+ // src/server/emit/tiers.ts
49
+ var SUBSCRIBE_LEVEL = "Read";
50
+ var SUBSCRIBER_LEVELS = Object.freeze([
51
+ "Read",
52
+ "Moderate",
53
+ "Admin"
54
+ ]);
55
+ var NOTHING = Object.freeze(/* @__PURE__ */ new Set());
56
+ function hiddenAt(fields, keys, level) {
57
+ const hidden = keys.filter((key) => {
58
+ const required = Object.hasOwn(fields, key) ? fields[key] : void 0;
59
+ return required !== void 0 && !meetsLevel(level, required);
60
+ });
61
+ return hidden.length === 0 ? NOTHING : Object.freeze(new Set(hidden));
62
+ }
63
+ function tiersOf(fields, keys) {
64
+ const byLevel = /* @__PURE__ */ new Map();
65
+ const labels = /* @__PURE__ */ new Map();
66
+ const hiding = (level) => {
67
+ let found = byLevel.get(level);
68
+ if (found === void 0) {
69
+ const set = hiddenAt(fields, keys, level);
70
+ const signature = [...set].join("\0");
71
+ const label = labels.get(signature) ?? String.fromCodePoint(97 + labels.size);
72
+ labels.set(signature, label);
73
+ found = { hidden: set, label };
74
+ byLevel.set(level, found);
75
+ }
76
+ return found;
77
+ };
78
+ const hidden = (level) => hiding(level).hidden;
79
+ const groups = /* @__PURE__ */ new Map();
80
+ for (const level of SUBSCRIBER_LEVELS) {
81
+ const set = hidden(level);
82
+ const signature = [...set].join("\0");
83
+ const group = groups.get(signature);
84
+ if (group === void 0) {
85
+ groups.set(signature, { levels: [level], hidden: set });
86
+ } else {
87
+ group.levels.push(level);
88
+ }
89
+ }
90
+ return Object.freeze({
91
+ tiered: keys.some((key) => Object.hasOwn(fields, key)),
92
+ hidden,
93
+ label: (level) => hiding(level).label,
94
+ groups: Object.freeze([...groups.values()].map((group) => Object.freeze(group)))
95
+ });
96
+ }
97
+ function strip(row, hidden) {
98
+ if (hidden.size === 0) {
99
+ return row;
100
+ }
101
+ const kept = {};
102
+ for (const [key, value] of Object.entries(row)) {
103
+ if (!hidden.has(key)) {
104
+ kept[key] = value;
105
+ }
106
+ }
107
+ return kept;
108
+ }
109
+
110
+ // src/server/emit/projection.ts
111
+ function isRecord(value) {
112
+ return typeof value === "object" && value !== null && !Array.isArray(value);
113
+ }
114
+ function isPlain(value) {
115
+ if (typeof value !== "object" || value === null) {
116
+ return false;
117
+ }
118
+ const prototype = Object.getPrototypeOf(value);
119
+ return Array.isArray(value) || prototype === Object.prototype || prototype === null;
120
+ }
121
+ function referenced(node, root) {
122
+ const ref = node.$ref;
123
+ if (typeof ref !== "string") {
124
+ return node;
125
+ }
126
+ if (ref === "#") {
127
+ return root;
128
+ }
129
+ const match = /^#\/(definitions|\$defs)\/(.+)$/.exec(ref);
130
+ const defs = match === null ? void 0 : root[match[1] ?? ""];
131
+ const name = (match?.[2] ?? "").replaceAll("~1", "/").replaceAll("~0", "~");
132
+ const target = isRecord(defs) ? defs[name] : void 0;
133
+ return isRecord(target) ? target : void 0;
134
+ }
135
+ function pointerToken(name) {
136
+ return name.replaceAll("~", "~0").replaceAll("/", "~1");
137
+ }
138
+ function schemaKeys(schema) {
139
+ if (!hasJsonSchema(schema)) {
140
+ return void 0;
141
+ }
142
+ let json;
143
+ try {
144
+ json = schema["~standard"].jsonSchema.output({ target: "draft-07" });
145
+ } catch {
146
+ return void 0;
147
+ }
148
+ const described = isRecord(json) ? referenced(json, json) : void 0;
149
+ const properties = described?.properties;
150
+ return isRecord(properties) ? Object.keys(properties) : void 0;
151
+ }
152
+ var BRANCHES = ["anyOf", "oneOf", "allOf"];
153
+ var UNREPRESENTABLE_AS_ANY = Object.freeze({ unrepresentable: "any" });
154
+ function addBranchKeys(node, root, keys, seen) {
155
+ const target = isRecord(node) ? referenced(node, root) : void 0;
156
+ if (target === void 0 || seen.has(target)) {
157
+ return;
158
+ }
159
+ seen.add(target);
160
+ if (isRecord(target.properties)) {
161
+ for (const key of Object.keys(target.properties)) {
162
+ keys.add(key);
163
+ }
164
+ }
165
+ for (const keyword of BRANCHES) {
166
+ const members = target[keyword];
167
+ if (Array.isArray(members)) {
168
+ for (const member of members) {
169
+ addBranchKeys(member, root, keys, seen);
170
+ }
171
+ }
172
+ }
173
+ }
174
+ function inputKeys(schema) {
175
+ if (!hasJsonSchema(schema)) {
176
+ return void 0;
177
+ }
178
+ let json;
179
+ try {
180
+ json = schema["~standard"].jsonSchema.input({
181
+ target: "draft-07",
182
+ libraryOptions: UNREPRESENTABLE_AS_ANY
183
+ });
184
+ } catch {
185
+ return void 0;
186
+ }
187
+ if (!isRecord(json)) {
188
+ return void 0;
189
+ }
190
+ const keys = /* @__PURE__ */ new Set();
191
+ addBranchKeys(json, json, keys, /* @__PURE__ */ new Set());
192
+ return [...keys];
193
+ }
194
+ var OPTION_KEYS = /* @__PURE__ */ new Set(["keys", "select", "map"]);
195
+ function checkKeyList(owner, keys, fail) {
196
+ const valid = Array.isArray(keys) && keys.every((key) => typeof key === "string" && key.length > 0) && new Set(keys).size === keys.length;
197
+ if (!valid) {
198
+ fail(`${owner}: keys must be a list of distinct field names`);
199
+ }
200
+ if (!keys.includes("id")) {
201
+ fail(`${owner}: keys must include "id"; every row is keyed by it`);
202
+ }
203
+ return keys;
204
+ }
205
+ function checkOption(owner, option, fail) {
206
+ if (option === void 0) {
207
+ return {};
208
+ }
209
+ if (!isRecord(option)) {
210
+ fail(`${owner} must be { keys?, select?, map? }`);
211
+ }
212
+ const unknownKey = Object.keys(option).find((key) => !OPTION_KEYS.has(key));
213
+ if (unknownKey !== void 0) {
214
+ fail(`${owner} has an unknown option "${unknownKey}"; the options are keys, select and map`);
215
+ }
216
+ if (option.select !== void 0 && !isRecord(option.select)) {
217
+ fail(`${owner}: select must be a select object, as in { id: true, labels: { select: ... } }`);
218
+ }
219
+ if (option.map !== void 0 && typeof option.map !== "function") {
220
+ fail(`${owner}: map must be a function of the row its select reads`);
221
+ }
222
+ return option;
223
+ }
224
+ function keysFor(name, schema, option, fail) {
225
+ const owner = `projection "${name}"`;
226
+ if (option.keys !== void 0) {
227
+ return checkKeyList(owner, option.keys, fail);
228
+ }
229
+ const keys = schemaKeys(schema);
230
+ if (keys === void 0) {
231
+ fail(
232
+ `${owner}: its schema cannot list its keys (it has no Standard JSON Schema the framework can read); use Zod 4.2 or later for it, or declare them with project: { ${name}: { keys: [...] } }`
233
+ );
234
+ }
235
+ return keys;
236
+ }
237
+ function compileOne(name, schema, option, fields, fail) {
238
+ const checked = checkOption(`projection "${name}"`, option, fail);
239
+ const keys = keysFor(name, schema, checked, fail);
240
+ const ordered = ["id", ...keys.filter((key) => key !== "id")];
241
+ const select = isRecord(checked.select) ? { id: true, ...checked.select } : Object.fromEntries(ordered.map((key) => [key, true]));
242
+ return Object.freeze({
243
+ name,
244
+ keys: Object.freeze(ordered),
245
+ select: Object.freeze(select),
246
+ map: checked.map,
247
+ tiers: tiersOf(fields, ordered)
248
+ });
249
+ }
250
+ function compileProjections(contract, option, fail) {
251
+ if (option !== void 0 && !isRecord(option)) {
252
+ fail("project must map projection names to { keys?, select?, map? }");
253
+ }
254
+ const options = option ?? {};
255
+ const schemas = new Map(Object.entries(contract.projections));
256
+ if (contract.entity !== void 0) {
257
+ schemas.set("entity", contract.entity);
258
+ }
259
+ const unknownName = Object.keys(options).find((name) => !schemas.has(name));
260
+ if (unknownName !== void 0) {
261
+ fail(
262
+ `project names "${unknownName}", which is not a projection of the contract; the projections are ${[...schemas.keys()].map((name) => `"${name}"`).join(", ") || "none"}`
263
+ );
264
+ }
265
+ const compiled = /* @__PURE__ */ new Map();
266
+ for (const [name, schema] of schemas) {
267
+ compiled.set(name, compileOne(name, schema, options[name], contract.fields, fail));
268
+ }
269
+ return compiled;
270
+ }
271
+ function projectedOutput(output, projections) {
272
+ if (typeof output === "string") {
273
+ const projection2 = projections.get(output);
274
+ return projection2 === void 0 ? void 0 : { projection: projection2, kind: "one" };
275
+ }
276
+ if (!("kind" in output)) {
277
+ return void 0;
278
+ }
279
+ const projection = projections.get(output.projection);
280
+ const kind = output.kind === "nullable" ? "nullable" : "list";
281
+ return projection === void 0 ? void 0 : { projection, kind };
282
+ }
283
+ function isoDates(value) {
284
+ if (value instanceof Date) {
285
+ return value.toISOString();
286
+ }
287
+ if (!isPlain(value)) {
288
+ return value;
289
+ }
290
+ if (Array.isArray(value)) {
291
+ return value.map(isoDates);
292
+ }
293
+ const copy = {};
294
+ for (const [key, item] of Object.entries(value)) {
295
+ copy[key] = isoDates(item);
296
+ }
297
+ return copy;
298
+ }
299
+ function pickKeys(row, keys) {
300
+ const picked = {};
301
+ for (const key of keys) {
302
+ if (Object.hasOwn(row, key)) {
303
+ picked[key] = isoDates(row[key]);
304
+ }
305
+ }
306
+ return picked;
307
+ }
308
+ function projectRow(projection, row) {
309
+ if (!isRecord(row)) {
310
+ return row;
311
+ }
312
+ const source = projection.map === void 0 ? row : projection.map(row);
313
+ return isRecord(source) ? pickKeys(source, projection.keys) : source;
314
+ }
315
+ function projectOutput(output, value) {
316
+ if (output.kind === "list") {
317
+ return Array.isArray(value) ? value.map((row) => projectRow(output.projection, row)) : value;
318
+ }
319
+ if (value === null && output.kind === "nullable") {
320
+ return null;
321
+ }
322
+ return projectRow(output.projection, value);
323
+ }
324
+ function rowIds(value) {
325
+ const rows = Array.isArray(value) ? value : [value];
326
+ const ids = [];
327
+ for (const row of rows) {
328
+ if (isRecord(row) && typeof row.id === "string" && row.id.length > 0) {
329
+ ids.push(row.id);
330
+ }
331
+ }
332
+ return ids;
333
+ }
334
+ function wholeView(value) {
335
+ return { key: "", strip: () => value };
336
+ }
337
+ async function readerView(output, value, levelsOf) {
338
+ const { tiers } = output.projection;
339
+ if (!tiers.tiered || value === null || value === void 0) {
340
+ return wholeView(value);
341
+ }
342
+ const ids = [...new Set(rowIds(value))];
343
+ const levels = ids.length === 0 ? /* @__PURE__ */ new Map() : await levelsOf(ids);
344
+ const levelOf = (row) => typeof row.id === "string" ? levels.get(row.id) ?? null : null;
345
+ const rows = Array.isArray(value) ? value : [value];
346
+ const key = rows.map((row) => isRecord(row) ? tiers.label(levelOf(row)) : "-").join("");
347
+ const one = (row) => isRecord(row) ? strip(row, tiers.hidden(levelOf(row))) : row;
348
+ return { key, strip: () => Array.isArray(value) ? value.map(one) : one(value) };
349
+ }
350
+
351
+ // src/server/service.ts
352
+ var runtimes = /* @__PURE__ */ new WeakMap();
353
+ function registerRuntime(service, runtime) {
354
+ runtimes.set(service, runtime);
355
+ }
356
+ function runtimeOf(service) {
357
+ return typeof service === "object" && service !== null ? runtimes.get(service) : void 0;
358
+ }
359
+ var handlerChecks = /* @__PURE__ */ new WeakMap();
360
+ function checkWhenDefined(handler, check) {
361
+ handlerChecks.set(handler, check);
362
+ }
363
+ var grantsEditors = /* @__PURE__ */ new WeakSet();
364
+ function markGrantsEditor(handler) {
365
+ grantsEditors.add(handler);
366
+ }
367
+ function editsGrants(handler) {
368
+ return grantsEditors.has(handler);
369
+ }
370
+ function handlerProblem(handler, service) {
371
+ return handlerChecks.get(handler)?.(service);
372
+ }
373
+ var servedChecks = /* @__PURE__ */ new WeakMap();
374
+ function checkWhenServed(handler, check) {
375
+ servedChecks.set(handler, check);
376
+ }
377
+ function servedProblem(handler, served) {
378
+ return servedChecks.get(handler)?.(served);
379
+ }
380
+ function isKitHandler(handler) {
381
+ return handlerChecks.has(handler);
382
+ }
383
+ var rowChecked = /* @__PURE__ */ new WeakSet();
384
+ function checksRowsItself(handler) {
385
+ rowChecked.add(handler);
386
+ }
387
+ function isRowChecked(handler) {
388
+ return rowChecked.has(handler);
389
+ }
390
+ var callerDependent = /* @__PURE__ */ new WeakSet();
391
+ function dependsOnCaller(handler) {
392
+ callerDependent.add(handler);
393
+ }
394
+ function isCallerDependent(handler) {
395
+ return callerDependent.has(handler);
396
+ }
11
397
 
12
398
  // src/server/caller.ts
13
399
  var CALLER_GRANTS = /* @__PURE__ */ new WeakMap();
@@ -60,6 +446,12 @@ async function withLoadedGrants(principal, grants) {
60
446
  }
61
447
  return { ...principal, serviceAccess: serviceAccess ?? {} };
62
448
  }
449
+ async function withCallerGrants(principal, grants) {
450
+ if (principal === null || carriesGrants(principal) || grants === void 0) {
451
+ return principal;
452
+ }
453
+ return await withLoadedGrants(principal, grants);
454
+ }
63
455
  function principalOfCalls(principal, grants) {
64
456
  if (principal === null || carriesGrants(principal) || grants === void 0) {
65
457
  return () => principal;
@@ -91,6 +483,7 @@ function principalOfCalls(principal, grants) {
91
483
  }
92
484
  function createCaller(resolve, principal, settings = {}) {
93
485
  const principalOfCall = principalOfCalls(principal, settings.grants);
486
+ const { mcp } = settings;
94
487
  return lazyMembers(
95
488
  (service) => lazyMembers((method) => async (input, options) => {
96
489
  const runAs = principalOfCall();
@@ -101,12 +494,51 @@ function createCaller(resolve, principal, settings = {}) {
101
494
  // Awaited only while grants load: a known principal is dispatched at once, as before.
102
495
  principal: runAs instanceof Promise ? await runAs : runAs,
103
496
  transport: "internal",
104
- signal: bothSignals(settings.signal, options?.signal)
497
+ signal: bothSignals(settings.signal, options?.signal),
498
+ ...mcp === void 0 ? {} : { mcp }
105
499
  });
106
500
  })
107
501
  );
108
502
  }
109
503
 
504
+ // src/server/access/kinds.ts
505
+ function isKindList(value) {
506
+ return Array.isArray(value) && value.length > 0 && value.every((kind) => typeof kind === "string" && kind.length > 0);
507
+ }
508
+ function narrowKinds(value, above, fail) {
509
+ if (value === void 0) {
510
+ return above?.kinds;
511
+ }
512
+ if (!isKindList(value)) {
513
+ fail(
514
+ 'kinds must be a non-empty list of principal kinds (strings), such as ["user"]; leave it out to admit every kind'
515
+ );
516
+ }
517
+ if (above?.kinds !== void 0) {
518
+ const { kinds, by } = above;
519
+ const wider = value.find((kind) => !kinds.includes(kind));
520
+ if (wider !== void 0) {
521
+ fail(
522
+ `kinds may only narrow the kinds ${by} admits (${kinds.join(", ")}), and "${wider}" is not one of them`
523
+ );
524
+ }
525
+ }
526
+ return Object.freeze([...new Set(value)]);
527
+ }
528
+ function checkKind(kinds, principal, what) {
529
+ if (kinds === void 0 || principal === null) {
530
+ return;
531
+ }
532
+ const { kind } = principal;
533
+ if (typeof kind === "string" && kinds.includes(kind)) {
534
+ return;
535
+ }
536
+ throw new QuickdrawError(
537
+ "FORBIDDEN",
538
+ kind === void 0 ? `${what} is not open to a principal without a kind` : `${what} is not open to principals of kind "${String(kind)}"`
539
+ );
540
+ }
541
+
110
542
  // src/server/pipeline/errors.ts
111
543
  function cancelledError() {
112
544
  return new QuickdrawError("CANCELLED", "The call was cancelled");
@@ -147,7 +579,7 @@ function toQuickdrawError(error) {
147
579
 
148
580
  // src/server/pipeline/schemaOutput.ts
149
581
  var ANY = Object.freeze({ any: true, object: void 0, array: void 0 });
150
- function isRecord(value) {
582
+ function isRecord2(value) {
151
583
  return typeof value === "object" && value !== null && !Array.isArray(value);
152
584
  }
153
585
  function isPlainObject(value) {
@@ -169,11 +601,11 @@ function follow(ref, root) {
169
601
  } catch {
170
602
  return void 0;
171
603
  }
172
- node = isRecord(node) && Object.hasOwn(node, part) ? node[part] : void 0;
604
+ node = isRecord2(node) && Object.hasOwn(node, part) ? node[part] : void 0;
173
605
  }
174
606
  return node;
175
607
  }
176
- var BRANCHES = ["anyOf", "oneOf", "allOf"];
608
+ var BRANCHES2 = ["anyOf", "oneOf", "allOf"];
177
609
  function hasAny(node, keywords) {
178
610
  return keywords.some((keyword) => node[keyword] !== void 0);
179
611
  }
@@ -222,7 +654,7 @@ var Compiler = class {
222
654
  if (value === void 0 || value === true) {
223
655
  return this.make(true);
224
656
  }
225
- if (!isRecord(value)) {
657
+ if (!isRecord2(value)) {
226
658
  return this.make(false);
227
659
  }
228
660
  const known = this.nodes.get(value);
@@ -242,7 +674,7 @@ var Compiler = class {
242
674
  const target = follow($ref, this.root);
243
675
  node.members.push(target === void 0 ? this.make(true) : this.read(target));
244
676
  }
245
- for (const keyword of BRANCHES) {
677
+ for (const keyword of BRANCHES2) {
246
678
  const members = json[keyword];
247
679
  if (!Array.isArray(members)) {
248
680
  continue;
@@ -280,14 +712,14 @@ var Compiler = class {
280
712
  }
281
713
  readObject(json) {
282
714
  const properties = /* @__PURE__ */ new Map();
283
- if (isRecord(json.properties)) {
715
+ if (isRecord2(json.properties)) {
284
716
  for (const [key, schema] of Object.entries(json.properties)) {
285
717
  properties.set(key, this.read(schema));
286
718
  }
287
719
  }
288
720
  const patterns = [];
289
721
  let open = false;
290
- if (isRecord(json.patternProperties)) {
722
+ if (isRecord2(json.patternProperties)) {
291
723
  for (const [source, schema] of Object.entries(json.patternProperties)) {
292
724
  const regex = patternOf(source);
293
725
  if (regex === void 0) {
@@ -491,7 +923,7 @@ function keyPaths(root) {
491
923
  }
492
924
  return paths;
493
925
  }
494
- var UNREPRESENTABLE_AS_ANY = Object.freeze({ unrepresentable: "any" });
926
+ var UNREPRESENTABLE_AS_ANY2 = Object.freeze({ unrepresentable: "any" });
495
927
  function compileSchemaOutput(schema) {
496
928
  if (!hasJsonSchema(schema)) {
497
929
  return void 0;
@@ -500,12 +932,12 @@ function compileSchemaOutput(schema) {
500
932
  try {
501
933
  json = schema["~standard"].jsonSchema.output({
502
934
  target: "draft-07",
503
- libraryOptions: UNREPRESENTABLE_AS_ANY
935
+ libraryOptions: UNREPRESENTABLE_AS_ANY2
504
936
  });
505
937
  } catch {
506
938
  return void 0;
507
939
  }
508
- if (!isRecord(json)) {
940
+ if (!isRecord2(json)) {
509
941
  return void 0;
510
942
  }
511
943
  const compiler = new Compiler(json);
@@ -610,11 +1042,8 @@ function withRuntime(ctx, runtime, services) {
610
1042
  return ctx;
611
1043
  }
612
1044
  var NEVER_ABORTED = new AbortController().signal;
613
- function notAvailable(member) {
614
- return new QuickdrawError(
615
- "INTERNAL",
616
- `${member} needs a dispatcher: it calls through the dispatcher that runs the method`
617
- );
1045
+ function notAvailable(member, why) {
1046
+ return new QuickdrawError("INTERNAL", `${member} needs a dispatcher: ${why}`);
618
1047
  }
619
1048
  function untracked() {
620
1049
  }
@@ -628,23 +1057,33 @@ var INSPECTED = /* @__PURE__ */ new Set([
628
1057
  "$$typeof",
629
1058
  "nodeType"
630
1059
  ]);
631
- function unavailable(member) {
1060
+ function unavailable(member, why) {
632
1061
  return new Proxy(Object.freeze({}), {
633
1062
  get(_target, key) {
634
1063
  if (typeof key === "symbol" || INSPECTED.has(key)) {
635
1064
  return void 0;
636
1065
  }
637
- throw notAvailable(`${member}.${key}`);
1066
+ throw notAvailable(`${member}.${key}`, why);
638
1067
  }
639
1068
  });
640
1069
  }
641
- var SERVICES = unavailable("ctx.services");
1070
+ var SERVICES = unavailable(
1071
+ "ctx.services",
1072
+ "it calls through the dispatcher that runs the method"
1073
+ );
1074
+ var ACCESS = unavailable(
1075
+ "ctx.access",
1076
+ "it reads the access policies of the dispatcher that runs the method"
1077
+ );
642
1078
  var NO_ROOMS = Object.freeze({
643
1079
  join: () => false,
644
1080
  leave: ((_room, target) => target === void 0 ? false : Promise.resolve()),
645
1081
  emit: untracked,
646
1082
  emitToUser: untracked,
647
- size: () => 0
1083
+ size: () => 0,
1084
+ setHost: () => false,
1085
+ hostOf: () => null,
1086
+ clearHost: () => void 0
648
1087
  });
649
1088
  var NO_PRESENCE = Object.freeze({
650
1089
  isOnline: () => Promise.resolve(false),
@@ -652,19 +1091,20 @@ var NO_PRESENCE = Object.freeze({
652
1091
  count: () => Promise.resolve(0),
653
1092
  users: () => Promise.resolve([])
654
1093
  });
655
- function servicesOf(dispatch, principal) {
1094
+ function servicesOf(dispatch, principal, mcp) {
656
1095
  if (dispatch === void 0) {
657
1096
  return void 0;
658
1097
  }
659
- return (signal) => createCaller(() => dispatch, principal, { signal });
1098
+ return (signal) => createCaller(() => dispatch, principal, { signal, mcp });
660
1099
  }
661
1100
  function createContext(fields, extend) {
662
- const { kit, dispatch, ...own } = fields;
663
- const services = servicesOf(dispatch, own.principal);
1101
+ const { kit, dispatch, access, ...own } = fields;
1102
+ const services = servicesOf(dispatch, own.principal, own.mcp);
664
1103
  const base = Object.freeze({
665
1104
  ...own,
666
1105
  touch: own.touch ?? untracked,
667
1106
  services: services?.(own.signal) ?? SERVICES,
1107
+ access: access?.forCaller(own.principal) ?? ACCESS,
668
1108
  rooms: own.rooms ?? NO_ROOMS,
669
1109
  presence: own.presence ?? NO_PRESENCE
670
1110
  });
@@ -678,8 +1118,57 @@ function withSignal(ctx, signal) {
678
1118
  const next = services === void 0 ? { ...ctx, signal } : { ...ctx, signal, services: services(signal) };
679
1119
  return withRuntime(Object.freeze(next), KIT_RUNTIMES.get(ctx), services);
680
1120
  }
1121
+ var CALLER_MEMBERS = /* @__PURE__ */ new Set([
1122
+ "principal",
1123
+ "services",
1124
+ "mcp",
1125
+ "access"
1126
+ ]);
1127
+ function watchCallerReads(ctx, onRead) {
1128
+ const watched = new Proxy(ctx, {
1129
+ get(target, key, receiver) {
1130
+ if (CALLER_MEMBERS.has(key)) {
1131
+ onRead(key);
1132
+ }
1133
+ return Reflect.get(target, key, receiver);
1134
+ }
1135
+ });
1136
+ return withRuntime(watched, KIT_RUNTIMES.get(ctx), SERVICE_CALLERS.get(ctx));
1137
+ }
681
1138
 
682
1139
  export {
1140
+ meetsLevel,
1141
+ maxLevel,
1142
+ levelsAtLeast,
1143
+ serviceGrant,
1144
+ SUBSCRIBE_LEVEL,
1145
+ SUBSCRIBER_LEVELS,
1146
+ strip,
1147
+ referenced,
1148
+ pointerToken,
1149
+ inputKeys,
1150
+ compileProjections,
1151
+ projectedOutput,
1152
+ pickKeys,
1153
+ projectRow,
1154
+ projectOutput,
1155
+ wholeView,
1156
+ readerView,
1157
+ registerRuntime,
1158
+ runtimeOf,
1159
+ checkWhenDefined,
1160
+ markGrantsEditor,
1161
+ editsGrants,
1162
+ handlerProblem,
1163
+ checkWhenServed,
1164
+ servedProblem,
1165
+ isKitHandler,
1166
+ checksRowsItself,
1167
+ isRowChecked,
1168
+ dependsOnCaller,
1169
+ isCallerDependent,
1170
+ narrowKinds,
1171
+ checkKind,
683
1172
  cancelledError,
684
1173
  timeoutError,
685
1174
  throwIfCancelled,
@@ -693,10 +1182,12 @@ export {
693
1182
  setCallerGrants,
694
1183
  callerGrantsOf,
695
1184
  lazyMembers,
1185
+ withCallerGrants,
696
1186
  createCaller,
697
1187
  kitRuntimeOf,
698
1188
  NEVER_ABORTED,
699
1189
  createContext,
700
- withSignal
1190
+ withSignal,
1191
+ watchCallerReads
701
1192
  };
702
- //# sourceMappingURL=chunk-2PWMUVC7.js.map
1193
+ //# sourceMappingURL=chunk-OCZJ4EYV.js.map