@aventara/core 0.1.0-pilot.3 → 1.0.0-rc.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/CHANGELOG.md +338 -0
- package/README.md +100 -3
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +2 -0
- package/dist/adapters/adapter-field.d.ts +3 -26
- package/dist/adapters/adapter-identifier.d.ts +1 -11
- package/dist/adapters/adapter-model.d.ts +12 -0
- package/dist/adapters/adapter-operation-executor.interface.d.ts +5 -1
- package/dist/adapters/adapter-resource.d.ts +7 -28
- package/dist/adapters/adapter.interface.d.ts +25 -26
- package/dist/compiler/contract-compiler-diagnostic.d.ts +8 -0
- package/dist/compiler/contract.compiler.d.ts +11 -22
- package/dist/compiler/contract.compiler.js +67 -0
- package/dist/config/any-framework-config.d.ts +5 -26
- package/dist/config/config-diagnostic.d.ts +2 -0
- package/dist/config/config-layer.d.ts +6 -19
- package/dist/config/config.resolver.d.ts +9 -14
- package/dist/config/config.resolver.js +1 -0
- package/dist/config/config.validator.d.ts +6 -3
- package/dist/config/config.validator.js +6 -0
- package/dist/config/define-fields.d.ts +15 -48
- package/dist/config/effective-fields.d.ts +6 -29
- package/dist/config/entrypoint.normalizer.d.ts +6 -18
- package/dist/config/framework-behaviors-config.d.ts +11 -10
- package/dist/config/framework-config.d.ts +19 -16
- package/dist/config/framework-fields-config.d.ts +20 -7
- package/dist/config/framework-restrictions-config.d.ts +41 -61
- package/dist/config/pipeline-config.d.ts +7 -17
- package/dist/contracts/capability.d.ts +13 -49
- package/dist/contracts/client-contract-structure.validator.d.ts +28 -54
- package/dist/contracts/client-contract-structure.validator.js +99 -2
- package/dist/contracts/contract-canonicalizer.d.ts +4 -6
- package/dist/contracts/contract-canonicalizer.js +32 -0
- package/dist/contracts/contract-hash.d.ts +3 -2
- package/dist/contracts/contract-limits.d.ts +7 -1
- package/dist/contracts/contract-protocol.d.ts +7 -8
- package/dist/contracts/contract.d.ts +20 -4
- package/dist/contracts/enum-definition.d.ts +2 -0
- package/dist/contracts/field.d.ts +40 -167
- package/dist/contracts/identifier.d.ts +1 -16
- package/dist/contracts/json-shape.d.ts +65 -0
- package/dist/contracts/json-shape.js +1 -0
- package/dist/contracts/lifecycle-trait.d.ts +4 -3
- package/dist/contracts/reference-write-limit.d.ts +7 -0
- package/dist/contracts/reference-write-limit.js +1 -0
- package/dist/contracts/resource-operations.d.ts +2 -62
- package/dist/contracts/resource.d.ts +2 -0
- package/dist/contracts/scalar-value-type.d.ts +28 -48
- package/dist/contracts/scalar.d.ts +4 -3
- package/dist/contracts/transaction-capability.d.ts +2 -0
- package/dist/contracts/wire-scalar-format.d.ts +6 -21
- package/dist/framework/contract-view.d.ts +152 -130
- package/dist/framework/framework-construction.error.d.ts +6 -1
- package/dist/framework/framework.d.ts +33 -46
- package/dist/framework/framework.factory.d.ts +3 -17
- package/dist/framework/framework.factory.js +56 -13
- package/dist/framework/operation-facade.d.ts +3 -7
- package/dist/index.d.ts +8 -40
- package/dist/index.js +0 -20
- package/dist/internal.d.ts +35 -0
- package/dist/internal.js +16 -0
- package/dist/json/avz.d.ts +96 -0
- package/dist/json/avz.js +212 -0
- package/dist/json/index.d.ts +6 -0
- package/dist/json/index.js +1 -0
- package/dist/json/json-shape.registry.d.ts +22 -0
- package/dist/json/json-shape.registry.js +16 -0
- package/dist/json/zod-issue.translator.d.ts +51 -0
- package/dist/json/zod-issue.translator.js +142 -0
- package/dist/operations/operation-arguments.d.ts +198 -303
- package/dist/operations/operation-call.d.ts +13 -15
- package/dist/operations/operation-identity.d.ts +6 -2
- package/dist/operations/operation-identity.js +3 -0
- package/dist/operations/operation-result.d.ts +15 -61
- package/dist/operations/operation-validator-core.d.ts +6 -5
- package/dist/operations/operation-validator-core.js +28 -10
- package/dist/operations/operation-validator.d.ts +22 -9
- package/dist/operations/operation-validator.js +26 -10
- package/dist/operations/projection-scope.resolver.d.ts +1 -11
- package/dist/operations/structural-limits.walker.d.ts +19 -0
- package/dist/operations/structural-limits.walker.js +344 -0
- package/dist/operations/validation-code.d.ts +5 -17
- package/dist/operations/write-scope.resolver.d.ts +3 -28
- package/dist/protocol/absent-route.responder.d.ts +25 -39
- package/dist/protocol/absent-route.responder.js +32 -6
- package/dist/protocol/av-protocol.d.ts +2 -8
- package/dist/protocol/contract-document.responder.d.ts +5 -18
- package/dist/protocol/http-request.decoder.d.ts +18 -59
- package/dist/protocol/http-request.decoder.js +11 -3
- package/dist/protocol/http-request.reader.d.ts +5 -5
- package/dist/protocol/http-response.encoder.d.ts +14 -20
- package/dist/protocol/http-status.table.d.ts +0 -8
- package/dist/protocol/index.d.ts +2 -7
- package/dist/protocol/operation-response.guard.d.ts +0 -15
- package/dist/protocol/protocol-failure.d.ts +8 -27
- package/dist/protocol/protocol-headers.d.ts +15 -42
- package/dist/protocol/protocol-surface.d.ts +0 -22
- package/dist/protocol/protocol.binder.d.ts +19 -27
- package/dist/protocol/protocol.binder.js +3 -1
- package/dist/protocol/protocol.handler.d.ts +19 -23
- package/dist/protocol/protocol.handler.js +14 -4
- package/dist/protocol/unmounted-route.error.d.ts +19 -0
- package/dist/protocol/unmounted-route.error.js +10 -0
- package/dist/runtime/caller-data.copier.d.ts +59 -0
- package/dist/runtime/caller-data.copier.js +470 -0
- package/dist/runtime/caller-data.door.d.ts +56 -0
- package/dist/runtime/caller-data.door.js +65 -0
- package/dist/runtime/computed-read-runtime.js +3 -10
- package/dist/runtime/computed-value.error.d.ts +13 -0
- package/dist/runtime/computed-value.error.js +9 -0
- package/dist/runtime/create-requirement.d.ts +43 -7
- package/dist/runtime/create-requirement.js +89 -9
- package/dist/runtime/decimal.d.ts +5 -3
- package/dist/runtime/diagnostics-reporter.d.ts +33 -37
- package/dist/runtime/diagnostics-reporter.js +11 -4
- package/dist/runtime/error-boundary.d.ts +14 -10
- package/dist/runtime/error-boundary.js +65 -35
- package/dist/runtime/execution-options.d.ts +3 -7
- package/dist/runtime/field-behavior.d.ts +14 -21
- package/dist/runtime/framework-error.d.ts +14 -2
- package/dist/runtime/json-value.d.ts +7 -15
- package/dist/runtime/misuse-reporter.d.ts +32 -0
- package/dist/runtime/misuse-reporter.js +19 -0
- package/dist/runtime/mutation-planner.d.ts +6 -12
- package/dist/runtime/mutation-planner.js +13 -11
- package/dist/runtime/operation-request.d.ts +11 -11
- package/dist/runtime/operation-response.d.ts +18 -23
- package/dist/runtime/operation-runtime.d.ts +25 -33
- package/dist/runtime/operation-runtime.js +37 -18
- package/dist/runtime/outcome-mapper.js +12 -2
- package/dist/runtime/output-validator.d.ts +10 -0
- package/dist/runtime/output-validator.js +11 -0
- package/dist/runtime/owned-execution.registry.d.ts +13 -0
- package/dist/runtime/owned-execution.registry.js +7 -0
- package/dist/runtime/pipeline.d.ts +33 -36
- package/dist/runtime/referential-action.d.ts +8 -26
- package/dist/runtime/request-envelope.validator.d.ts +5 -0
- package/dist/runtime/request-envelope.validator.js +118 -0
- package/dist/runtime/request-id.d.ts +3 -10
- package/dist/runtime/scalar-runtime.d.ts +42 -14
- package/dist/runtime/scalar-runtime.js +162 -79
- package/dist/transactions/deferred-operation.d.ts +10 -21
- package/dist/transactions/operation-arguments-encoder.d.ts +1 -0
- package/dist/transactions/operation-fingerprint.d.ts +3 -1
- package/dist/transactions/transaction-envelope.d.ts +2 -4
- package/dist/transactions/transaction-integrity-error.d.ts +4 -15
- package/dist/transactions/transaction-plan-assembler.d.ts +6 -1
- package/dist/transactions/transaction-plan-assembler.js +74 -75
- package/dist/transactions/transaction-plan-validator.d.ts +33 -24
- package/dist/transactions/transaction-plan-validator.js +204 -153
- package/dist/transactions/transaction-reference-collector.d.ts +30 -0
- package/dist/transactions/transaction-reference-collector.js +204 -0
- package/dist/transactions/transaction-reference-resolver.d.ts +9 -12
- package/dist/transactions/transaction-reference-resolver.js +10 -5
- package/dist/transactions/transaction-reference-validator.js +24 -17
- package/dist/transactions/transaction-reference.d.ts +31 -64
- package/dist/transactions/transaction-request.d.ts +6 -8
- package/dist/transactions/transaction-response.d.ts +10 -7
- package/dist/transactions/transaction-response.js +24 -1
- package/dist/transactions/transaction-runtime.d.ts +7 -5
- package/dist/transactions/transaction-runtime.js +4 -3
- package/dist/transactions/transaction-slot-path-error.d.ts +5 -15
- package/dist/transactions/transaction-slot-writer.d.ts +3 -13
- package/package.json +17 -3
- package/dist/operations/operation-boolean-nodes.d.ts +0 -11
- package/dist/operations/operation-boolean-nodes.js +0 -283
- package/dist/operations/operation-nesting.d.ts +0 -8
- package/dist/operations/operation-nesting.js +0 -307
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The framework entrypoint's mount path, in its one canonical form: `""` at the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The framework entrypoint's mount path, in its one canonical form: `""` at the root,
|
|
3
|
+
* otherwise `/seg(/seg)*` — one leading slash, no trailing slash, no empty segment.
|
|
4
|
+
* Root is the empty string, not `"/"`, so a route joins onto it by concatenation with
|
|
5
|
+
* no special case.
|
|
6
6
|
*/
|
|
7
7
|
export type EntrypointPath = "" | `/${string}`;
|
|
8
8
|
/**
|
|
@@ -26,19 +26,7 @@ export type EntrypointNormalization = {
|
|
|
26
26
|
readonly message: string;
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
|
-
* `AvProtocol.normalizeEntrypoint` — a mount path, as written, to its canonical
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* The one source of the rule: config resolution stores the canonical form as
|
|
33
|
-
* `framework.entrypoint`, config validation turns a refusal into a `CONFIG_`
|
|
34
|
-
* diagnostic, and the client generator's `resolveEntrypoint` hands it the mount
|
|
35
|
-
* path of the URL it is given — as written, before a URL parser has trimmed,
|
|
36
|
-
* resolved or percent-encoded anything. Execution code reads it from here;
|
|
37
|
-
* `@aventara/core/protocol` re-exports it, and the main entry does not.
|
|
38
|
-
*
|
|
39
|
-
* Checked in order, so each value has one reason: whitespace, a scheme (`://`), a
|
|
40
|
-
* query, a fragment, a `..` or `.` segment (either separator, `%2e` spelling
|
|
41
|
-
* included), a backslash, a non-ASCII character, a `%`, and finally any other
|
|
42
|
-
* character outside RFC 3986's `pchar`.
|
|
29
|
+
* `AvProtocol.normalizeEntrypoint` — a mount path, as written, to its canonical form
|
|
30
|
+
* or a refusal.
|
|
43
31
|
*/
|
|
44
32
|
export declare function normalizeEntrypoint(value: string): EntrypointNormalization;
|
|
@@ -3,27 +3,28 @@ import type { ComputedReadBehavior, ComputeOnCreate, ComputeOnUpdate } from "../
|
|
|
3
3
|
import type { AnyFrameworkConfig } from "./any-framework-config.js";
|
|
4
4
|
import type { EffectiveFieldKey } from "./effective-fields.js";
|
|
5
5
|
import type { FrameworkResourceKey } from "./framework-fields-config.js";
|
|
6
|
+
/** A read behavior: a compute function, or one declaring the fields it reads. */
|
|
6
7
|
export type FrameworkReadBehavior<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig, R extends FrameworkResourceKey<M> = FrameworkResourceKey<M>> = ComputedReadBehavior<M, Cfg, R>;
|
|
8
|
+
/**
|
|
9
|
+
* A field's behaviors: a value computed on create, on update, or on read.
|
|
10
|
+
* `false` turns off a behavior set at an outer layer.
|
|
11
|
+
*/
|
|
7
12
|
export type FrameworkFieldBehaviorConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig, R extends FrameworkResourceKey<M> = FrameworkResourceKey<M>> = {
|
|
13
|
+
/** Computes the field's value when a row is created. */
|
|
8
14
|
readonly create?: false | ComputeOnCreate<M, Cfg, R>;
|
|
15
|
+
/** Computes the field's value when a row is updated. */
|
|
9
16
|
readonly update?: false | ComputeOnUpdate<M, Cfg, R>;
|
|
17
|
+
/** Computes the field's value when a row is read. */
|
|
10
18
|
readonly read?: false | FrameworkReadBehavior<M, Cfg, R>;
|
|
11
19
|
};
|
|
12
|
-
/**
|
|
13
|
-
* Executable behavior bindings for one Resource, keyed on the single effective
|
|
14
|
-
* field-key answer.
|
|
15
|
-
*
|
|
16
|
-
* `Partial` is required, not cosmetic: a mapped type over a literal key set would
|
|
17
|
-
* otherwise demand a binding for every field of the Resource. Under the default
|
|
18
|
-
* `Cfg` the key set is `string`, the mapped half collapses to one index signature
|
|
19
|
-
* and today's wide acceptance is preserved.
|
|
20
|
-
*/
|
|
20
|
+
/** Behaviors for one Resource's fields. */
|
|
21
21
|
export type FrameworkResourceBehaviorsConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig, R extends FrameworkResourceKey<M> = FrameworkResourceKey<M>> = {
|
|
22
|
+
/** Behaviors per field name. */
|
|
22
23
|
readonly fields: Readonly<Partial<{
|
|
23
24
|
[F in EffectiveFieldKey<M, Cfg, R>]: FrameworkFieldBehaviorConfig<M, Cfg, R>;
|
|
24
25
|
}>>;
|
|
25
26
|
};
|
|
26
|
-
/**
|
|
27
|
+
/** Server-side behaviors, per Resource. */
|
|
27
28
|
export type FrameworkBehaviorsConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig> = Readonly<Partial<{
|
|
28
29
|
[R in FrameworkResourceKey<M>]: FrameworkResourceBehaviorsConfig<M, Cfg, R>;
|
|
29
30
|
}>>;
|
|
@@ -3,43 +3,46 @@ import type { AdapterModel } from "../adapters/adapter-model.js";
|
|
|
3
3
|
import type { ContractLimits } from "../contracts/contract-limits.js";
|
|
4
4
|
import type { TransactionCapability } from "../contracts/transaction-capability.js";
|
|
5
5
|
import type { FrameworkDiagnosticsSink } from "../runtime/diagnostics-reporter.js";
|
|
6
|
+
import type { FrameworkMisuseSink } from "../runtime/misuse-reporter.js";
|
|
6
7
|
import type { AnyFrameworkConfig } from "./any-framework-config.js";
|
|
7
8
|
import type { FrameworkBehaviorsConfig } from "./framework-behaviors-config.js";
|
|
8
9
|
import type { FrameworkFieldsConfig } from "./framework-fields-config.js";
|
|
9
10
|
import type { FrameworkRestrictionsConfig } from "./framework-restrictions-config.js";
|
|
10
11
|
import type { PipelineConfig } from "./pipeline-config.js";
|
|
11
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Request limits to override; each one left out takes its default from
|
|
14
|
+
* {@link DEFAULT_CONTRACT_LIMITS}.
|
|
15
|
+
*/
|
|
12
16
|
export type FrameworkLimitsConfig = Partial<ContractLimits>;
|
|
13
17
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* default `AnyFrameworkConfig` the effective key set degenerates to `string`, so
|
|
18
|
-
* an unannotated `FrameworkScopeConfig<M>` behaves exactly as it did before.
|
|
18
|
+
* Settings available at the root and in the `application` and `client`
|
|
19
|
+
* overlays. A setting in an overlay replaces the root's for that origin;
|
|
20
|
+
* pipelines are added to the root's instead.
|
|
19
21
|
*/
|
|
20
22
|
export type FrameworkScopeConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig> = {
|
|
23
|
+
/** Fields to add to Resources, or details to set on discovered fields. */
|
|
21
24
|
readonly fields?: FrameworkFieldsConfig<M>;
|
|
25
|
+
/** Computed values and read behaviors, per Resource and field. */
|
|
22
26
|
readonly behaviors?: FrameworkBehaviorsConfig<M, Cfg>;
|
|
27
|
+
/** What to hide or narrow: Resources, fields, capabilities and operations. */
|
|
23
28
|
readonly restrictions?: FrameworkRestrictionsConfig<M, Cfg>;
|
|
29
|
+
/** Request limits; see {@link FrameworkLimitsConfig}. */
|
|
24
30
|
readonly limits?: FrameworkLimitsConfig;
|
|
25
|
-
|
|
31
|
+
/** Guards, pipes, hooks, interceptors and filters run around each operation. */
|
|
32
|
+
readonly pipelines?: PipelineConfig<NoInfer<M>>;
|
|
33
|
+
/** `"none"` turns transactions off; `"interactive"` needs adapter support. */
|
|
26
34
|
readonly transactions?: TransactionCapability;
|
|
27
35
|
};
|
|
28
36
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* Root properties are the root/core/default source. There is intentionally no
|
|
32
|
-
* `core` namespace; `application` and `client` are scoped overlays.
|
|
33
|
-
*
|
|
34
|
-
* `diagnostics` is deliberately root-only and absent from
|
|
35
|
-
* {@link FrameworkScopeConfig}: the framework owns the channel that reports
|
|
36
|
-
* the developer's own unplanned failures, so it is neither scoped, ordered,
|
|
37
|
-
* composable nor overridable.
|
|
37
|
+
* The configuration passed to `createFramework`: the adapter, the mount path,
|
|
38
|
+
* root settings, and optional `application` and `client` overlays.
|
|
38
39
|
*/
|
|
39
40
|
export type FrameworkConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig> = FrameworkScopeConfig<M, Cfg> & {
|
|
40
41
|
readonly entrypoint: string;
|
|
41
42
|
readonly adapter: Adapter<M>;
|
|
42
43
|
readonly diagnostics?: FrameworkDiagnosticsSink;
|
|
44
|
+
/** Told about every caller value refused as unreadable or not plain data. */
|
|
45
|
+
readonly misuse?: FrameworkMisuseSink;
|
|
43
46
|
readonly application?: FrameworkScopeConfig<M, Cfg>;
|
|
44
47
|
readonly client?: FrameworkScopeConfig<M, Cfg>;
|
|
45
48
|
};
|
|
@@ -1,29 +1,42 @@
|
|
|
1
1
|
import type { AdapterModel } from "../adapters/adapter-model.js";
|
|
2
2
|
import type { ScalarFieldCapabilities, ScalarFormat } from "../contracts/field.js";
|
|
3
|
+
import type { JsonShape } from "../contracts/json-shape.js";
|
|
3
4
|
import type { LifecycleTrait } from "../contracts/lifecycle-trait.js";
|
|
5
|
+
/** The lifecycle traits a configuration may set on a field. */
|
|
4
6
|
export type FrameworkFieldLifecycleTrait = Extract<LifecycleTrait, "VIRTUAL">;
|
|
7
|
+
/** The names of the Resources in adapter model `M`. */
|
|
5
8
|
export type FrameworkResourceKey<M extends AdapterModel> = Extract<keyof M["resources"], string>;
|
|
9
|
+
/** A scalar type or an enum of adapter model `M`, by name. */
|
|
6
10
|
export type FrameworkScalarTypeRef<M extends AdapterModel> = {
|
|
7
11
|
readonly scalar: Extract<keyof M["scalars"], string>;
|
|
8
12
|
} | {
|
|
9
13
|
readonly enum: Extract<keyof M["enums"], string>;
|
|
10
14
|
};
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* absent from the adapter model represents a framework-added scalar field and
|
|
16
|
-
* must provide the structural leaves required by compilation.
|
|
16
|
+
* A scalar field's settings. For a discovered field, the discovered values are
|
|
17
|
+
* the baseline; a field the adapter did not discover must state `type`,
|
|
18
|
+
* `nullable` and `list`.
|
|
17
19
|
*/
|
|
18
20
|
export type FrameworkScalarFieldConfig<M extends AdapterModel = AdapterModel> = {
|
|
21
|
+
/** The field's scalar or enum type. */
|
|
19
22
|
readonly type?: FrameworkScalarTypeRef<M>;
|
|
23
|
+
/** The scalar's format name, carried in the Contract. */
|
|
20
24
|
readonly format?: ScalarFormat;
|
|
25
|
+
/** Whether the field may be `null`. */
|
|
21
26
|
readonly nullable?: boolean;
|
|
27
|
+
/** Whether the field holds a list of values. */
|
|
22
28
|
readonly list?: boolean;
|
|
23
|
-
/**
|
|
29
|
+
/** Persistence traits: `"VIRTUAL"` marks a field the store does not hold. */
|
|
24
30
|
readonly lifecycle?: readonly FrameworkFieldLifecycleTrait[];
|
|
31
|
+
/** The field's capabilities; see {@link ScalarFieldCapabilities}. */
|
|
25
32
|
readonly capabilities?: Partial<ScalarFieldCapabilities>;
|
|
33
|
+
/**
|
|
34
|
+
* A Json field's shape, built with `AvZ` from `@aventara/core/json`: writes
|
|
35
|
+
* to the field are checked against it, and its value is typed by it.
|
|
36
|
+
*/
|
|
37
|
+
readonly json?: JsonShape;
|
|
26
38
|
};
|
|
39
|
+
/** Field settings for one Resource, by field name. */
|
|
27
40
|
export type FrameworkResourceFieldsConfig<M extends AdapterModel = AdapterModel> = Readonly<Record<string, FrameworkScalarFieldConfig<M>>>;
|
|
28
|
-
/**
|
|
41
|
+
/** Fields to add or describe, per Resource. */
|
|
29
42
|
export type FrameworkFieldsConfig<M extends AdapterModel = AdapterModel> = Readonly<Partial<Record<FrameworkResourceKey<M>, FrameworkResourceFieldsConfig<M>>>>;
|
|
@@ -4,69 +4,54 @@ import type { PaginationCapability, ProjectionScope, RelationFilterCapability, R
|
|
|
4
4
|
import type { AnyFrameworkConfig } from "./any-framework-config.js";
|
|
5
5
|
import type { EffectiveFieldKey } from "./effective-fields.js";
|
|
6
6
|
import type { FrameworkResourceKey } from "./framework-fields-config.js";
|
|
7
|
+
/**
|
|
8
|
+
* `true` keeps a capability, `false` removes it, and a list keeps only the
|
|
9
|
+
* listed entries. Restrictions only narrow what the adapter offers.
|
|
10
|
+
*/
|
|
7
11
|
export type FrameworkCapabilitySetRestriction<T extends string> = boolean | readonly T[];
|
|
8
12
|
/**
|
|
9
|
-
* A restriction on a
|
|
10
|
-
*
|
|
11
|
-
* all.
|
|
12
|
-
*
|
|
13
|
-
* Three operations, and they are three because narrowing a qualified capability is
|
|
14
|
-
* not one thing:
|
|
15
|
-
*
|
|
16
|
-
* - `false` **denies** the capability — the member leaves the projection.
|
|
17
|
-
* - a scope list **removes positions** — the member survives, reachable in fewer
|
|
18
|
-
* argument positions.
|
|
19
|
-
* - `true` **restores** the baseline member, qualifier included.
|
|
20
|
-
*
|
|
21
|
-
* The **empty** list is the fourth operation written as a degenerate third: a
|
|
22
|
-
* capability narrowed to no position is a capability that is not available, and
|
|
23
|
-
* `ProjectionScopes` cannot represent an empty list, so the compiler denies the
|
|
24
|
-
* member rather than emitting a second encoding of "absent".
|
|
13
|
+
* A restriction on a relation's `select` or `include` capability: `true`,
|
|
14
|
+
* `false`, or the projection positions to keep.
|
|
25
15
|
*/
|
|
26
16
|
export type FrameworkProjectionScopeRestriction = boolean | readonly ProjectionScope[];
|
|
27
17
|
/**
|
|
28
|
-
* A restriction on a
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* Removing a directive and removing a write position are **different narrowings**,
|
|
32
|
-
* so each is authorable without restating the other. The bare directive list keeps
|
|
33
|
-
* the grammar it has always had and narrows tokens only, leaving the positions the
|
|
34
|
-
* baseline advertises in place; the object arm names either axis, or both.
|
|
18
|
+
* A restriction on a relation's `create` or `update` capability. A directive
|
|
19
|
+
* list narrows the directives only; the object form can also narrow the write
|
|
20
|
+
* positions (`scopes`).
|
|
35
21
|
*
|
|
36
|
-
* `directives: []`
|
|
37
|
-
*
|
|
38
|
-
* directive list narrows the tokens to none and leaves the member present —
|
|
39
|
-
* `scopes: []` is what denies it, for the reason
|
|
40
|
-
* {@link FrameworkProjectionScopeRestriction} gives.
|
|
22
|
+
* `directives: []` leaves the relation writable with no directive;
|
|
23
|
+
* `scopes: []` or `false` makes it not writable.
|
|
41
24
|
*/
|
|
42
25
|
export type FrameworkRelationMutationRestriction = boolean | readonly RelationMutationDirective[] | {
|
|
43
26
|
readonly directives?: readonly RelationMutationDirective[];
|
|
44
27
|
readonly scopes?: readonly WriteScope[];
|
|
45
28
|
};
|
|
46
29
|
/**
|
|
47
|
-
* A restriction on a relation's
|
|
48
|
-
*
|
|
49
|
-
* Contract arm uses, so the restriction is written in the vocabulary of the value
|
|
50
|
-
* it narrows rather than a second one.
|
|
30
|
+
* A restriction on a relation's `reducers` capability: `true`, `false`, a
|
|
31
|
+
* reducer list, or an object narrowing reducers and projection positions.
|
|
51
32
|
*/
|
|
52
33
|
export type FrameworkRelationReducerRestriction = boolean | readonly RelationReducer[] | {
|
|
53
34
|
readonly reducers?: readonly RelationReducer[];
|
|
54
35
|
readonly scopes?: readonly ProjectionScope[];
|
|
55
36
|
};
|
|
37
|
+
/** Restrictions on a scalar field's capabilities. */
|
|
56
38
|
export type FrameworkScalarCapabilityRestrictions = {
|
|
39
|
+
/** Whether the field can be selected. */
|
|
57
40
|
readonly select?: boolean;
|
|
41
|
+
/** The filter operators to keep. */
|
|
58
42
|
readonly filter?: FrameworkCapabilitySetRestriction<ScalarFilterOperator>;
|
|
43
|
+
/** Whether results can be ordered by the field. */
|
|
59
44
|
readonly order?: boolean;
|
|
45
|
+
/** Whether ordering can place `null`s first or last. */
|
|
60
46
|
readonly orderNulls?: boolean;
|
|
47
|
+
/** The directives to keep when creating. */
|
|
61
48
|
readonly create?: FrameworkCapabilitySetRestriction<ScalarMutationDirective>;
|
|
49
|
+
/** The directives to keep when updating. */
|
|
62
50
|
readonly update?: FrameworkCapabilitySetRestriction<ScalarMutationDirective>;
|
|
63
51
|
};
|
|
64
52
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* measured uniform across every operation variant, so there is no position to name
|
|
68
|
-
* and a grammar that let one be named would invent a narrowing the adapter cannot
|
|
69
|
-
* honour.
|
|
53
|
+
* Restrictions on a relation field's capabilities. `select`, `include`,
|
|
54
|
+
* `reducers`, `create` and `update` can also be narrowed by argument position.
|
|
70
55
|
*/
|
|
71
56
|
export type FrameworkRelationCapabilityRestrictions = {
|
|
72
57
|
readonly select?: FrameworkProjectionScopeRestriction;
|
|
@@ -78,15 +63,26 @@ export type FrameworkRelationCapabilityRestrictions = {
|
|
|
78
63
|
readonly create?: FrameworkRelationMutationRestriction;
|
|
79
64
|
readonly update?: FrameworkRelationMutationRestriction;
|
|
80
65
|
};
|
|
66
|
+
/** Restrictions for one scalar field. */
|
|
81
67
|
export type FrameworkScalarFieldRestrictions = {
|
|
68
|
+
/** `true` hides the field. */
|
|
82
69
|
readonly hidden?: boolean;
|
|
70
|
+
/** Capabilities to narrow. */
|
|
83
71
|
readonly capabilities?: FrameworkScalarCapabilityRestrictions;
|
|
84
72
|
};
|
|
73
|
+
/** Restrictions for one relation field. */
|
|
85
74
|
export type FrameworkRelationFieldRestrictions = {
|
|
75
|
+
/** `true` hides the field. */
|
|
86
76
|
readonly hidden?: boolean;
|
|
77
|
+
/** Capabilities to narrow. */
|
|
87
78
|
readonly capabilities?: FrameworkRelationCapabilityRestrictions;
|
|
88
79
|
};
|
|
80
|
+
/** Restrictions for one field: scalar or relation. */
|
|
89
81
|
export type FrameworkFieldRestrictions = FrameworkScalarFieldRestrictions | FrameworkRelationFieldRestrictions;
|
|
82
|
+
/**
|
|
83
|
+
* Standard operations to turn off, by family and variant: `false` removes
|
|
84
|
+
* one the adapter offers.
|
|
85
|
+
*/
|
|
90
86
|
export type FrameworkResourceOperationRestrictions = {
|
|
91
87
|
readonly find?: {
|
|
92
88
|
readonly first?: boolean;
|
|
@@ -122,40 +118,24 @@ type AdapterFieldRestrictionsFor<TField> = TField extends {
|
|
|
122
118
|
readonly kind: "relation";
|
|
123
119
|
} ? FrameworkRelationFieldRestrictions : FrameworkFieldRestrictions;
|
|
124
120
|
/**
|
|
125
|
-
* The restriction shape one effective field name admits. Three cases, in
|
|
126
|
-
*
|
|
127
|
-
* `string extends F` is the wide default. Under `AnyFrameworkConfig`, {@link
|
|
128
|
-
* EffectiveFieldKey} degenerates to `string`, the mapped type below collapses to a
|
|
129
|
-
* single index signature and no field identity survives to discriminate on.
|
|
130
|
-
* Today's wide acceptance is preserved there deliberately: narrowing below the
|
|
131
|
-
* resource key is opt-in, never imposed.
|
|
132
|
-
*
|
|
133
|
-
* An adapter-discovered name is discriminated by the model's own `kind`.
|
|
134
|
-
*
|
|
135
|
-
* Anything else is a name the configuration's own `fields` block added. Per the
|
|
136
|
-
* target type graph an added field is an added *scalar* field — there is no
|
|
137
|
-
* configuration surface that authors a relation — so the answer is {@link
|
|
138
|
-
* FrameworkScalarFieldRestrictions}.
|
|
121
|
+
* The restriction shape one effective field name admits. Three cases, in
|
|
122
|
+
* order.
|
|
139
123
|
*/
|
|
140
124
|
type FieldRestrictionsFor<M extends AdapterModel, R extends FrameworkResourceKey<M>, F extends string> = string extends F ? FrameworkFieldRestrictions : F extends AdapterFieldKey<M, R> ? AdapterFieldRestrictionsFor<M["resources"][R]["fields"][F]> : FrameworkScalarFieldRestrictions;
|
|
141
|
-
/**
|
|
142
|
-
* Projection policy for one Resource's fields, keyed on the single effective
|
|
143
|
-
* field-key answer.
|
|
144
|
-
*
|
|
145
|
-
* This type used to intersect the mapped half with `Readonly<Record<string,
|
|
146
|
-
* FrameworkFieldRestrictions>>`, whose index signature absorbed every field name
|
|
147
|
-
* the model does not declare. The catch-all is gone: a name must be an adapter
|
|
148
|
-
* field or one `Cfg` adds.
|
|
149
|
-
*/
|
|
125
|
+
/** Restrictions for one Resource's fields, by field name. */
|
|
150
126
|
export type FrameworkResourceFieldRestrictions<M extends AdapterModel, Cfg, R extends FrameworkResourceKey<M>> = Readonly<Partial<{
|
|
151
127
|
[F in EffectiveFieldKey<M, Cfg, R>]: FieldRestrictionsFor<M, R, F>;
|
|
152
128
|
}>>;
|
|
129
|
+
/** Restrictions for one Resource. */
|
|
153
130
|
export type FrameworkResourceRestrictions<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig, R extends FrameworkResourceKey<M> = FrameworkResourceKey<M>> = {
|
|
131
|
+
/** `true` hides the whole Resource. */
|
|
154
132
|
readonly hidden?: boolean;
|
|
133
|
+
/** Restrictions per field. */
|
|
155
134
|
readonly fields?: FrameworkResourceFieldRestrictions<M, Cfg, R>;
|
|
135
|
+
/** Standard operations to turn off. */
|
|
156
136
|
readonly operations?: FrameworkResourceOperationRestrictions;
|
|
157
137
|
};
|
|
158
|
-
/**
|
|
138
|
+
/** What to hide or narrow, per Resource. */
|
|
159
139
|
export type FrameworkRestrictionsConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig> = Readonly<Partial<{
|
|
160
140
|
[R in FrameworkResourceKey<M>]: FrameworkResourceRestrictions<M, Cfg, R>;
|
|
161
141
|
}>>;
|
|
@@ -1,32 +1,22 @@
|
|
|
1
1
|
import type { AdapterModel } from "../adapters/adapter-model.js";
|
|
2
2
|
import type { AfterHook, BeforeHook, Filter, Guard, Interceptor, Pipe } from "../runtime/pipeline.js";
|
|
3
|
-
/**
|
|
4
|
-
* Pipeline registrations for one configuration scope.
|
|
5
|
-
*
|
|
6
|
-
* See {@link PipelineContext}.
|
|
7
|
-
*/
|
|
3
|
+
/** Pipeline registrations for one configuration scope. See {@link PipelineContext}. */
|
|
8
4
|
export type PipelineConfig<M extends AdapterModel = AdapterModel> = {
|
|
5
|
+
/** Run first; a guard returning `false` denies the operation with `A4001`. */
|
|
9
6
|
readonly guards?: readonly Guard<M>[];
|
|
7
|
+
/** Run in order on the arguments; a pipe may return replacement arguments. */
|
|
10
8
|
readonly pipes?: readonly Pipe<M>[];
|
|
9
|
+
/** Run just before (`before`) and after (`after`) the operation executes. */
|
|
11
10
|
readonly hooks?: {
|
|
12
11
|
readonly before?: readonly BeforeHook<M>[];
|
|
13
12
|
readonly after?: readonly AfterHook<M>[];
|
|
14
13
|
};
|
|
14
|
+
/** Wrap the operation's execution; each calls `next()` to continue. */
|
|
15
15
|
readonly interceptors?: readonly Interceptor<M>[];
|
|
16
|
+
/** Turn a thrown error into a {@link FrameworkError} outcome. */
|
|
16
17
|
readonly filters?: readonly Filter<M>[];
|
|
17
18
|
};
|
|
18
|
-
/**
|
|
19
|
-
* Fully normalized pipeline registration lists after scope composition.
|
|
20
|
-
*
|
|
21
|
-
* Parameterizing this type would let `M` flow past `resolveFrameworkConfig` into a
|
|
22
|
-
* runtime that cannot honour it, and would force a cast at the context factory to
|
|
23
|
-
* manufacture a literal the request does not carry.
|
|
24
|
-
*
|
|
25
|
-
* Unlike `behaviors`, erasing here costs nothing at the type level: `M` occurs in
|
|
26
|
-
* these callbacks *only* in parameter position, never as a mapped-type key, so
|
|
27
|
-
* `PipelineConfig<M>` is accepted where the erased form is required and
|
|
28
|
-
* `resolvePipelines` composes the authored lists with no cast at all.
|
|
29
|
-
*/
|
|
19
|
+
/** The pipelines that run for one origin, root and overlay combined. */
|
|
30
20
|
export type ResolvedPipelineConfig = {
|
|
31
21
|
readonly guards: readonly Guard[];
|
|
32
22
|
readonly pipes: readonly Pipe[];
|
|
@@ -1,64 +1,28 @@
|
|
|
1
|
+
/** The operators a scalar field can be filtered with. */
|
|
1
2
|
export type ScalarFilterOperator = "equals" | "not" | "in" | "notIn" | "lt" | "lte" | "gt" | "gte" | "contains" | "startsWith" | "endsWith" | "mode" | "has" | "hasEvery" | "hasSome" | "isEmpty" | "path" | "stringContains" | "stringStartsWith" | "stringEndsWith" | "arrayContains" | "arrayStartsWith" | "arrayEndsWith";
|
|
3
|
+
/** What an update can do to a scalar value besides setting it. */
|
|
2
4
|
export type ScalarMutationDirective = "$increment" | "$decrement" | "$multiply" | "$divide" | "$push" | "$unset";
|
|
5
|
+
/** How a relation can be filtered on. */
|
|
3
6
|
export type RelationFilterCapability = "nested" | "match" | "null" | "some" | "every" | "none";
|
|
7
|
+
/** What a write can do to a relation: `$create`, `$connect` and the rest. */
|
|
4
8
|
export type RelationMutationDirective = "$create" | "$connect" | "$connectOrCreate" | "$disconnect" | "$set" | "$update" | "$delete" | "$upsert";
|
|
9
|
+
/** How a list of related rows can be paginated. */
|
|
5
10
|
export type PaginationCapability = "limit" | "offset" | "cursor";
|
|
11
|
+
/** What a projection can compute over a to-many relation. */
|
|
6
12
|
export type RelationReducer = "$count";
|
|
7
13
|
/**
|
|
8
|
-
* Where a projected field may be asked for: the kind of argument POSITION a
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* both pilot engines answer — a third position would have to be measured, not
|
|
13
|
-
* supposed.
|
|
14
|
-
*
|
|
15
|
-
* **A scope qualifies the TOP LEVEL of a projection only. It does not narrow
|
|
16
|
-
* recursively.** Measured at runtime on both pilot engines, 2026-10-03, not
|
|
17
|
-
* inferred from types: a bulk-returning write accepted `include: { <owned to-one>:
|
|
18
|
-
* { include: { <to-many>: true } } }` and populated the rows (the nested to-many
|
|
19
|
-
* returned its 3 rows and a full reducer object), while the SAME to-many asked for
|
|
20
|
-
* at depth 1 was refused outright. The reason is visible in the generated types: a
|
|
21
|
-
* bulk projection types an admitted relation as the *unrestricted* projection
|
|
22
|
-
* argument, so the full surface returns one level in.
|
|
23
|
-
*
|
|
24
|
-
* A reader who assumes a scope narrows recursively will write a rule that refuses
|
|
25
|
-
* what the ORM accepts.
|
|
26
|
-
*
|
|
27
|
-
* # Why the axis is a value and the union is derived from it
|
|
28
|
-
*
|
|
29
|
-
* The axis is written down exactly once, as `LIFECYCLE_TRAITS` and
|
|
30
|
-
* `TRANSACTION_CAPABILITIES` are, because one reader needs its **cardinality** at
|
|
31
|
-
* runtime and not merely its member names: a scope list naming every member of the
|
|
32
|
-
* axis says exactly what the unqualified arm says, so the canonicalizer collapses
|
|
33
|
-
* it. That reader asks "does this list name every member of the axis?" against
|
|
34
|
-
* this array. A hardcoded two would answer *yes* for a two-of-three list the day a
|
|
35
|
-
* third position is measured, which widens every Contract carrying it and nothing
|
|
36
|
-
* downstream can tell — so the derivation is load-bearing, not tidiness.
|
|
37
|
-
*
|
|
38
|
-
* Declaration order is registry order and the canonicalizer orders scope lists by
|
|
39
|
-
* it, the way it orders `pagination`.
|
|
14
|
+
* Where a projected field may be asked for: the kind of argument POSITION a projection
|
|
15
|
+
* sits in, not the operation that carries it. A variant states the position its
|
|
16
|
+
* projection arguments sit in (`OperationScopes`); a field states the positions it is
|
|
17
|
+
* projectable in.
|
|
40
18
|
*/
|
|
41
19
|
export declare const PROJECTION_SCOPES: readonly ["record", "bulkWrite"];
|
|
42
20
|
/** @see PROJECTION_SCOPES — the axis this union is derived from. */
|
|
43
21
|
export type ProjectionScope = (typeof PROJECTION_SCOPES)[number];
|
|
44
22
|
/**
|
|
45
|
-
* Where a field may be written: the kind of argument POSITION a write sits in,
|
|
46
|
-
* the operation that carries it. The
|
|
47
|
-
*
|
|
48
|
-
* — an adapter may narrow one without narrowing the other.
|
|
49
|
-
*
|
|
50
|
-
* **A scope qualifies the TOP LEVEL of a write argument only. It does not narrow
|
|
51
|
-
* recursively**, for the same reason {@link ProjectionScope} does not: past an
|
|
52
|
-
* admitted entry the unrestricted surface returns. On both pilot engines
|
|
53
|
-
* `"bulkWrite"` admits no nested write at all, so today the rule has no admitted
|
|
54
|
-
* top-level entry to apply beneath — it is stated because an adapter that admits
|
|
55
|
-
* one must not then be narrowed a second level down, which would refuse what the
|
|
56
|
-
* ORM accepts.
|
|
57
|
-
*
|
|
58
|
-
* A value for the same reason {@link PROJECTION_SCOPES} is one, and a **separate**
|
|
59
|
-
* array because the two axes are separate: a write scope list that names every
|
|
60
|
-
* write position is degenerate, a write scope list that happens to have as many
|
|
61
|
-
* members as the projection axis is not.
|
|
23
|
+
* Where a field may be written: the kind of argument POSITION a write sits in,
|
|
24
|
+
* not the operation that carries it. The write counterpart of
|
|
25
|
+
* {@link ProjectionScope}.
|
|
62
26
|
*/
|
|
63
27
|
export declare const WRITE_SCOPES: readonly ["nested", "bulkWrite"];
|
|
64
28
|
/** @see WRITE_SCOPES — the axis this union is derived from. */
|
|
@@ -1,52 +1,10 @@
|
|
|
1
1
|
import type { ClientContract } from "./contract.js";
|
|
2
|
+
import type { JsonSchema } from "./json-shape.js";
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* member — `resources: { Spell: 5 }` — reaches it and throws a plain `TypeError`.
|
|
8
|
-
* The structure of a ClientContract is a core fact, so its check is core's, and
|
|
9
|
-
* every reader of an untrusted Contract (the client generator today, a host
|
|
10
|
-
* asserting what it serves tomorrow) asks this one function.
|
|
11
|
-
*
|
|
12
|
-
* # One source of truth: the schema IS the type
|
|
13
|
-
*
|
|
14
|
-
* {@link CLIENT_CONTRACT_STRUCTURE} is a passive description, and {@link
|
|
15
|
-
* Structured} decodes it into a TypeScript type. That decoded type must be
|
|
16
|
-
* `ClientContract` exactly, in both directions:
|
|
17
|
-
*
|
|
18
|
-
* - **schema → type** is enforced here, at build time: the accepted arm hands back
|
|
19
|
-
* the decoded value as a `ClientContract` with no cast, so a schema that admits
|
|
20
|
-
* something the type does not fails to compile.
|
|
21
|
-
* - **type → schema** is enforced by
|
|
22
|
-
* `client-contract-structure.validator.test-d.ts`: a schema that is stricter
|
|
23
|
-
* than the type — a vocabulary token missed, an optional member written as
|
|
24
|
-
* required — fails the type test.
|
|
25
|
-
*
|
|
26
|
-
* So a member added to, removed from or re-typed in core's ClientContract types
|
|
27
|
-
* breaks the build or the type test until this schema says the same thing.
|
|
28
|
-
*
|
|
29
|
-
* # Where the line is
|
|
30
|
-
*
|
|
31
|
-
* The line is the TYPE, judged at the erased `ClientContract`: what the type
|
|
32
|
-
* admits is accepted, what it rules out is refused. Two consequences are
|
|
33
|
-
* deliberate:
|
|
34
|
-
*
|
|
35
|
-
* - **References are not structure.** At the erased type a relation `target`, a
|
|
36
|
-
* field's `{ scalar }`/`{ enum }` and an identifier's field keys are `string`,
|
|
37
|
-
* so a dangling reference passes. Referential consistency is a separate,
|
|
38
|
-
* semantic check.
|
|
39
|
-
*
|
|
40
|
-
* One rule is stricter than the type, because no TypeScript type can state it:
|
|
41
|
-
* **an enum's values are distinct.** `readonly string[]` admits a repeat, but an
|
|
42
|
-
* enum with one names a member twice — the generated client's `as const` object
|
|
43
|
-
* would declare one key twice (TS1117) — so a repeat is refused at the second
|
|
44
|
-
* occurrence, naming the first. The list node carries it as `unique`, which {@link
|
|
45
|
-
* Structured} ignores, so the decoded type is still `ClientContract` exactly.
|
|
46
|
-
* Every reader judges it here, once, rather than each re-checking it.
|
|
47
|
-
*
|
|
48
|
-
* The validator reads every member it judges and never throws on any input: a
|
|
49
|
-
* value that is not JSON at all is reported, not crashed on.
|
|
4
|
+
* Whether an untrusted value is a `ClientContract`: every member present, of its JSON
|
|
5
|
+
* kind, inside its closed vocabulary, and nothing else. An enum's values must be
|
|
6
|
+
* distinct. Reads every member it judges and never throws on any input; a value that
|
|
7
|
+
* is not JSON at all is reported.
|
|
50
8
|
*/
|
|
51
9
|
/** A literal a closed vocabulary can hold. */
|
|
52
10
|
type Literal = string | number | boolean;
|
|
@@ -87,6 +45,12 @@ export type StructureNode = {
|
|
|
87
45
|
} | {
|
|
88
46
|
readonly is: "union";
|
|
89
47
|
readonly arms: readonly StructureNode[];
|
|
48
|
+
} | {
|
|
49
|
+
/**
|
|
50
|
+
* A Json Shape's schema: recursive, so judged by its own reader
|
|
51
|
+
* ({@link jsonSchemaDefect}) rather than spelled out in nodes.
|
|
52
|
+
*/
|
|
53
|
+
readonly is: "jsonSchema";
|
|
90
54
|
};
|
|
91
55
|
/**
|
|
92
56
|
* The TypeScript type a structure description admits, dispatched through a
|
|
@@ -122,6 +86,7 @@ type StructuredBy<N> = {
|
|
|
122
86
|
readonly union: N extends {
|
|
123
87
|
readonly arms: readonly (infer A)[];
|
|
124
88
|
} ? Structured<A> : never;
|
|
89
|
+
readonly jsonSchema: JsonSchema;
|
|
125
90
|
};
|
|
126
91
|
type StructuredObject<R, O> = {
|
|
127
92
|
readonly [K in keyof R]: Structured<R[K]>;
|
|
@@ -262,6 +227,9 @@ export declare const CLIENT_CONTRACT_STRUCTURE: {
|
|
|
262
227
|
readonly format: {
|
|
263
228
|
readonly is: "string";
|
|
264
229
|
};
|
|
230
|
+
readonly json: {
|
|
231
|
+
readonly is: "jsonSchema";
|
|
232
|
+
};
|
|
265
233
|
};
|
|
266
234
|
};
|
|
267
235
|
readonly relation: {
|
|
@@ -439,6 +407,10 @@ export declare const CLIENT_CONTRACT_STRUCTURE: {
|
|
|
439
407
|
readonly optional: Record<never, never>;
|
|
440
408
|
}];
|
|
441
409
|
};
|
|
410
|
+
readonly nestedWriteFilter: {
|
|
411
|
+
readonly is: "literal";
|
|
412
|
+
readonly values: readonly ["scalar"];
|
|
413
|
+
};
|
|
442
414
|
};
|
|
443
415
|
};
|
|
444
416
|
};
|
|
@@ -1100,15 +1072,17 @@ export declare const CLIENT_CONTRACT_STRUCTURE: {
|
|
|
1100
1072
|
readonly optional: Record<never, never>;
|
|
1101
1073
|
};
|
|
1102
1074
|
};
|
|
1103
|
-
readonly optional:
|
|
1075
|
+
readonly optional: {
|
|
1076
|
+
readonly referenceWrites: {
|
|
1077
|
+
readonly is: "literal";
|
|
1078
|
+
readonly values: readonly ["uniform"];
|
|
1079
|
+
};
|
|
1080
|
+
};
|
|
1104
1081
|
};
|
|
1105
1082
|
/**
|
|
1106
|
-
* The answer. A refusal names the
|
|
1107
|
-
*
|
|
1108
|
-
* `message`
|
|
1109
|
-
*
|
|
1110
|
-
* The specification allocates no error code to a malformed ClientContract — the
|
|
1111
|
-
* A/V codes are request outcomes, not generator failures — so none is invented.
|
|
1083
|
+
* The answer of {@link validateClientContractStructure}. A refusal names the
|
|
1084
|
+
* first defect found, as a `path` in JSONPath form (`$.resources.Spell`) and
|
|
1085
|
+
* a `message` that begins with that path in quotes.
|
|
1112
1086
|
*/
|
|
1113
1087
|
export type ClientContractStructureVerdict = {
|
|
1114
1088
|
readonly valid: true;
|