@fougere/core 0.11.0-alpha.0 → 0.12.1-alpha.0
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/dist/EffectiveOperationModel.d.ts.map +1 -1
- package/dist/EffectiveOperationModel.js +18 -0
- package/dist/EffectiveOperationModel.js.map +1 -1
- package/dist/FougereConfig.d.ts +10 -6
- package/dist/FougereConfig.d.ts.map +1 -1
- package/dist/FougereConfig.js +19 -4
- package/dist/FougereConfig.js.map +1 -1
- package/dist/FrondConfig.d.ts +0 -6
- package/dist/FrondConfig.d.ts.map +1 -1
- package/dist/FrondConfig.js.map +1 -1
- package/dist/FrondDeclaration.d.ts +2 -9
- package/dist/FrondDeclaration.d.ts.map +1 -1
- package/dist/FrondDeclaration.js +0 -1
- package/dist/FrondDeclaration.js.map +1 -1
- package/dist/FrondsStated.d.ts +54 -0
- package/dist/FrondsStated.d.ts.map +1 -0
- package/dist/FrondsStated.js +26 -0
- package/dist/FrondsStated.js.map +1 -0
- package/dist/StatedFrond.d.ts +21 -0
- package/dist/StatedFrond.d.ts.map +1 -0
- package/dist/StatedFrond.js +34 -0
- package/dist/StatedFrond.js.map +1 -0
- package/dist/StatedModules.d.ts +19 -0
- package/dist/StatedModules.d.ts.map +1 -0
- package/dist/StatedModules.js +37 -0
- package/dist/StatedModules.js.map +1 -0
- package/dist/boot/CreateAppOptions.d.ts +19 -2
- package/dist/boot/CreateAppOptions.d.ts.map +1 -1
- package/dist/boot/Emissions.d.ts +9 -0
- package/dist/boot/Emissions.d.ts.map +1 -1
- package/dist/boot/Emissions.js +11 -5
- package/dist/boot/Emissions.js.map +1 -1
- package/dist/boot/bootstrap.d.ts.map +1 -1
- package/dist/boot/bootstrap.js +342 -307
- package/dist/boot/bootstrap.js.map +1 -1
- package/dist/boot/declared.d.ts.map +1 -1
- package/dist/boot/declared.js +3 -0
- package/dist/boot/declared.js.map +1 -1
- package/dist/boot/frame.d.ts +0 -4
- package/dist/boot/frame.d.ts.map +1 -1
- package/dist/boot/frame.js +31 -14
- package/dist/boot/frame.js.map +1 -1
- package/dist/boot/hosted.d.ts.map +1 -1
- package/dist/boot/hosted.js +4 -3
- package/dist/boot/hosted.js.map +1 -1
- package/dist/boot/install.d.ts +9 -0
- package/dist/boot/install.d.ts.map +1 -1
- package/dist/boot/install.js +275 -185
- package/dist/boot/install.js.map +1 -1
- package/dist/boot/nesting.d.ts +33 -0
- package/dist/boot/nesting.d.ts.map +1 -0
- package/dist/boot/nesting.js +164 -0
- package/dist/boot/nesting.js.map +1 -0
- package/dist/boot/ownership.d.ts +0 -1
- package/dist/boot/ownership.d.ts.map +1 -1
- package/dist/boot/ownership.js +66 -51
- package/dist/boot/ownership.js.map +1 -1
- package/dist/boot/ports.js +30 -25
- package/dist/boot/ports.js.map +1 -1
- package/dist/boot/remote.d.ts.map +1 -1
- package/dist/boot/remote.js +39 -30
- package/dist/boot/remote.js.map +1 -1
- package/dist/boot/seed.d.ts.map +1 -1
- package/dist/boot/seed.js +27 -20
- package/dist/boot/seed.js.map +1 -1
- package/dist/boot/together.d.ts.map +1 -1
- package/dist/boot/together.js +71 -56
- package/dist/boot/together.js.map +1 -1
- package/dist/contract.d.ts +2 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +2 -0
- package/dist/contract.js.map +1 -1
- package/dist/descriptor/FrondDescriptor.d.ts +7 -0
- package/dist/descriptor/FrondDescriptor.d.ts.map +1 -1
- package/dist/descriptor/MiddlewareEntry.d.ts +6 -5
- package/dist/descriptor/MiddlewareEntry.d.ts.map +1 -1
- package/dist/descriptor/ProviderEntry.d.ts +7 -0
- package/dist/descriptor/ProviderEntry.d.ts.map +1 -1
- package/dist/dispatch/HandlerFacade.d.ts +6 -1
- package/dist/dispatch/HandlerFacade.d.ts.map +1 -1
- package/dist/dispatch/HandlerFacade.js +23 -20
- package/dist/dispatch/HandlerFacade.js.map +1 -1
- package/dist/dispatch/OutputView.d.ts.map +1 -1
- package/dist/dispatch/OutputView.js +7 -0
- package/dist/dispatch/OutputView.js.map +1 -1
- package/dist/dispatch/PresenterExecutor.d.ts +6 -0
- package/dist/dispatch/PresenterExecutor.d.ts.map +1 -1
- package/dist/dispatch/PresenterExecutor.js +37 -22
- package/dist/dispatch/PresenterExecutor.js.map +1 -1
- package/dist/dispatch/Received.d.ts +3 -0
- package/dist/dispatch/Received.d.ts.map +1 -0
- package/dist/dispatch/Received.js +2 -0
- package/dist/dispatch/Received.js.map +1 -0
- package/dist/dispatch/Release.js +53 -47
- package/dist/dispatch/Release.js.map +1 -1
- package/dist/dispatch/StorageGuard.d.ts +21 -0
- package/dist/dispatch/StorageGuard.d.ts.map +1 -1
- package/dist/dispatch/StorageGuard.js +84 -66
- package/dist/dispatch/StorageGuard.js.map +1 -1
- package/dist/dispatch/decoded.d.ts +19 -0
- package/dist/dispatch/decoded.d.ts.map +1 -0
- package/dist/dispatch/decoded.js +36 -0
- package/dist/dispatch/decoded.js.map +1 -0
- package/dist/entry/facade.d.ts +9 -2
- package/dist/entry/facade.d.ts.map +1 -1
- package/dist/entry/facade.js +16 -7
- package/dist/entry/facade.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +2 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +2 -1
- package/dist/node.js.map +1 -1
- package/dist/prefab/CrudConstructor.d.ts.map +1 -1
- package/dist/prefab/CrudConstructor.js +3 -2
- package/dist/prefab/CrudConstructor.js.map +1 -1
- package/dist/prefab/CrudOps.d.ts +2 -2
- package/dist/prefab/CrudOps.d.ts.map +1 -1
- package/dist/prefab/MirrorConstructor.js +1 -1
- package/dist/prefab/MirrorConstructor.js.map +1 -1
- package/dist/prefab/Refreshed.d.ts +7 -2
- package/dist/prefab/Refreshed.d.ts.map +1 -1
- package/dist/storage/Storage.js +1 -1
- package/dist/storage/Storage.js.map +1 -1
- package/dist/storage/Store.d.ts.map +1 -1
- package/dist/storage/Store.js +35 -31
- package/dist/storage/Store.js.map +1 -1
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +14 -0
- package/dist/verify.js.map +1 -1
- package/dist/wire/AppMiddleware.d.ts +10 -1
- package/dist/wire/AppMiddleware.d.ts.map +1 -1
- package/dist/wire/AppMiddleware.js.map +1 -1
- package/dist/wire/AppNext.d.ts +2 -1
- package/dist/wire/AppNext.d.ts.map +1 -1
- package/dist/wire/Facade.d.ts +14 -2
- package/dist/wire/Facade.d.ts.map +1 -1
- package/dist/wire/Facade.js.map +1 -1
- package/dist/wire/FougereError.js +1 -1
- package/dist/wire/FougereError.js.map +1 -1
- package/dist/wire/Invocation.d.ts +1 -1
- package/dist/wire/Invocation.d.ts.map +1 -1
- package/dist/wire/Invocation.js +1 -1
- package/dist/wire/Invocation.js.map +1 -1
- package/dist/wire/OperationContract.js +1 -1
- package/dist/wire/OperationContract.js.map +1 -1
- package/dist/wire/Page.d.ts +32 -0
- package/dist/wire/Page.d.ts.map +1 -0
- package/dist/wire/Page.js +32 -0
- package/dist/wire/Page.js.map +1 -0
- package/dist/wire/Signature.d.ts +7 -0
- package/dist/wire/Signature.d.ts.map +1 -1
- package/dist/wire/binding.d.ts.map +1 -1
- package/dist/wire/binding.js +29 -57
- package/dist/wire/binding.js.map +1 -1
- package/dist/wire/drift.d.ts.map +1 -1
- package/dist/wire/drift.js +22 -19
- package/dist/wire/drift.js.map +1 -1
- package/package.json +4 -4
- package/src/EffectiveOperationModel.ts +19 -0
- package/src/FougereConfig.ts +24 -10
- package/src/FrondConfig.ts +0 -6
- package/src/FrondDeclaration.ts +2 -7
- package/src/FrondsStated.ts +72 -0
- package/src/StatedFrond.ts +51 -0
- package/src/StatedModules.ts +58 -0
- package/src/boot/CreateAppOptions.ts +19 -2
- package/src/boot/Emissions.ts +16 -5
- package/src/boot/bootstrap.ts +478 -359
- package/src/boot/declared.ts +3 -0
- package/src/boot/frame.ts +42 -11
- package/src/boot/hosted.ts +4 -3
- package/src/boot/install.ts +392 -212
- package/src/boot/nesting.ts +196 -0
- package/src/boot/ownership.ts +79 -51
- package/src/boot/ports.ts +45 -31
- package/src/boot/remote.ts +57 -32
- package/src/boot/seed.ts +36 -27
- package/src/boot/together.ts +98 -63
- package/src/contract.ts +2 -0
- package/src/descriptor/FrondDescriptor.ts +7 -0
- package/src/descriptor/MiddlewareEntry.ts +6 -5
- package/src/descriptor/ProviderEntry.ts +7 -0
- package/src/dispatch/HandlerFacade.ts +27 -17
- package/src/dispatch/OutputView.ts +7 -0
- package/src/dispatch/PresenterExecutor.ts +40 -22
- package/src/dispatch/Received.ts +2 -0
- package/src/dispatch/Release.ts +68 -44
- package/src/dispatch/StorageGuard.ts +90 -69
- package/src/dispatch/decoded.ts +37 -0
- package/src/entry/facade.ts +21 -9
- package/src/index.ts +4 -0
- package/src/node.ts +2 -1
- package/src/prefab/CrudConstructor.ts +3 -2
- package/src/prefab/CrudOps.ts +2 -2
- package/src/prefab/MirrorConstructor.ts +1 -1
- package/src/prefab/Refreshed.ts +7 -2
- package/src/storage/Storage.ts +2 -2
- package/src/storage/Store.ts +45 -27
- package/src/verify.ts +15 -0
- package/src/wire/AppMiddleware.ts +10 -1
- package/src/wire/AppNext.ts +2 -1
- package/src/wire/Facade.ts +14 -2
- package/src/wire/FougereError.ts +1 -1
- package/src/wire/Invocation.ts +2 -1
- package/src/wire/OperationContract.ts +1 -1
- package/src/wire/Page.ts +50 -0
- package/src/wire/Signature.ts +7 -0
- package/src/wire/binding.ts +26 -58
- package/src/wire/drift.ts +48 -21
|
@@ -7,5 +7,11 @@ export declare class PresenterExecutor {
|
|
|
7
7
|
private readonly operation;
|
|
8
8
|
constructor(presenter: Record<string, unknown> | undefined, fieldNames: readonly string[] | undefined, entity?: string, operation?: string);
|
|
9
9
|
present(result: unknown, args?: PresenterArgs): Promise<unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* One computed field, handed the whole PAGE — so one query per page is possible where one per
|
|
12
|
+
* row was not. It answers for every row or for none: a shorter list would silently shift the
|
|
13
|
+
* values onto the wrong rows.
|
|
14
|
+
*/
|
|
15
|
+
private computed;
|
|
10
16
|
}
|
|
11
17
|
//# sourceMappingURL=PresenterExecutor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresenterExecutor.d.ts","sourceRoot":"","sources":["../../src/dispatch/PresenterExecutor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"PresenterExecutor.d.ts","sourceRoot":"","sources":["../../src/dispatch/PresenterExecutor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,kEAAkE;AAClE,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAHT,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC9C,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACzC,MAAM,SAAY,EAClB,SAAS,SAAY;IAGlC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IA8B1E;;;;OAIG;YACW,QAAQ;CAsBvB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ErrorCode } from '../wire/ErrorCode.js';
|
|
2
2
|
import { FougereError } from '../wire/FougereError.js';
|
|
3
3
|
import { preserveArrayProperties } from './ArrayResult.js';
|
|
4
|
+
import { asPage } from '../wire/Page.js';
|
|
4
5
|
/** Adds a presenter's computed fields after output projection. */
|
|
5
6
|
export class PresenterExecutor {
|
|
6
7
|
presenter;
|
|
@@ -17,29 +18,18 @@ export class PresenterExecutor {
|
|
|
17
18
|
if (!this.presenter || !this.fieldNames?.length || result === null || typeof result !== 'object') {
|
|
18
19
|
return result;
|
|
19
20
|
}
|
|
21
|
+
// A paged op answers an envelope, and what a computed field sits on is a ROW. Handed the
|
|
22
|
+
// envelope itself, a presenter added its fields to `{ items, total }` and every row came
|
|
23
|
+
// back untouched.
|
|
24
|
+
const page = asPage(result, Object.fromEntries(this.fieldNames.map((name) => [name, true])));
|
|
25
|
+
if (page)
|
|
26
|
+
return { ...page, items: await this.present(page.items, args) };
|
|
20
27
|
const rows = Array.isArray(result) ? result : [result];
|
|
21
28
|
const values = new Map();
|
|
22
29
|
for (const name of this.fieldNames) {
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
continue;
|
|
26
|
-
try {
|
|
27
|
-
const answered = await field.call(this.presenter, rows, ...(args[name] ?? []));
|
|
28
|
-
if (!Array.isArray(answered) || answered.length !== rows.length) {
|
|
29
|
-
const actual = Array.isArray(answered) ? answered.length : typeof answered;
|
|
30
|
-
throw new Error(`expected ${rows.length} value(s) for ${rows.length} row(s), got ${actual}`);
|
|
31
|
-
}
|
|
30
|
+
const answered = await this.computed(name, rows, args[name] ?? []);
|
|
31
|
+
if (answered)
|
|
32
32
|
values.set(name, answered);
|
|
33
|
-
}
|
|
34
|
-
catch (cause) {
|
|
35
|
-
throw new FougereError({
|
|
36
|
-
code: ErrorCode.INTERNAL_ERROR,
|
|
37
|
-
message: `Computed field '${name}' failed: ${cause?.message ?? cause}`,
|
|
38
|
-
entity: this.entity,
|
|
39
|
-
operation: this.operation,
|
|
40
|
-
cause,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
33
|
}
|
|
44
34
|
const enriched = rows.map((item, index) => {
|
|
45
35
|
if (item === null || typeof item !== 'object')
|
|
@@ -49,9 +39,34 @@ export class PresenterExecutor {
|
|
|
49
39
|
output[name] = answered[index];
|
|
50
40
|
return output;
|
|
51
41
|
});
|
|
52
|
-
return Array.isArray(result)
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
return Array.isArray(result) ? preserveArrayProperties(result, enriched) : enriched[0];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* One computed field, handed the whole PAGE — so one query per page is possible where one per
|
|
46
|
+
* row was not. It answers for every row or for none: a shorter list would silently shift the
|
|
47
|
+
* values onto the wrong rows.
|
|
48
|
+
*/
|
|
49
|
+
async computed(name, rows, args) {
|
|
50
|
+
const field = this.presenter?.[name];
|
|
51
|
+
if (typeof field !== 'function')
|
|
52
|
+
return undefined;
|
|
53
|
+
try {
|
|
54
|
+
const answered = await field.call(this.presenter, rows, ...args);
|
|
55
|
+
if (!Array.isArray(answered) || answered.length !== rows.length) {
|
|
56
|
+
const actual = Array.isArray(answered) ? answered.length : typeof answered;
|
|
57
|
+
throw new Error(`expected ${rows.length} value(s) for ${rows.length} row(s), got ${actual}`);
|
|
58
|
+
}
|
|
59
|
+
return answered;
|
|
60
|
+
}
|
|
61
|
+
catch (cause) {
|
|
62
|
+
throw new FougereError({
|
|
63
|
+
code: ErrorCode.INTERNAL_ERROR,
|
|
64
|
+
message: `Computed field '${name}' failed: ${cause?.message ?? cause}`,
|
|
65
|
+
entity: this.entity,
|
|
66
|
+
operation: this.operation,
|
|
67
|
+
cause,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
72
|
//# sourceMappingURL=PresenterExecutor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PresenterExecutor.js","sourceRoot":"","sources":["../../src/dispatch/PresenterExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"PresenterExecutor.js","sourceRoot":"","sources":["../../src/dispatch/PresenterExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Received.d.ts","sourceRoot":"","sources":["../../src/dispatch/Received.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Received.js","sourceRoot":"","sources":["../../src/dispatch/Received.ts"],"names":[],"mappings":""}
|
package/dist/dispatch/Release.js
CHANGED
|
@@ -58,55 +58,10 @@ async function walk(entity, keys, world, seen, trail) {
|
|
|
58
58
|
// dependents, and declaration order would otherwise let a cascade beside a `restrict` win.
|
|
59
59
|
// Depth needs no such pass — a level acts only once the level below it came back.
|
|
60
60
|
for (const dependent of dependents.filter((one) => one.onDelete === 'restrict')) {
|
|
61
|
-
|
|
62
|
-
if (!rows)
|
|
63
|
-
continue;
|
|
64
|
-
const found = [...(await rows.findAllByKeys(dependent.field, keys.map(String))).values()].flat();
|
|
65
|
-
if (found.length === 0)
|
|
66
|
-
continue;
|
|
67
|
-
throw new FougereError({
|
|
68
|
-
code: ErrorCode.CONFLICT,
|
|
69
|
-
message: `${dependent.entity}.${dependent.field} holds ${found.length} row(s) naming this one, `
|
|
70
|
-
+ `and states onDelete 'restrict' — take them out first, or declare what should happen.`,
|
|
71
|
-
entity,
|
|
72
|
-
operation: 'delete',
|
|
73
|
-
});
|
|
61
|
+
await refuseHeld(entity, dependent, keys, world);
|
|
74
62
|
}
|
|
75
63
|
for (const dependent of dependents.filter((one) => one.onDelete !== 'restrict')) {
|
|
76
|
-
|
|
77
|
-
// Nothing here holds those rows. The process that does answers the same two readings core
|
|
78
|
-
// serves everywhere, so the ask crosses and the work happens on ITS side of the wire —
|
|
79
|
-
// which is what keeps the declaration identical whatever the topology.
|
|
80
|
-
// Nothing here holds those rows: every declared remote is asked about THIS level, and the
|
|
81
|
-
// one that holds them walks its own tree from there. The trail grows by one mark per level,
|
|
82
|
-
// so a deeper ask is never mistaken for the bounce of a shallower one.
|
|
83
|
-
if (!rows) {
|
|
84
|
-
for (const key of keys) {
|
|
85
|
-
// A level already on the trail is one somebody is asking every process about, so
|
|
86
|
-
// asking again is the bounce — the same reason `release` reads it before crossing.
|
|
87
|
-
if (trail.includes(`${entity}#${String(key)}`))
|
|
88
|
-
continue;
|
|
89
|
-
for (const peer of world.peers())
|
|
90
|
-
await peer.release(entity, key, trail);
|
|
91
|
-
}
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
const naming = await rows.findAllByKeys(dependent.field, keys.map(String));
|
|
95
|
-
const found = [...naming.values()].flat();
|
|
96
|
-
if (found.length === 0)
|
|
97
|
-
continue;
|
|
98
|
-
if (dependent.onDelete === 'set null') {
|
|
99
|
-
const primary = keyOf(world, dependent.entity);
|
|
100
|
-
for (const row of found)
|
|
101
|
-
await rows.update(String(row[primary]), { [dependent.field]: null });
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
const primary = keyOf(world, dependent.entity);
|
|
105
|
-
const below = found.map((row) => row[primary]).filter((id) => !taken(seen, dependent.entity, id));
|
|
106
|
-
// Deepest first: what names THESE rows goes before they do, all the way down.
|
|
107
|
-
await walk(dependent.entity, below, world, seen, trail);
|
|
108
|
-
for (const id of below)
|
|
109
|
-
await rows.delete(String(id));
|
|
64
|
+
await carryOut(entity, dependent, keys, world, seen, trail);
|
|
110
65
|
}
|
|
111
66
|
}
|
|
112
67
|
/** True once, and remembers — a key already on the path is what ends a cycle. */
|
|
@@ -121,4 +76,55 @@ function keyOf(world, entity) {
|
|
|
121
76
|
const schema = world.schemaOf(entity);
|
|
122
77
|
return (schema && FieldSet.of(schema.getFields()).primary) ?? 'id';
|
|
123
78
|
}
|
|
79
|
+
/** What names these rows and states `restrict` stops the whole release, before anything moves. */
|
|
80
|
+
async function refuseHeld(entity, dependent, keys, world) {
|
|
81
|
+
const rows = world.rowsOf(dependent.entity);
|
|
82
|
+
if (!rows)
|
|
83
|
+
return;
|
|
84
|
+
const found = [...(await rows.findAllByKeys(dependent.field, keys.map(String))).values()].flat();
|
|
85
|
+
if (found.length === 0)
|
|
86
|
+
return;
|
|
87
|
+
throw new FougereError({
|
|
88
|
+
code: ErrorCode.CONFLICT,
|
|
89
|
+
message: `${dependent.entity}.${dependent.field} holds ${found.length} row(s) naming this one, `
|
|
90
|
+
+ `and states onDelete 'restrict' — take them out first, or declare what should happen.`,
|
|
91
|
+
entity,
|
|
92
|
+
operation: 'delete',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* One dependent level: cleared here, or asked of whoever holds it.
|
|
97
|
+
*
|
|
98
|
+
* Nothing here holds those rows — every declared remote is asked about THIS level, and the one
|
|
99
|
+
* that holds them walks its own tree from there. The trail grows by one mark per level, so a
|
|
100
|
+
* deeper ask is never mistaken for the bounce of a shallower one.
|
|
101
|
+
*/
|
|
102
|
+
async function carryOut(entity, dependent, keys, world, seen, trail) {
|
|
103
|
+
const rows = world.rowsOf(dependent.entity);
|
|
104
|
+
if (!rows) {
|
|
105
|
+
for (const key of keys) {
|
|
106
|
+
// A level already on the trail is one somebody is asking every process about, so asking
|
|
107
|
+
// again is the bounce — the same reason `release` reads it before crossing.
|
|
108
|
+
if (trail.includes(`${entity}#${String(key)}`))
|
|
109
|
+
continue;
|
|
110
|
+
for (const peer of world.peers())
|
|
111
|
+
await peer.release(entity, key, trail);
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const found = [...(await rows.findAllByKeys(dependent.field, keys.map(String))).values()].flat();
|
|
116
|
+
if (found.length === 0)
|
|
117
|
+
return;
|
|
118
|
+
const primary = keyOf(world, dependent.entity);
|
|
119
|
+
if (dependent.onDelete === 'set null') {
|
|
120
|
+
for (const row of found)
|
|
121
|
+
await rows.update(String(row[primary]), { [dependent.field]: null });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const below = found.map((row) => row[primary]).filter((id) => !taken(seen, dependent.entity, id));
|
|
125
|
+
// Deepest first: what names THESE rows goes before they do, all the way down.
|
|
126
|
+
await walk(dependent.entity, below, world, seen, trail);
|
|
127
|
+
for (const id of below)
|
|
128
|
+
await rows.delete(String(id));
|
|
129
|
+
}
|
|
124
130
|
//# sourceMappingURL=Release.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Release.js","sourceRoot":"","sources":["../../src/dispatch/Release.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,QAAQ,EAAmB,MAAM,iBAAiB,CAAC;AAG5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAoBvD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAc,EACd,GAAY,EACZ,KAAgB,EAChB,UAA6B,EAAE,EAC/B,GAA4B;IAE5B,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACxC,yFAAyF;IACzF,2FAA2F;IAC3F,4FAA4F;IAC5F,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC;IAEnD,6FAA6F;IAC7F,2DAA2D;IAC3D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,OAAO,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM;QAAE,OAAO;IAE1E,8FAA8F;IAC9F,oFAAoF;IACpF,IAAI,CAAC,KAAK;QAAE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAErF,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,OAAO,EAAE,CAAC;QACjB,sFAAsF;QACtF,qFAAqF;QACrF,2DAA2D;QAC3D,IAAI,OAAO,YAAY,YAAY;YAAE,MAAM,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/E,MAAM,OAAO,CAAC;IAChB,CAAC;IAED,0FAA0F;IAC1F,sFAAsF;IACtF,6FAA6F;IAC7F,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,EAAE,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,MAAc,EACd,IAAwB,EACxB,KAAgB,EAChB,IAAiB,EACjB,KAAwB;IAExB,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"Release.js","sourceRoot":"","sources":["../../src/dispatch/Release.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,15 @@ export declare class StorageGuard {
|
|
|
13
13
|
private readonly said;
|
|
14
14
|
constructor(fields: Fields, entity: string, report?: GuardReport, relations?: readonly RelationCheck[], releasing?: Releasing | undefined);
|
|
15
15
|
guard<T extends object>(storage: T): T;
|
|
16
|
+
/**
|
|
17
|
+
* What names this row goes first, and this row last: an interruption then leaves fewer
|
|
18
|
+
* children rather than an orphan. A key holds the rest, at the rows, in one statement.
|
|
19
|
+
*/
|
|
20
|
+
private guardDelete;
|
|
21
|
+
/** Every gesture that puts a row down: judged first, and handed on the value it parsed. */
|
|
22
|
+
private guardWrites;
|
|
23
|
+
/** A criterion is read where the entity declares it, so a page is asked for what it can answer. */
|
|
24
|
+
private guardList;
|
|
16
25
|
/**
|
|
17
26
|
* The values this write carries, validated and handed on PARSED — the rule the client facade
|
|
18
27
|
* already holds (`InputValidator`), applied to a write that never passed through it. What a
|
|
@@ -28,6 +37,13 @@ export declare class StorageGuard {
|
|
|
28
37
|
* array is judged member by member, since that is what `IN` binds.
|
|
29
38
|
*/
|
|
30
39
|
private criteria;
|
|
40
|
+
/**
|
|
41
|
+
* One criterion, told from a value by the FIELD and never by its own shape.
|
|
42
|
+
*
|
|
43
|
+
* A comparison names its own vocabulary, and a typo in it would otherwise be a criterion that
|
|
44
|
+
* filters nothing — the silent truncation this facade exists to stop.
|
|
45
|
+
*/
|
|
46
|
+
private criterion;
|
|
31
47
|
/**
|
|
32
48
|
* A filter on a field this facade does not hand back.
|
|
33
49
|
*
|
|
@@ -39,6 +55,11 @@ export declare class StorageGuard {
|
|
|
39
55
|
*/
|
|
40
56
|
private beyondTheView;
|
|
41
57
|
/** One value against one field — validated, then decoded the way the wire hands it. */
|
|
58
|
+
/**
|
|
59
|
+
* One key a handler wrote. A key the entity does not declare has no column to land in and no
|
|
60
|
+
* judge to pass: on the client facade it is a typo, and on this one a mapping that went stale.
|
|
61
|
+
*/
|
|
62
|
+
private written;
|
|
42
63
|
private value;
|
|
43
64
|
private validated;
|
|
44
65
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageGuard.d.ts","sourceRoot":"","sources":["../../src/dispatch/StorageGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"StorageGuard.d.ts","sourceRoot":"","sources":["../../src/dispatch/StorageGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AAKzG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAYvD,sFAAsF;AACtF,qBAAa,YAAY;IAKrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAR7B,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;gBAGvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,WAAgB,EACxB,SAAS,GAAE,SAAS,aAAa,EAAO,EACxC,SAAS,CAAC,EAAE,SAAS,YAAA;IAGxC,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC;IAatC;;;OAGG;IACH,OAAO,CAAC,WAAW;IAenB,2FAA2F;IAC3F,OAAO,CAAC,WAAW;IAoCnB,mGAAmG;IACnG,OAAO,CAAC,SAAS;IAcjB;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAMb;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IA0BhB;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAqBjB;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAUrB,uFAAuF;IACvF;;;OAGG;IACH,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,SAAS;IA0BjB;;;;;;;;;;;OAWG;YACW,SAAS;CAwBxB"}
|
|
@@ -24,20 +24,32 @@ export class StorageGuard {
|
|
|
24
24
|
const writer = storage;
|
|
25
25
|
if (typeof writer.create !== 'function' || typeof writer.update !== 'function')
|
|
26
26
|
return storage;
|
|
27
|
-
const validation = this;
|
|
28
27
|
const guarded = Object.create(storage);
|
|
28
|
+
this.guardDelete(guarded, writer);
|
|
29
|
+
this.guardWrites(guarded, writer);
|
|
30
|
+
this.guardList(guarded, writer);
|
|
31
|
+
return guarded;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What names this row goes first, and this row last: an interruption then leaves fewer
|
|
35
|
+
* children rather than an orphan. A key holds the rest, at the rows, in one statement.
|
|
36
|
+
*/
|
|
37
|
+
guardDelete(guarded, writer) {
|
|
29
38
|
const remove = writer.delete;
|
|
30
|
-
if (typeof remove
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
if (typeof remove !== 'function' || !this.releasing)
|
|
40
|
+
return;
|
|
41
|
+
const validation = this;
|
|
42
|
+
guarded.delete = async function (id) {
|
|
43
|
+
let gone = false;
|
|
44
|
+
await release(validation.entity, id, validation.releasing, [], async () => {
|
|
45
|
+
gone = await remove.call(this, id);
|
|
46
|
+
});
|
|
47
|
+
return gone;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Every gesture that puts a row down: judged first, and handed on the value it parsed. */
|
|
51
|
+
guardWrites(guarded, writer) {
|
|
52
|
+
const validation = this;
|
|
41
53
|
guarded.create = async function (...args) {
|
|
42
54
|
args[0] = validation.validated(args[0], 'create');
|
|
43
55
|
await validation.targetsOf([args[0]], 'create');
|
|
@@ -58,27 +70,28 @@ export class StorageGuard {
|
|
|
58
70
|
}
|
|
59
71
|
const upsertAll = writer.upsertAll;
|
|
60
72
|
if (typeof upsertAll === 'function') {
|
|
61
|
-
// Every row before the first write
|
|
62
|
-
//
|
|
73
|
+
// Every row before the first write, and the keys of the whole page in one read per
|
|
74
|
+
// relation: a page refused on its fourth row has already written three.
|
|
63
75
|
guarded.upsertAll = async function (...args) {
|
|
64
76
|
args[0] = args[0].map((row, index) => validation.validated(row, 'upsertAll', index));
|
|
65
|
-
// The keys of the whole page in one read per relation, for the reason above: a page
|
|
66
|
-
// refused on its fourth row has already written three.
|
|
67
77
|
await validation.targetsOf(args[0], 'upsertAll');
|
|
68
78
|
return upsertAll.apply(this, args);
|
|
69
79
|
};
|
|
70
80
|
}
|
|
81
|
+
}
|
|
82
|
+
/** A criterion is read where the entity declares it, so a page is asked for what it can answer. */
|
|
83
|
+
guardList(guarded, writer) {
|
|
71
84
|
const list = writer.list;
|
|
72
|
-
if (typeof list
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
if (typeof list !== 'function')
|
|
86
|
+
return;
|
|
87
|
+
const validation = this;
|
|
88
|
+
guarded.list = async function (...args) {
|
|
89
|
+
const options = args[0];
|
|
90
|
+
assertListOptions(options, validation.entity, Object.keys(validation.fields));
|
|
91
|
+
if (options?.where)
|
|
92
|
+
args[0] = { ...options, where: validation.criteria(options.where) };
|
|
93
|
+
return list.apply(this, args);
|
|
94
|
+
};
|
|
82
95
|
}
|
|
83
96
|
/**
|
|
84
97
|
* The values this write carries, validated and handed on PARSED — the rule the client facade
|
|
@@ -102,33 +115,13 @@ export class StorageGuard {
|
|
|
102
115
|
const errors = [];
|
|
103
116
|
const parsed = {};
|
|
104
117
|
for (const [key, asked] of Object.entries(where)) {
|
|
105
|
-
const
|
|
106
|
-
if (
|
|
107
|
-
errors.push(`${key}: ${
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// A comparison names its own vocabulary, and a typo in it would otherwise be a
|
|
111
|
-
// criterion that filters nothing — the silent truncation this facade exists to stop.
|
|
112
|
-
const comparison = comparisonOf(field, asked);
|
|
113
|
-
if (comparison) {
|
|
114
|
-
const unknown = unknownIn(comparison);
|
|
115
|
-
if (unknown.length) {
|
|
116
|
-
errors.push(`${key}: unknown comparison ${unknown.join(', ')} — one of ${COMPARISONS.join(', ')}`);
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
parsed[key] = comparison;
|
|
118
|
+
const read = this.criterion(key, asked);
|
|
119
|
+
if ('message' in read)
|
|
120
|
+
errors.push(`${key}: ${read.message}`);
|
|
121
|
+
else {
|
|
122
|
+
parsed[key] = read.value;
|
|
120
123
|
this.beyondTheView(key);
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
const values = Array.isArray(asked) ? asked : [asked];
|
|
124
|
-
const each = values.map((value) => this.value(field, value));
|
|
125
|
-
const refused = each.find((one) => typeof one === 'object' && one !== null && 'error' in one);
|
|
126
|
-
if (refused) {
|
|
127
|
-
errors.push(`${key}: ${refused.error}`);
|
|
128
|
-
continue;
|
|
129
124
|
}
|
|
130
|
-
parsed[key] = Array.isArray(asked) ? each.map(unwrap) : unwrap(each[0]);
|
|
131
|
-
this.beyondTheView(key);
|
|
132
125
|
}
|
|
133
126
|
if (errors.length > 0) {
|
|
134
127
|
throw new FougereError({
|
|
@@ -141,6 +134,30 @@ export class StorageGuard {
|
|
|
141
134
|
}
|
|
142
135
|
return parsed;
|
|
143
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* One criterion, told from a value by the FIELD and never by its own shape.
|
|
139
|
+
*
|
|
140
|
+
* A comparison names its own vocabulary, and a typo in it would otherwise be a criterion that
|
|
141
|
+
* filters nothing — the silent truncation this facade exists to stop.
|
|
142
|
+
*/
|
|
143
|
+
criterion(key, asked) {
|
|
144
|
+
const field = this.fields[key];
|
|
145
|
+
if (!field)
|
|
146
|
+
return { message: InputRefusal.unknownField };
|
|
147
|
+
const comparison = comparisonOf(field, asked);
|
|
148
|
+
if (comparison) {
|
|
149
|
+
const unknown = unknownIn(comparison);
|
|
150
|
+
return unknown.length
|
|
151
|
+
? { message: `unknown comparison ${unknown.join(', ')} — one of ${COMPARISONS.join(', ')}` }
|
|
152
|
+
: { value: comparison };
|
|
153
|
+
}
|
|
154
|
+
const values = Array.isArray(asked) ? asked : [asked];
|
|
155
|
+
const each = values.map((value) => this.value(field, value));
|
|
156
|
+
const refused = each.find((one) => 'message' in one);
|
|
157
|
+
if (refused)
|
|
158
|
+
return refused;
|
|
159
|
+
return { value: Array.isArray(asked) ? each.map(unwrap) : unwrap(each[0]) };
|
|
160
|
+
}
|
|
144
161
|
/**
|
|
145
162
|
* A filter on a field this facade does not hand back.
|
|
146
163
|
*
|
|
@@ -159,6 +176,18 @@ export class StorageGuard {
|
|
|
159
176
|
+ 'a filter on a hidden field answers questions about it one call at a time.');
|
|
160
177
|
}
|
|
161
178
|
/** One value against one field — validated, then decoded the way the wire hands it. */
|
|
179
|
+
/**
|
|
180
|
+
* One key a handler wrote. A key the entity does not declare has no column to land in and no
|
|
181
|
+
* judge to pass: on the client facade it is a typo, and on this one a mapping that went stale.
|
|
182
|
+
*/
|
|
183
|
+
written(key, item) {
|
|
184
|
+
const field = this.fields[key];
|
|
185
|
+
if (!field)
|
|
186
|
+
return { message: InputRefusal.unknownField };
|
|
187
|
+
if (item === undefined)
|
|
188
|
+
return { value: item };
|
|
189
|
+
return FieldValueValidator.of(field).parse(item);
|
|
190
|
+
}
|
|
162
191
|
value(field, asked) {
|
|
163
192
|
if (asked === null || asked === undefined)
|
|
164
193
|
return { value: asked };
|
|
@@ -171,22 +200,11 @@ export class StorageGuard {
|
|
|
171
200
|
const where = index === undefined ? '' : `${this.rowAt(value, index)} — `;
|
|
172
201
|
const parsed = {};
|
|
173
202
|
for (const [key, item] of Object.entries(value)) {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (!field) {
|
|
178
|
-
errors.push(`${where}${key}: ${InputRefusal.unknownField}`);
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
if (item === undefined) {
|
|
182
|
-
parsed[key] = item;
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
const value = FieldValueValidator.of(field).parse(item);
|
|
186
|
-
if ('error' in value)
|
|
187
|
-
errors.push(`${where}${key}: ${value.error}`);
|
|
203
|
+
const read = this.written(key, item);
|
|
204
|
+
if ('message' in read)
|
|
205
|
+
errors.push(`${where}${key}: ${read.message}`);
|
|
188
206
|
else
|
|
189
|
-
parsed[key] =
|
|
207
|
+
parsed[key] = read.value;
|
|
190
208
|
}
|
|
191
209
|
if (errors.length > 0) {
|
|
192
210
|
throw new FougereError({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageGuard.js","sourceRoot":"","sources":["../../src/dispatch/StorageGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"StorageGuard.js","sourceRoot":"","sources":["../../src/dispatch/StorageGuard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type SchemaView } from '@fougere/schema';
|
|
2
|
+
/**
|
|
3
|
+
* What a caller receives, read back into the shape its type promises — the dual of
|
|
4
|
+
* `OutputView.project`, applied on the other side of the call.
|
|
5
|
+
*
|
|
6
|
+
* `date-time` means a `Date` on both sides (`Boundary.forShape`), and only the outgoing half was
|
|
7
|
+
* ever applied: `Visibility.encode` turned `new Date(0)` into `"1970-01-01T00:00:00.000Z"` and
|
|
8
|
+
* nobody turned it back, so `Facade<PostHandler>` promised `createdAt: Date` and handed over a
|
|
9
|
+
* string — in this process as well as across a wire.
|
|
10
|
+
*
|
|
11
|
+
* Applied by the facade a caller HOLDS, never by the one that answers: a row leaves as data,
|
|
12
|
+
* which is what a Rust frond or a plain HTTP client reads, and the codecs are what this side
|
|
13
|
+
* knows how to put back. Measured 2026-09-18: 389 ns per row against the 1 277 ns encoding one
|
|
14
|
+
* already costs.
|
|
15
|
+
*
|
|
16
|
+
* Documented: [the gradient](https://fougere.dev/docs/infra/gradient).
|
|
17
|
+
*/
|
|
18
|
+
export declare function decoded(schema: SchemaView | undefined, answer: unknown): unknown;
|
|
19
|
+
//# sourceMappingURL=decoded.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoded.d.ts","sourceRoot":"","sources":["../../src/dispatch/decoded.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI3E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAgBhF"}
|