@fitzzero/quickdraw-core 5.0.1 → 5.1.1

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 (60) hide show
  1. package/README.md +303 -32
  2. package/dist/{admin-CBlTY0do.d.ts → admin-DKwkIh5i.d.ts} +2 -2
  3. package/dist/{adminSchemas-zji11V74.d.ts → adminSchemas-2DUA_hZ8.d.ts} +1 -1
  4. package/dist/{auth-CMyRkfjZ.d.ts → auth-BhWqdyb-.d.ts} +2 -2
  5. package/dist/{caller-BqCYnpmC.d.ts → caller-CXTFswBO.d.ts} +27 -5
  6. package/dist/{chunk-2XJFNVHW.js → chunk-2PWMUVC7.js} +1 -1
  7. package/dist/{chunk-2XJFNVHW.js.map → chunk-2PWMUVC7.js.map} +1 -1
  8. package/dist/{chunk-O2PWC2YW.js → chunk-OECZPRPW.js} +3 -3
  9. package/dist/{chunk-3JNMVB2V.js → chunk-QCHKWIRS.js} +2 -2
  10. package/dist/{chunk-5YRQ26LF.js → chunk-RT6OILOI.js} +1 -1
  11. package/dist/chunk-RT6OILOI.js.map +1 -0
  12. package/dist/{chunk-NS5PUHIZ.js → chunk-RZTP4IEW.js} +130 -23
  13. package/dist/chunk-RZTP4IEW.js.map +1 -0
  14. package/dist/{chunk-HQ6WIRE2.js → chunk-SHEGLZEP.js} +4 -4
  15. package/dist/{chunk-WVIRXYI4.js → chunk-VSQBHPWH.js} +2 -2
  16. package/dist/{chunk-WVIRXYI4.js.map → chunk-VSQBHPWH.js.map} +1 -1
  17. package/dist/chunk-XNLWBZIG.js +9 -0
  18. package/dist/chunk-XNLWBZIG.js.map +1 -0
  19. package/dist/{chunk-ZACRRYWL.js → chunk-ZIVPHYRG.js} +4 -4
  20. package/dist/cli/quickdraw-docs.js +241 -27
  21. package/dist/cli/quickdraw-docs.js.map +1 -1
  22. package/dist/client/index.d.ts +7 -7
  23. package/dist/client/index.js +4 -4
  24. package/dist/{clientTypes-DuZW_8mb.d.ts → clientTypes-Bc-G8n-U.d.ts} +3 -3
  25. package/dist/{connection-DuN8GvcD.d.ts → connection-Cr1BU07W.d.ts} +2 -2
  26. package/dist/{createServer-CGsJlxM8.d.ts → createServer-CP9eDHZZ.d.ts} +30 -9
  27. package/dist/{createTestApp-Cg2CZa1g.d.ts → createTestApp-UKVGEmOf.d.ts} +6 -6
  28. package/dist/{envelope-nf5eGB-a.d.ts → envelope-Cp3YcVxC.d.ts} +1 -1
  29. package/dist/{http-D3fSFQ57.d.ts → http-Djj2Inuu.d.ts} +6 -6
  30. package/dist/index.d.ts +6 -6
  31. package/dist/index.js +26 -6
  32. package/dist/index.js.map +1 -1
  33. package/dist/{infer-Dw21kmLw.d.ts → infer-Teo1xpsd.d.ts} +17 -0
  34. package/dist/{metrics-C0WvB7-I.d.ts → metrics-BdBu5o8G.d.ts} +2 -2
  35. package/dist/prisma/index.d.ts +4 -4
  36. package/dist/server/auth/index.d.ts +3 -3
  37. package/dist/server/index.d.ts +47 -26
  38. package/dist/server/index.js +62 -36
  39. package/dist/server/index.js.map +1 -1
  40. package/dist/server/mcp/index.d.ts +51 -11
  41. package/dist/server/mcp/index.js +129 -8
  42. package/dist/server/mcp/index.js.map +1 -1
  43. package/dist/server/otel.d.ts +3 -3
  44. package/dist/{sharing-CoreezAq.d.ts → sharing-DVa8W-yR.d.ts} +3 -3
  45. package/dist/testing/client.d.ts +13 -13
  46. package/dist/testing/client.js +5 -5
  47. package/dist/testing/index.d.ts +156 -12
  48. package/dist/testing/index.js +1036 -21
  49. package/dist/testing/index.js.map +1 -1
  50. package/dist/testing/mock.d.ts +5 -5
  51. package/dist/testing/mock.js +4 -4
  52. package/dist/{types-Bwg3kIEc.d.ts → types-Cu0vmx7c.d.ts} +8 -2
  53. package/dist/utils/index.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/dist/chunk-5YRQ26LF.js.map +0 -1
  56. package/dist/chunk-NS5PUHIZ.js.map +0 -1
  57. /package/dist/{chunk-O2PWC2YW.js.map → chunk-OECZPRPW.js.map} +0 -0
  58. /package/dist/{chunk-3JNMVB2V.js.map → chunk-QCHKWIRS.js.map} +0 -0
  59. /package/dist/{chunk-HQ6WIRE2.js.map → chunk-SHEGLZEP.js.map} +0 -0
  60. /package/dist/{chunk-ZACRRYWL.js.map → chunk-ZIVPHYRG.js.map} +0 -0
@@ -1,18 +1,18 @@
1
- import { T as TestApp } from '../createTestApp-Cg2CZa1g.js';
2
- export { E as EventQuery, F as FrameMatch, d as FrameQuery, f as FrameRecorder, R as RecordedFrame, S as ServerFrameOf, a as TestAppOptions, b as TestConnection, c as createTestApp, g as emitWithAck, e as eventFrames, s as streamFrames, w as waitForEvent } from '../createTestApp-Cg2CZa1g.js';
3
- import { d as FlushSink, W as WriteRecord, e as FlushInfo, A as AnyService, f as Service } from '../caller-BqCYnpmC.js';
4
- export { g as DevWarning, D as DevWarningError, h as DevWarningKind } from '../caller-BqCYnpmC.js';
5
- import { J as AnyContract, ap as MethodName, al as InputOf } from '../infer-Dw21kmLw.js';
1
+ import { T as TestApp } from '../createTestApp-UKVGEmOf.js';
2
+ export { E as EventQuery, F as FrameMatch, d as FrameQuery, f as FrameRecorder, R as RecordedFrame, S as ServerFrameOf, a as TestAppOptions, b as TestConnection, c as createTestApp, g as emitWithAck, e as eventFrames, s as streamFrames, w as waitForEvent } from '../createTestApp-UKVGEmOf.js';
3
+ import { e as FlushSink, W as WriteRecord, f as FlushInfo, A as AnyService, g as ServiceMethod, h as Service } from '../caller-CXTFswBO.js';
4
+ export { i as DevWarning, D as DevWarningError, j as DevWarningKind } from '../caller-CXTFswBO.js';
5
+ import { P as PrincipalOfServices } from '../http-Djj2Inuu.js';
6
6
  import { a as ErrorCode } from '../errors-S-bxEIBC.js';
7
- import { P as PrincipalOfServices } from '../http-D3fSFQ57.js';
8
- import { Q as QuickdrawTypes, P as Principal } from '../types-Bwg3kIEc.js';
9
- import '../envelope-nf5eGB-a.js';
10
- import '../createServer-CGsJlxM8.js';
7
+ import { J as AnyContract, ap as MethodName, al as InputOf } from '../infer-Teo1xpsd.js';
8
+ import { Q as QuickdrawTypes, P as Principal } from '../types-Cu0vmx7c.js';
9
+ import '../envelope-Cp3YcVxC.js';
10
+ import '../createServer-CP9eDHZZ.js';
11
11
  import 'node:http';
12
- import '../auth-CMyRkfjZ.js';
12
+ import '../auth-BhWqdyb-.js';
13
13
  import 'socket.io';
14
14
  import '../logger-BY28acW-.js';
15
- import '../metrics-C0WvB7-I.js';
15
+ import '../metrics-BdBu5o8G.js';
16
16
  import 'socket.io-client';
17
17
 
18
18
  /** One flush a recording sink received. */
@@ -113,6 +113,148 @@ declare function budgetFileOf(testFile: string): string;
113
113
  */
114
114
  declare function expectBudget(run: () => unknown, options: BudgetOptions): Promise<BudgetResult>;
115
115
 
116
+ /** What one cell recorded: `"ok"`, or the error code the call or subscribe failed with. */
117
+ type AccessOutcome = "ok" | ErrorCode;
118
+ /**
119
+ * A principal as the snapshot records it: its `kind` (`null` for a principal
120
+ * without one), or `null` for the anonymous caller.
121
+ */
122
+ type AccessSnapshotPrincipal = {
123
+ readonly kind: string | null;
124
+ } | null;
125
+ /** One row of the matrix (a method, subscribe or scope, with its row variant): an outcome per principal. */
126
+ type AccessSnapshotRow = Readonly<Record<string, AccessOutcome>>;
127
+ /** The contents of an access snapshot file. */
128
+ interface AccessSnapshot {
129
+ readonly version: 1;
130
+ /** Every principal of the matrix, the anonymous caller included, by name. */
131
+ readonly principals: Readonly<Record<string, AccessSnapshotPrincipal>>;
132
+ /** Method calls: `<service>.<method>`, plus ` (<variant>)` for a row variant. */
133
+ readonly methods: Readonly<Record<string, AccessSnapshotRow>>;
134
+ /** Entity subscribes (`qd:sub`): `<service>`, plus ` (<variant>)`. */
135
+ readonly subscriptions: Readonly<Record<string, AccessSnapshotRow>>;
136
+ /** Collection scopes (`qd:col:sub`): `<service>.<collection>`, plus ` (<variant>)` (`(self)` for a `"self"` scope). */
137
+ readonly collections: Readonly<Record<string, AccessSnapshotRow>>;
138
+ /** The methods left out with `exclude`, as `<service>.<method>`. */
139
+ readonly excluded: readonly string[];
140
+ }
141
+
142
+ /** The environment variable that rewrites access snapshots: `QD_UPDATE_ACCESS_SNAPSHOT=1` (or `true`). */
143
+ declare const ACCESS_SNAPSHOT_ENV = "QD_UPDATE_ACCESS_SNAPSHOT";
144
+ /** What a run did with the snapshot file. */
145
+ type AccessSnapshotChange = "written" | "unchanged" | "updated";
146
+ /** The access snapshot file of `testFile`: `__access__/<its name>.json` in its directory. */
147
+ declare function accessSnapshotFileOf(testFile: string): string;
148
+
149
+ /** The row ids a matrix's cells are about, by service name: one id, or named variants (`{ own, other }`). */
150
+ type AccessRows = Readonly<Record<string, string | Readonly<Record<string, string>>>>;
151
+ /** The callers of a matrix by name, or a function of the fixture making them. */
152
+ type AccessPrincipals<P, Fixture, Name extends string = string> = Readonly<Record<Name, P | null>> | ((fixture: Fixture) => Readonly<Record<Name, P | null>>);
153
+
154
+ /** The cell an `inputs` function makes the input of. */
155
+ interface AccessSnapshotRef {
156
+ /** The service's name. */
157
+ readonly service: string;
158
+ /** The method's name. */
159
+ readonly method: string;
160
+ readonly kind: ServiceMethod["kind"];
161
+ /** The row variant, when `rows` names variants for the service whose row the method is about. */
162
+ readonly variant: string | undefined;
163
+ /**
164
+ * The row the cell is about, from `rows`: the method's own service's for
165
+ * an `entry` form, the `of` contract's for a `scope` form, and its own
166
+ * for any other form whose input has an `id`; `undefined` for a method
167
+ * about no row.
168
+ */
169
+ readonly row: string | undefined;
170
+ /** The name of the principal the cell runs as. */
171
+ readonly principal: string;
172
+ }
173
+ /** Options of {@link snapshotAccessMatrix}. `Fixture` is what `reset` resolves with. */
174
+ interface AccessSnapshotOptions<P, Fixture, Name extends string> {
175
+ /**
176
+ * The callers, by name, or a function of the fixture making them (read
177
+ * again after every reset, for a seed that makes new ids); their names
178
+ * must stay the same. An anonymous caller named `"anonymous"` is added
179
+ * unless one is `null`.
180
+ */
181
+ readonly principals: AccessPrincipals<P, Fixture, Name>;
182
+ /**
183
+ * Empties the database and seeds it, resolving with what the seed made
184
+ * (the fixture): the app's `resetDatabase` (from `./testing/prisma`) and
185
+ * its seed, writing with the untracked client. Called first, and again
186
+ * after every mutation the pipeline did not refuse.
187
+ */
188
+ readonly reset: () => Fixture | PromiseLike<Fixture>;
189
+ /**
190
+ * The row each service's cells are about, by service name: a row id, or
191
+ * named variants (`{ own: p1, other: p2 }`), each a row of its own in the
192
+ * snapshot. It must name every service whose rows a method's form, an
193
+ * entity subscribe or a collection scope of the matrix reads.
194
+ */
195
+ readonly rows: (fixture: Fixture) => AccessRows;
196
+ /**
197
+ * A method's input for one cell, when the generated one will not do;
198
+ * `undefined` to generate it. An input that fails the method's input
199
+ * schema is recorded as `VALIDATION` and never called.
200
+ */
201
+ readonly inputs?: (ref: AccessSnapshotRef, fixture: Fixture) => unknown;
202
+ /** The services whose methods, subscribes and scopes the matrix holds. Default: every service the app serves. */
203
+ readonly services?: readonly AnyService[];
204
+ /** Methods left out, as `<service>.<method>`: those whose outcome is not the same on every run. */
205
+ readonly exclude?: readonly string[];
206
+ /** The test file the snapshot sits beside. Default: the running test's file, from the test runner. */
207
+ readonly file?: string;
208
+ }
209
+ /** What {@link snapshotAccessMatrix} recorded, and what it did with the snapshot file. */
210
+ interface AccessSnapshotReport {
211
+ /** The snapshot file. */
212
+ readonly path: string;
213
+ /**
214
+ * `"written"`: there was no file; `"unchanged"`: the matrix is the stored
215
+ * one; `"updated"`: the file was rewritten (cells added or removed in a
216
+ * local run, or changes accepted with `QD_UPDATE_ACCESS_SNAPSHOT=1`).
217
+ */
218
+ readonly change: AccessSnapshotChange;
219
+ /** The matrix this run recorded. */
220
+ readonly snapshot: AccessSnapshot;
221
+ /**
222
+ * The cells never called because no input passed the method's input
223
+ * schema (or named the cell's row where its form reads it), as
224
+ * `<row> as <principal>`: recorded as `VALIDATION`, they pin nothing
225
+ * about access. Give their inputs with `inputs`.
226
+ */
227
+ readonly inconclusive: readonly string[];
228
+ }
229
+ /**
230
+ * Records who may call what through `app` (from `createTestApp`): every
231
+ * method of `services` (default: every service the app serves), each
232
+ * entity subscribe (`qd:sub`) and each collection scope (`qd:col:sub`), as
233
+ * every principal and anonymously, against the rows `reset` seeds, and
234
+ * compares the matrix with the snapshot file beside the test
235
+ * (`__access__/<test file>.json`, keys sorted: commit it).
236
+ *
237
+ * - A missing file is written. Under CI (`CI=1` or `CI=true`) it fails
238
+ * instead: a snapshot that writes itself pins nothing.
239
+ * - A cell whose outcome changed fails, naming the row (method and
240
+ * variant), the principal and both outcomes, and whether the change opens
241
+ * or closes access. Accept the changes with `QD_UPDATE_ACCESS_SNAPSHOT=1`,
242
+ * which rewrites the file (never under CI).
243
+ * - Cells added or removed (a new method, principal or exclusion) rewrite
244
+ * the file locally, and fail under CI.
245
+ *
246
+ * Outcomes are exact: `"ok"`, or the error code. Each principal's `kind` is
247
+ * recorded too, and a changed kind fails like a cell. A cell whose input
248
+ * failed the method's input schema is `VALIDATION`, never called, and
249
+ * listed in the report's `inconclusive`. Leave out methods whose outcome is
250
+ * not the same on every run with `exclude`. One snapshot per test file.
251
+ *
252
+ * @example
253
+ * const report = await snapshotAccessMatrix(app, { principals, reset, rows });
254
+ * expect(report.inconclusive).toEqual([]);
255
+ */
256
+ declare function snapshotAccessMatrix<S extends readonly AnyService[], Fixture, const Name extends string>(app: TestApp<S>, options: AccessSnapshotOptions<PrincipalOfServices<S>, Fixture, Name>): Promise<AccessSnapshotReport>;
257
+
116
258
  /**
117
259
  * What one cell expects: `"allow"` (the call succeeds), `"deny"` (it fails
118
260
  * with `UNAUTHENTICATED` without a principal and `FORBIDDEN` with one), or
@@ -162,6 +304,8 @@ interface AccessMatrixOptions<C extends AnyContract, P, Name extends string> {
162
304
  interface AccessMatrixCell {
163
305
  readonly case: string;
164
306
  readonly principal: string;
307
+ /** The principal's `kind`; `undefined` for the anonymous caller and a principal without one. */
308
+ readonly kind: string | undefined;
165
309
  readonly expected: MatrixOutcome;
166
310
  /** `"allow"` when the call succeeded, or its error code. */
167
311
  readonly actual: "allow" | ErrorCode;
@@ -179,4 +323,4 @@ interface AccessMatrixReport {
179
323
  */
180
324
  declare function describeAccessMatrix<S extends readonly AnyService[], C extends AnyContract, const Name extends string>(app: TestApp<S>, options: AccessMatrixOptions<C, PrincipalOfServices<S>, Name>): Promise<AccessMatrixReport>;
181
325
 
182
- export { ANONYMOUS, type AccessMatrixCase, type AccessMatrixCell, type AccessMatrixOptions, type AccessMatrixReport, BUDGET_BYTES_TOLERANCE, BUDGET_GROWTH_ENV, type Budget, type BudgetCall, type BudgetOptions, type BudgetResult, type MatrixCell, type MatrixInputFactory, type MatrixOutcome, type RecordedFlush, type RecordingSink, TestApp, budgetFileOf, createRecordingSink, describeAccessMatrix, expectBudget };
326
+ export { ACCESS_SNAPSHOT_ENV, ANONYMOUS, type AccessMatrixCase, type AccessMatrixCell, type AccessMatrixOptions, type AccessMatrixReport, type AccessOutcome, type AccessPrincipals, type AccessRows, type AccessSnapshot, type AccessSnapshotChange, type AccessSnapshotOptions, type AccessSnapshotPrincipal, type AccessSnapshotRef, type AccessSnapshotReport, type AccessSnapshotRow, BUDGET_BYTES_TOLERANCE, BUDGET_GROWTH_ENV, type Budget, type BudgetCall, type BudgetOptions, type BudgetResult, type MatrixCell, type MatrixInputFactory, type MatrixOutcome, type RecordedFlush, type RecordingSink, TestApp, accessSnapshotFileOf, budgetFileOf, createRecordingSink, describeAccessMatrix, expectBudget, snapshotAccessMatrix };