@aventara/core 1.0.0-rc.0 → 1.0.0-rc.2
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 +1434 -0
- package/ERRORS.md +142 -0
- package/README.md +247 -57
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
- package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
- package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
- package/dist/adapters/adapter-field.d.ts +25 -11
- package/dist/adapters/adapter-identifier.d.ts +6 -6
- package/dist/adapters/adapter-model.d.ts +18 -9
- package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
- package/dist/adapters/adapter-operation.d.ts +3 -3
- package/dist/adapters/adapter-resource.d.ts +18 -9
- package/dist/adapters/adapter-sql-statement.d.ts +19 -0
- package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
- package/dist/adapters/adapter.interface.d.ts +59 -29
- package/dist/avz/avz-check.factory.d.ts +83 -0
- package/dist/avz/avz-check.factory.js +116 -0
- package/dist/avz/avz-check.registry.d.ts +35 -0
- package/dist/avz/avz-check.registry.js +9 -0
- package/dist/avz/avz.d.ts +203 -0
- package/dist/{json → avz}/avz.js +150 -8
- package/dist/{json → avz}/index.d.ts +2 -1
- package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
- package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
- package/dist/{json → avz}/zod-issue.translator.js +7 -0
- package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
- package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
- package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
- package/dist/compiler/contract.compiler.d.ts +18 -18
- package/dist/compiler/contract.compiler.js +637 -442
- package/dist/compiler/create-requirements.projector.d.ts +49 -0
- package/dist/compiler/create-requirements.projector.js +423 -0
- package/dist/compiler/field-validator.compiler.d.ts +47 -0
- package/dist/compiler/field-validator.compiler.js +238 -0
- package/dist/config/any-framework-config.d.ts +19 -12
- package/dist/config/computed-fields.d.ts +62 -0
- package/dist/config/computed-fields.js +80 -0
- package/dist/config/config-diagnostic.d.ts +11 -4
- package/dist/config/config-diagnostic.guidance.d.ts +6 -0
- package/dist/config/config-diagnostic.guidance.js +32 -0
- package/dist/config/config-layer.d.ts +15 -6
- package/dist/config/config.resolver.d.ts +74 -31
- package/dist/config/config.resolver.js +108 -44
- package/dist/config/config.validator.d.ts +7 -7
- package/dist/config/config.validator.js +581 -72
- package/dist/config/define-resource.d.ts +57 -0
- package/dist/config/define-resource.js +14 -0
- package/dist/config/effective-fields.d.ts +19 -23
- package/dist/config/entrypoint.normalizer.d.ts +1 -1
- package/dist/config/exact-framework-config.d.ts +308 -0
- package/dist/config/field-compute.resolver.d.ts +21 -0
- package/dist/config/field-compute.resolver.js +123 -0
- package/dist/config/field-pipeline-config.d.ts +47 -0
- package/dist/config/forced-operation.validator.d.ts +10 -0
- package/dist/config/forced-operation.validator.js +66 -0
- package/dist/config/framework-config.d.ts +111 -39
- package/dist/config/framework-exemptions-config.d.ts +91 -0
- package/dist/config/framework-exemptions-config.js +1 -0
- package/dist/config/framework-field-definition.d.ts +78 -0
- package/dist/config/framework-field-definition.js +28 -0
- package/dist/config/framework-resources-config.d.ts +122 -0
- package/dist/config/framework-resources-config.js +1 -0
- package/dist/config/pipeline-config.d.ts +56 -20
- package/dist/config/pipeline-tree.resolver.d.ts +79 -0
- package/dist/config/pipeline-tree.resolver.js +220 -0
- package/dist/config/stage-type.eraser.d.ts +65 -0
- package/dist/config/stage-type.eraser.js +1 -0
- package/dist/contracts/capability.d.ts +21 -12
- package/dist/contracts/capability.js +2 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +388 -63
- package/dist/contracts/client-contract-structure.validator.js +156 -10
- package/dist/contracts/contract-canonicalizer.d.ts +26 -3
- package/dist/contracts/contract-canonicalizer.js +156 -29
- package/dist/contracts/contract-hash.d.ts +12 -7
- package/dist/contracts/contract-hash.js +3 -2
- package/dist/contracts/contract-limits.d.ts +4 -1
- package/dist/contracts/contract-limits.js +1 -0
- package/dist/contracts/contract-lookup.d.ts +5 -5
- package/dist/contracts/contract-protocol.d.ts +4 -4
- package/dist/contracts/contract.d.ts +24 -16
- package/dist/contracts/create-requirements.d.ts +35 -0
- package/dist/contracts/create-requirements.js +1 -0
- package/dist/contracts/enum-definition.d.ts +1 -1
- package/dist/contracts/field-check.d.ts +101 -0
- package/dist/contracts/field-check.js +1 -0
- package/dist/contracts/field.d.ts +81 -42
- package/dist/contracts/identifier.d.ts +4 -4
- package/dist/contracts/json-shape.d.ts +12 -1
- package/dist/contracts/lifecycle-trait.d.ts +2 -2
- package/dist/contracts/resource-operations.d.ts +28 -28
- package/dist/contracts/resource.d.ts +15 -9
- package/dist/contracts/scalar-value-type.d.ts +15 -15
- package/dist/contracts/scalar.d.ts +3 -3
- package/dist/contracts/transaction-capability.d.ts +1 -1
- package/dist/contracts/wire-scalar-format.d.ts +4 -4
- package/dist/framework/contract-view.d.ts +213 -147
- package/dist/framework/framework-construction.error.d.ts +19 -10
- package/dist/framework/framework-construction.error.js +7 -3
- package/dist/framework/framework.d.ts +47 -23
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +49 -22
- package/dist/framework/operation-facade.d.ts +123 -52
- package/dist/framework/operation-facade.js +9 -1
- package/dist/index.d.ts +57 -50
- package/dist/index.js +7 -6
- package/dist/internal.d.ts +17 -10
- package/dist/internal.js +4 -1
- package/dist/operations/database-refusal.d.ts +51 -0
- package/dist/operations/database-refusal.js +45 -0
- package/dist/operations/operation-arguments.d.ts +343 -207
- package/dist/operations/operation-call.d.ts +27 -28
- package/dist/operations/operation-identity.d.ts +10 -10
- package/dist/operations/operation-result.d.ts +21 -21
- package/dist/operations/operation-validator-core.d.ts +6 -6
- package/dist/operations/operation-validator-core.js +99 -6
- package/dist/operations/operation-validator.d.ts +9 -9
- package/dist/operations/projection-scope.resolver.d.ts +6 -6
- package/dist/operations/structural-limits.walker.d.ts +6 -6
- package/dist/operations/structural-limits.walker.js +145 -0
- package/dist/operations/validation-code.d.ts +11 -6
- package/dist/operations/validation-code.guidance.d.ts +6 -0
- package/dist/operations/validation-code.guidance.js +90 -0
- package/dist/operations/validation-code.js +4 -0
- package/dist/operations/write-scope.resolver.d.ts +10 -6
- package/dist/operations/write-scope.resolver.js +2 -0
- package/dist/protocol/absent-route.responder.d.ts +13 -12
- package/dist/protocol/absent-route.responder.js +19 -19
- package/dist/protocol/contract-document.responder.d.ts +3 -3
- package/dist/protocol/contract-document.responder.js +2 -2
- package/dist/protocol/http-request.decoder.d.ts +17 -13
- package/dist/protocol/http-request.decoder.js +10 -10
- package/dist/protocol/http-request.reader.d.ts +3 -3
- package/dist/protocol/http-response.encoder.d.ts +4 -4
- package/dist/protocol/http-response.encoder.js +94 -55
- package/dist/protocol/http-status.table.d.ts +2 -2
- package/dist/protocol/operation-response.guard.d.ts +2 -2
- package/dist/protocol/protocol-surface.d.ts +4 -4
- package/dist/protocol/protocol.binder.d.ts +50 -27
- package/dist/protocol/protocol.binder.js +12 -9
- package/dist/protocol/protocol.handler.d.ts +22 -13
- package/dist/protocol/protocol.handler.js +91 -17
- package/dist/protocol/unmounted-route.error.d.ts +4 -4
- package/dist/protocol/unmounted-route.error.js +2 -2
- package/dist/runtime/caller-data.copier.d.ts +22 -5
- package/dist/runtime/caller-data.copier.js +31 -14
- package/dist/runtime/caller-data.door.d.ts +17 -11
- package/dist/runtime/caller-data.door.js +6 -4
- package/dist/runtime/computed-read-runtime.d.ts +7 -6
- package/dist/runtime/computed-read-runtime.js +76 -50
- package/dist/runtime/computed-value.error.d.ts +7 -6
- package/dist/runtime/computed-value.error.js +5 -4
- package/dist/runtime/context-executor.runtime.d.ts +59 -0
- package/dist/runtime/context-executor.runtime.js +275 -0
- package/dist/runtime/create-requirement.d.ts +44 -79
- package/dist/runtime/create-requirement.js +213 -73
- package/dist/runtime/decimal.d.ts +2 -2
- package/dist/runtime/decimal.js +1 -1
- package/dist/runtime/diagnostics-reporter.d.ts +54 -27
- package/dist/runtime/diagnostics-reporter.js +24 -0
- package/dist/runtime/error-boundary.d.ts +65 -8
- package/dist/runtime/error-boundary.js +49 -19
- package/dist/runtime/error-guidance.d.ts +12 -0
- package/dist/runtime/error-guidance.js +1 -0
- package/dist/runtime/error.catalog.d.ts +49 -0
- package/dist/runtime/error.catalog.js +49 -0
- package/dist/runtime/execution-options.d.ts +10 -2
- package/dist/runtime/field-check.evaluator.d.ts +29 -0
- package/dist/runtime/field-check.evaluator.js +521 -0
- package/dist/runtime/field-compute.d.ts +64 -0
- package/dist/runtime/field-compute.js +1 -0
- package/dist/runtime/field-stage.plan.d.ts +15 -0
- package/dist/runtime/field-stage.plan.js +27 -0
- package/dist/runtime/field-stage.runtime.d.ts +37 -0
- package/dist/runtime/field-stage.runtime.js +147 -0
- package/dist/runtime/field-validator.runtime.d.ts +19 -0
- package/dist/runtime/field-validator.runtime.js +92 -0
- package/dist/runtime/framework-error-class.table.d.ts +33 -0
- package/dist/runtime/framework-error-class.table.js +25 -0
- package/dist/runtime/framework-error.d.ts +68 -8
- package/dist/runtime/framework-error.factory.d.ts +4 -0
- package/dist/runtime/framework-error.factory.js +15 -0
- package/dist/runtime/framework-error.js +23 -2
- package/dist/runtime/interceptor-next.error.d.ts +5 -0
- package/dist/runtime/interceptor-next.error.js +6 -0
- package/dist/runtime/json-value.d.ts +11 -6
- package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
- package/dist/runtime/level-lifecycle.runtime.js +39 -0
- package/dist/runtime/misuse-reporter.d.ts +12 -12
- package/dist/runtime/mutation-planner.d.ts +19 -10
- package/dist/runtime/mutation-planner.js +48 -35
- package/dist/runtime/nested-write.walker.d.ts +32 -0
- package/dist/runtime/nested-write.walker.js +73 -0
- package/dist/runtime/operation-code.guidance.d.ts +6 -0
- package/dist/runtime/operation-code.guidance.js +167 -0
- package/dist/runtime/operation-request.d.ts +33 -6
- package/dist/runtime/operation-response.d.ts +17 -17
- package/dist/runtime/operation-runtime.d.ts +127 -25
- package/dist/runtime/operation-runtime.js +441 -78
- package/dist/runtime/outcome-mapper.d.ts +16 -5
- package/dist/runtime/outcome-mapper.js +23 -6
- package/dist/runtime/output-validator.d.ts +10 -10
- package/dist/runtime/output-validator.js +3 -3
- package/dist/runtime/owned-execution.registry.d.ts +16 -6
- package/dist/runtime/pipe-output.validator.d.ts +43 -18
- package/dist/runtime/pipe-output.validator.js +15 -13
- package/dist/runtime/pipeline.d.ts +223 -34
- package/dist/runtime/readonly-value.d.ts +43 -0
- package/dist/runtime/readonly-value.js +150 -0
- package/dist/runtime/request-envelope.validator.d.ts +3 -3
- package/dist/runtime/request-envelope.validator.js +12 -7
- package/dist/runtime/request-id.d.ts +1 -1
- package/dist/runtime/request-state.d.ts +14 -0
- package/dist/runtime/request-state.js +1 -0
- package/dist/runtime/request-state.resolver.d.ts +12 -0
- package/dist/runtime/request-state.resolver.js +20 -0
- package/dist/runtime/scalar-runtime.d.ts +35 -16
- package/dist/runtime/scalar-runtime.js +102 -34
- package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
- package/dist/runtime/unsent-value.normalizer.js +128 -0
- package/dist/transactions/deferred-operation.d.ts +35 -20
- package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
- package/dist/transactions/operation-arguments-encoder.js +2 -2
- package/dist/transactions/operation-fingerprint.js +2 -2
- package/dist/transactions/sql-statement.d.ts +85 -0
- package/dist/transactions/sql-statement.js +47 -0
- package/dist/transactions/sql-statement.validator.d.ts +44 -0
- package/dist/transactions/sql-statement.validator.js +167 -0
- package/dist/transactions/transaction-envelope.d.ts +4 -4
- package/dist/transactions/transaction-integrity-error.d.ts +6 -6
- package/dist/transactions/transaction-integrity-error.js +5 -2
- package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
- package/dist/transactions/transaction-plan-assembler.js +169 -32
- package/dist/transactions/transaction-plan-validator.d.ts +45 -20
- package/dist/transactions/transaction-plan-validator.js +96 -38
- package/dist/transactions/transaction-reference-collector.d.ts +5 -5
- package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
- package/dist/transactions/transaction-reference-resolver.js +26 -14
- package/dist/transactions/transaction-reference-validator.d.ts +76 -4
- package/dist/transactions/transaction-reference-validator.js +129 -71
- package/dist/transactions/transaction-reference.d.ts +13 -13
- package/dist/transactions/transaction-reference.js +5 -0
- package/dist/transactions/transaction-request.d.ts +18 -5
- package/dist/transactions/transaction-response.d.ts +6 -6
- package/dist/transactions/transaction-runtime.d.ts +8 -7
- package/dist/transactions/transaction-runtime.js +191 -50
- package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
- package/dist/transactions/transaction-settlement.runtime.js +120 -0
- package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
- package/dist/transactions/transaction-slot-path-error.js +2 -2
- package/dist/transactions/transaction-slot-writer.js +2 -2
- package/dist/transactions/transaction-stage.runtime.d.ts +82 -0
- package/dist/transactions/transaction-stage.runtime.js +126 -0
- package/package.json +9 -7
- package/src/runtime/field-check.evaluator.ts +720 -0
- package/dist/config/define-fields.d.ts +0 -42
- package/dist/config/define-fields.js +0 -3
- package/dist/config/framework-behaviors-config.d.ts +0 -30
- package/dist/config/framework-fields-config.d.ts +0 -42
- package/dist/config/framework-restrictions-config.d.ts +0 -142
- package/dist/json/avz.d.ts +0 -96
- package/dist/runtime/field-behavior.d.ts +0 -48
- /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
- /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
- /package/dist/{json → avz}/index.js +0 -0
- /package/dist/{json → avz}/json-shape.registry.js +0 -0
- /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
- /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import type { JsonSchemaPrimitive, JsonShape, JsonShapeValue } from "../contracts/json-shape.js";
|
|
2
|
+
import { type AvZCheck } from "./avz-check.registry.js";
|
|
3
|
+
/** The forms a Json Shape takes. */
|
|
4
|
+
export type AvZKind = "string" | "number" | "int" | "boolean" | "null" | "literal" | "enum" | "object" | "array" | "tuple" | "record" | "union" | "discriminatedUnion" | "optional" | "nullable";
|
|
5
|
+
/** The checks a shape of one kind takes: a string's, a number's, a list's length; else none. */
|
|
6
|
+
type AvZShapeCheck<Kind extends AvZKind> = Kind extends "string" ? AvZCheck<"string"> : Kind extends "number" | "int" ? AvZCheck<"number"> : Kind extends "array" ? AvZCheck<"list"> : never;
|
|
7
|
+
/**
|
|
8
|
+
* A Json Shape built with {@link AvZ}: opaque, its `kind` and `check` its only
|
|
9
|
+
* members. Its TypeScript type is `AvZ.infer<typeof shape>`.
|
|
10
|
+
*/
|
|
11
|
+
export interface AvZShape<Value = unknown, Kind extends AvZKind = AvZKind> extends JsonShape<Value> {
|
|
12
|
+
readonly kind: Kind;
|
|
13
|
+
/**
|
|
14
|
+
* The same shape with `checks` added: a string takes length, pattern and
|
|
15
|
+
* format checks, a number or an integer takes bounds and `multipleOf`, an
|
|
16
|
+
* array takes `AvZ.minItems`/`AvZ.maxItems`. No other shape takes any.
|
|
17
|
+
*/
|
|
18
|
+
check(...checks: readonly AvZShapeCheck<Kind>[]): this;
|
|
19
|
+
}
|
|
20
|
+
/** The fields of an object shape, by key. */
|
|
21
|
+
export type AvZFields = {
|
|
22
|
+
readonly [key: string]: AvZShape;
|
|
23
|
+
};
|
|
24
|
+
declare const avzOptionalKey: unique symbol;
|
|
25
|
+
/** Marks a shape whose object key may be left out. Type-level only. */
|
|
26
|
+
interface AvZOptionalKey {
|
|
27
|
+
readonly [avzOptionalKey]: true;
|
|
28
|
+
}
|
|
29
|
+
type FieldKeysOptional<Fields extends AvZFields> = {
|
|
30
|
+
[Key in keyof Fields]: Fields[Key] extends AvZOptionalKey ? Key : never;
|
|
31
|
+
}[keyof Fields];
|
|
32
|
+
type Flatten<T> = {
|
|
33
|
+
[Key in keyof T]: T[Key];
|
|
34
|
+
} & {};
|
|
35
|
+
/** The value an object shape describes. */
|
|
36
|
+
type AvZObjectValue<Fields extends AvZFields> = ObjectValueOf<Fields, FieldKeysOptional<Fields>>;
|
|
37
|
+
type ObjectValueOf<Fields extends AvZFields, Optional extends keyof Fields> = Flatten<{
|
|
38
|
+
-readonly [Key in Exclude<keyof Fields, Optional>]: JsonShapeValue<Fields[Key]>;
|
|
39
|
+
} & {
|
|
40
|
+
-readonly [Key in Optional]?: JsonShapeValue<Fields[Key]>;
|
|
41
|
+
}>;
|
|
42
|
+
/** An object shape: closed, so a key it does not declare is refused. */
|
|
43
|
+
export interface AvZObject<Fields extends AvZFields = AvZFields> extends AvZShape<AvZObjectValue<Fields>, "object"> {
|
|
44
|
+
readonly fields: Fields;
|
|
45
|
+
}
|
|
46
|
+
/** A shape whose object key may be left out. */
|
|
47
|
+
export interface AvZOptional<Inner extends AvZShape = AvZShape> extends AvZShape<JsonShapeValue<Inner> | undefined, "optional">, AvZOptionalKey {
|
|
48
|
+
}
|
|
49
|
+
/** A shape that also admits `null`. */
|
|
50
|
+
export type AvZNullable<Inner extends AvZShape = AvZShape> = AvZShape<JsonShapeValue<Inner> | null, "nullable"> & (Inner extends AvZOptionalKey ? AvZOptionalKey : unknown);
|
|
51
|
+
/** A value a literal shape may hold. */
|
|
52
|
+
export type AvZLiteralValue = JsonSchemaPrimitive;
|
|
53
|
+
/** What keys a record shape: any string, an enum's values or one literal. */
|
|
54
|
+
type AvZRecordKey = AvZShape<string, "string"> | AvZShape<string, "enum"> | AvZShape<string, "literal">;
|
|
55
|
+
/** An option of a discriminated union: an object whose discriminator is a literal or an enum. */
|
|
56
|
+
type AvZDiscriminable<Discriminator extends string> = AvZObject<{
|
|
57
|
+
readonly [Key in Discriminator]: AvZShape<AvZLiteralValue, "literal"> | AvZShape<string, "enum">;
|
|
58
|
+
} & AvZFields>;
|
|
59
|
+
type TupleValue<Items extends readonly AvZShape[]> = {
|
|
60
|
+
-readonly [Index in keyof Items]: JsonShapeValue<Items[Index]>;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Builds Json Shapes (the type of a Json field, declared at
|
|
64
|
+
* `resources.<Resource>.fields.<field>.definition.json`) and checks in zod's
|
|
65
|
+
* vocabulary: a field's `validators`, and a shape node's `check(...)`. No
|
|
66
|
+
* refinements, transforms or defaults. Objects are closed: a key the shape does
|
|
67
|
+
* not declare is refused.
|
|
68
|
+
*/
|
|
69
|
+
export declare class AvZ {
|
|
70
|
+
private constructor();
|
|
71
|
+
/** Any string. */
|
|
72
|
+
static readonly string: () => AvZShape<string, "string">;
|
|
73
|
+
/** Any finite number. */
|
|
74
|
+
static readonly number: () => AvZShape<number, "number">;
|
|
75
|
+
/** An integer (a safe one). */
|
|
76
|
+
static readonly int: () => AvZShape<number, "int">;
|
|
77
|
+
/** `true` or `false`. */
|
|
78
|
+
static readonly boolean: () => AvZShape<boolean, "boolean">;
|
|
79
|
+
/** `null`. */
|
|
80
|
+
static readonly null: () => AvZShape<null, "null">;
|
|
81
|
+
/** Exactly `value`: a string, a finite number, a boolean or `null`. */
|
|
82
|
+
static readonly literal: <const Value extends AvZLiteralValue>(value: Value) => AvZShape<Value, "literal">;
|
|
83
|
+
/** One of `values`. */
|
|
84
|
+
static readonly enum: <const Values extends readonly [string, ...string[]]>(values: Values) => AvZShape<Values[number], "enum">;
|
|
85
|
+
/** An object with exactly these keys; `AvZ.optional` marks one that may be left out. */
|
|
86
|
+
static readonly object: <const Fields extends AvZFields>(fields: Fields) => AvZObject<Fields>;
|
|
87
|
+
/** A list of `item`s. */
|
|
88
|
+
static readonly array: <Item extends AvZShape>(item: Item) => AvZShape<JsonShapeValue<Item>[], "array">;
|
|
89
|
+
/** A list of exactly these items, in order. */
|
|
90
|
+
static readonly tuple: <const Items extends readonly [AvZShape, ...AvZShape[]]>(items: Items) => AvZShape<TupleValue<Items>, "tuple">;
|
|
91
|
+
/** An object of `value`s, keyed by any string, an enum's values or a literal. */
|
|
92
|
+
static readonly record: <Key extends AvZRecordKey, Value extends AvZShape>(key: Key, value: Value) => AvZShape<Record<JsonShapeValue<Key>, JsonShapeValue<Value>>, "record">;
|
|
93
|
+
/** Any one of `options`. */
|
|
94
|
+
static readonly union: <const Options extends readonly [AvZShape, AvZShape, ...AvZShape[]]>(options: Options) => AvZShape<JsonShapeValue<Options[number]>, "union">;
|
|
95
|
+
/** One of `options`, told apart by the literal or enum at `discriminator`. */
|
|
96
|
+
static readonly discriminatedUnion: <Discriminator extends string, const Options extends readonly [AvZDiscriminable<Discriminator>, ...AvZDiscriminable<Discriminator>[]]>(discriminator: Discriminator, options: Options) => AvZShape<JsonShapeValue<Options[number]>, "discriminatedUnion">;
|
|
97
|
+
/** An object key that may be left out. */
|
|
98
|
+
static readonly optional: <Inner extends AvZShape>(inner: Inner) => AvZOptional<Inner>;
|
|
99
|
+
/** `inner`, or `null`. */
|
|
100
|
+
static readonly nullable: <Inner extends AvZShape>(inner: Inner) => AvZNullable<Inner>;
|
|
101
|
+
/** A value below `value` (a number, a bigint or a `Date`). */
|
|
102
|
+
static readonly lt: <const Value extends number | bigint | Date>(value: Value) => AvZCheck<Value extends Date ? "datetime" : Value extends bigint ? "bigint" | "decimal" : "number" | "decimal">;
|
|
103
|
+
/** A value at most `value` (a number, a bigint or a `Date`). */
|
|
104
|
+
static readonly lte: <const Value extends number | bigint | Date>(value: Value) => AvZCheck<Value extends Date ? "datetime" : Value extends bigint ? "bigint" | "decimal" : "number" | "decimal">;
|
|
105
|
+
/** A value above `value` (a number, a bigint or a `Date`). */
|
|
106
|
+
static readonly gt: <const Value extends number | bigint | Date>(value: Value) => AvZCheck<Value extends Date ? "datetime" : Value extends bigint ? "bigint" | "decimal" : "number" | "decimal">;
|
|
107
|
+
/** A value at least `value` (a number, a bigint or a `Date`). */
|
|
108
|
+
static readonly gte: <const Value extends number | bigint | Date>(value: Value) => AvZCheck<Value extends Date ? "datetime" : Value extends bigint ? "bigint" | "decimal" : "number" | "decimal">;
|
|
109
|
+
/** A value above zero. */
|
|
110
|
+
static readonly positive: () => AvZCheck<"number" | "bigint" | "decimal">;
|
|
111
|
+
/** A value at least zero. */
|
|
112
|
+
static readonly nonnegative: () => AvZCheck<"number" | "bigint" | "decimal">;
|
|
113
|
+
/** A value below zero. */
|
|
114
|
+
static readonly negative: () => AvZCheck<"number" | "bigint" | "decimal">;
|
|
115
|
+
/** A value at most zero. */
|
|
116
|
+
static readonly nonpositive: () => AvZCheck<"number" | "bigint" | "decimal">;
|
|
117
|
+
/** A multiple of `value`. */
|
|
118
|
+
static readonly multipleOf: <const Value extends number | bigint>(value: Value) => AvZCheck<Value extends bigint ? "bigint" | "decimal" : "number" | "decimal">;
|
|
119
|
+
/** A string of at most `maximum` characters; on a list field, each entry. */
|
|
120
|
+
static readonly maxLength: (maximum: number) => AvZCheck<"string">;
|
|
121
|
+
/** A string of at least `minimum` characters; on a list field, each entry. */
|
|
122
|
+
static readonly minLength: (minimum: number) => AvZCheck<"string">;
|
|
123
|
+
/** A string of exactly `length` characters; on a list field, each entry. */
|
|
124
|
+
static readonly length: (exact: number) => AvZCheck<"string">;
|
|
125
|
+
/** A list of at most `maximum` entries: a list field, or an array shape. */
|
|
126
|
+
static readonly maxItems: (maximum: number) => AvZCheck<"list">;
|
|
127
|
+
/** A list of at least `minimum` entries: a list field, or an array shape. */
|
|
128
|
+
static readonly minItems: (minimum: number) => AvZCheck<"list">;
|
|
129
|
+
/** Bytes of at most `maximum` in length. */
|
|
130
|
+
static readonly maxSize: (maximum: number) => AvZCheck<"bytes">;
|
|
131
|
+
/** Bytes of at least `minimum` in length. */
|
|
132
|
+
static readonly minSize: (minimum: number) => AvZCheck<"bytes">;
|
|
133
|
+
/** Bytes of exactly `size` in length. */
|
|
134
|
+
static readonly size: (exact: number) => AvZCheck<"bytes">;
|
|
135
|
+
/** A string the pattern matches: a JavaScript regular expression, flags included. */
|
|
136
|
+
static readonly regex: (pattern: RegExp) => AvZCheck<"string">;
|
|
137
|
+
/** A string containing `value`. */
|
|
138
|
+
static readonly includes: (value: string) => AvZCheck<"string">;
|
|
139
|
+
/** A string starting with `prefix`. */
|
|
140
|
+
static readonly startsWith: (prefix: string) => AvZCheck<"string">;
|
|
141
|
+
/** A string ending with `suffix`. */
|
|
142
|
+
static readonly endsWith: (suffix: string) => AvZCheck<"string">;
|
|
143
|
+
/** A string with no uppercase letter. */
|
|
144
|
+
static readonly lowercase: () => AvZCheck<"string">;
|
|
145
|
+
/** A string with no lowercase letter. */
|
|
146
|
+
static readonly uppercase: () => AvZCheck<"string">;
|
|
147
|
+
/** An email address. */
|
|
148
|
+
static readonly email: () => AvZCheck<"string">;
|
|
149
|
+
/** A URL. */
|
|
150
|
+
static readonly url: () => AvZCheck<"string">;
|
|
151
|
+
/** Emoji only. */
|
|
152
|
+
static readonly emoji: () => AvZCheck<"string">;
|
|
153
|
+
/** A UUID (any version). */
|
|
154
|
+
static readonly uuid: () => AvZCheck<"string">;
|
|
155
|
+
/** A GUID: any 8-4-4-4-12 hex identifier. */
|
|
156
|
+
static readonly guid: () => AvZCheck<"string">;
|
|
157
|
+
/** A Nano ID. */
|
|
158
|
+
static readonly nanoid: () => AvZCheck<"string">;
|
|
159
|
+
/** A CUID. */
|
|
160
|
+
static readonly cuid: () => AvZCheck<"string">;
|
|
161
|
+
/** A CUID2. */
|
|
162
|
+
static readonly cuid2: () => AvZCheck<"string">;
|
|
163
|
+
/** A ULID. */
|
|
164
|
+
static readonly ulid: () => AvZCheck<"string">;
|
|
165
|
+
/** An XID. */
|
|
166
|
+
static readonly xid: () => AvZCheck<"string">;
|
|
167
|
+
/** A KSUID. */
|
|
168
|
+
static readonly ksuid: () => AvZCheck<"string">;
|
|
169
|
+
/** An IPv4 address. */
|
|
170
|
+
static readonly ipv4: () => AvZCheck<"string">;
|
|
171
|
+
/** An IPv6 address. */
|
|
172
|
+
static readonly ipv6: () => AvZCheck<"string">;
|
|
173
|
+
/** An IPv4 CIDR block. */
|
|
174
|
+
static readonly cidrv4: () => AvZCheck<"string">;
|
|
175
|
+
/** An IPv6 CIDR block. */
|
|
176
|
+
static readonly cidrv6: () => AvZCheck<"string">;
|
|
177
|
+
/** Base64. */
|
|
178
|
+
static readonly base64: () => AvZCheck<"string">;
|
|
179
|
+
/** Base64url. */
|
|
180
|
+
static readonly base64url: () => AvZCheck<"string">;
|
|
181
|
+
/** A string that parses as JSON (zod's `json_string` format). */
|
|
182
|
+
static readonly jsonString: () => AvZCheck<"string">;
|
|
183
|
+
/** An E.164 phone number. */
|
|
184
|
+
static readonly e164: () => AvZCheck<"string">;
|
|
185
|
+
/** A credit card number (Luhn-checked). */
|
|
186
|
+
static readonly creditCard: () => AvZCheck<"string">;
|
|
187
|
+
/** An IBAN (checksum-checked). */
|
|
188
|
+
static readonly iban: () => AvZCheck<"string">;
|
|
189
|
+
/** A JWT. */
|
|
190
|
+
static readonly jwt: () => AvZCheck<"string">;
|
|
191
|
+
/** ISO 8601: `datetime`, `date`, `time` and `duration`. */
|
|
192
|
+
static readonly iso: Readonly<{
|
|
193
|
+
datetime: () => AvZCheck<"string">;
|
|
194
|
+
date: () => AvZCheck<"string">;
|
|
195
|
+
time: () => AvZCheck<"string">;
|
|
196
|
+
duration: () => AvZCheck<"string">;
|
|
197
|
+
}>;
|
|
198
|
+
}
|
|
199
|
+
export declare namespace AvZ {
|
|
200
|
+
/** The TypeScript type a shape describes. */
|
|
201
|
+
type infer<Shape extends JsonShape> = JsonShapeValue<Shape>;
|
|
202
|
+
}
|
|
203
|
+
export {};
|
package/dist/{json → avz}/avz.js
RENAMED
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { array as zodArray, boolean as zodBoolean, discriminatedUnion as zodDiscriminatedUnion, enum as zodEnum, int as zodInt, literal as zodLiteral, null as zodNull, nullable as zodNullable, number as zodNumber, optional as zodOptional, record as zodRecord, strictObject as zodStrictObject, string as zodString, tuple as zodTuple, union as zodUnion, } from "zod/mini";
|
|
2
|
+
import { fieldCheckIssue, passesFieldCheck, } from "../runtime/field-check.evaluator.js";
|
|
3
|
+
import * as checks from "./avz-check.factory.js";
|
|
4
|
+
import { avzCheckOf, } from "./avz-check.registry.js";
|
|
2
5
|
import { registerJsonShape } from "./json-shape.registry.js";
|
|
3
|
-
import { translateZodIssues } from "./zod-issue.translator.js";
|
|
4
|
-
const z =
|
|
5
|
-
|
|
6
|
+
import { AVZ_CHECK_ISSUE, translateZodIssues, } from "./zod-issue.translator.js";
|
|
7
|
+
const z = {
|
|
8
|
+
string: zodString,
|
|
9
|
+
number: zodNumber,
|
|
10
|
+
int: zodInt,
|
|
11
|
+
boolean: zodBoolean,
|
|
12
|
+
null: zodNull,
|
|
13
|
+
literal: zodLiteral,
|
|
14
|
+
enum: zodEnum,
|
|
15
|
+
strictObject: zodStrictObject,
|
|
16
|
+
array: zodArray,
|
|
17
|
+
tuple: zodTuple,
|
|
18
|
+
record: zodRecord,
|
|
19
|
+
union: zodUnion,
|
|
20
|
+
discriminatedUnion: zodDiscriminatedUnion,
|
|
21
|
+
optional: zodOptional,
|
|
22
|
+
nullable: zodNullable,
|
|
23
|
+
};
|
|
6
24
|
const compiled = new WeakMap();
|
|
7
25
|
function compiledOf(builder, value) {
|
|
8
26
|
const found = typeof value === "object" && value !== null
|
|
@@ -20,10 +38,17 @@ function requiredPart(builder, value) {
|
|
|
20
38
|
}
|
|
21
39
|
return part;
|
|
22
40
|
}
|
|
23
|
-
function build(node, zod, schema, optionalKey = false) {
|
|
41
|
+
function build(node, zod, schema, optionalKey = false, checked) {
|
|
24
42
|
const shape = Object.freeze(Object.assign(Object.create(SHAPE_PROTOTYPE), { kind: node.kind }));
|
|
25
43
|
const frozenSchema = deepFreeze(schema);
|
|
26
|
-
compiled.set(shape, {
|
|
44
|
+
compiled.set(shape, {
|
|
45
|
+
node,
|
|
46
|
+
zod,
|
|
47
|
+
schema: frozenSchema,
|
|
48
|
+
optionalKey,
|
|
49
|
+
unchecked: checked?.unchecked ?? zod,
|
|
50
|
+
checks: checked?.checks ?? [],
|
|
51
|
+
});
|
|
27
52
|
registerJsonShape(shape, {
|
|
28
53
|
schema: frozenSchema,
|
|
29
54
|
validate: (value) => {
|
|
@@ -35,6 +60,69 @@ function build(node, zod, schema, optionalKey = false) {
|
|
|
35
60
|
});
|
|
36
61
|
return shape;
|
|
37
62
|
}
|
|
63
|
+
const CHECKABLE = {
|
|
64
|
+
string: { target: "string", subject: "string", label: "string" },
|
|
65
|
+
number: { target: "number", subject: "number", label: "number" },
|
|
66
|
+
int: { target: "number", subject: "number", label: "int" },
|
|
67
|
+
array: { target: "list", subject: "number", label: "array" },
|
|
68
|
+
};
|
|
69
|
+
function shapeCheck(kind, target, added) {
|
|
70
|
+
const data = avzCheckOf(added);
|
|
71
|
+
if (data === undefined) {
|
|
72
|
+
throw new TypeError(`AvZ.${kind}(…).check: every check must be built with AvZ (AvZ.maxLength(…), AvZ.email(), …); a Zod check or any other value is not accepted.`);
|
|
73
|
+
}
|
|
74
|
+
const fits = target === "string"
|
|
75
|
+
? data.check === "string_format" ||
|
|
76
|
+
data.check === "length_equals" ||
|
|
77
|
+
((data.check === "max_length" || data.check === "min_length") &&
|
|
78
|
+
data.list !== true)
|
|
79
|
+
: target === "number"
|
|
80
|
+
? (data.check === "less_than" ||
|
|
81
|
+
data.check === "greater_than" ||
|
|
82
|
+
data.check === "multiple_of") &&
|
|
83
|
+
typeof data.value === "number"
|
|
84
|
+
: (data.check === "max_length" || data.check === "min_length") &&
|
|
85
|
+
data.list === true;
|
|
86
|
+
if (!fits) {
|
|
87
|
+
throw new TypeError(`AvZ.${kind}(…).check: the check "${data.check}"${"format" in data ? ` (${data.format})` : ""} does not apply to ${kind === "array" ? "an array's length; an array takes AvZ.minItems and AvZ.maxItems" : `a${kind === "int" ? "n" : ""} ${kind} shape`}.`);
|
|
88
|
+
}
|
|
89
|
+
return data;
|
|
90
|
+
}
|
|
91
|
+
function zodChecks(checks, subject) {
|
|
92
|
+
return (payload) => {
|
|
93
|
+
for (const check of checks) {
|
|
94
|
+
if (passesFieldCheck(check, payload.value, subject)) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const issue = fieldCheckIssue(check, subject, []);
|
|
98
|
+
payload.issues.push({
|
|
99
|
+
code: "custom",
|
|
100
|
+
message: issue.message,
|
|
101
|
+
input: payload.value,
|
|
102
|
+
path: [],
|
|
103
|
+
params: { [AVZ_CHECK_ISSUE]: issue },
|
|
104
|
+
continue: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function addChecks(...added) {
|
|
110
|
+
const part = compiledOf("check", this);
|
|
111
|
+
const kind = part.node.kind;
|
|
112
|
+
const checkable = CHECKABLE[kind];
|
|
113
|
+
if (added.length === 0) {
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
if (checkable === undefined) {
|
|
117
|
+
throw new TypeError(`AvZ.${kind}(…).check: only a string, number, int or array shape takes checks.`);
|
|
118
|
+
}
|
|
119
|
+
const all = [
|
|
120
|
+
...part.checks,
|
|
121
|
+
...added.map((check) => shapeCheck(kind, checkable.target, check)),
|
|
122
|
+
];
|
|
123
|
+
return build(part.node, part.unchecked.check(zodChecks(all, checkable.subject)), { ...part.schema, checks: all }, part.optionalKey, { unchecked: part.unchecked, checks: all });
|
|
124
|
+
}
|
|
125
|
+
const SHAPE_PROTOTYPE = Object.freeze(Object.assign(Object.create(null), { check: addChecks }));
|
|
38
126
|
function deepFreeze(value) {
|
|
39
127
|
if (typeof value === "object" && value !== null) {
|
|
40
128
|
for (const child of Object.values(value)) {
|
|
@@ -74,6 +162,10 @@ const enumShape = (values) => {
|
|
|
74
162
|
enum: copy,
|
|
75
163
|
});
|
|
76
164
|
};
|
|
165
|
+
function contractKeyOrder(keys) {
|
|
166
|
+
const sorted = [...keys].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
|
|
167
|
+
return Object.keys(Object.fromEntries(sorted.map((key) => [key, true])));
|
|
168
|
+
}
|
|
77
169
|
const object = (fields) => {
|
|
78
170
|
if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
|
|
79
171
|
throw new TypeError("AvZ.object: the fields must be an object of shapes.");
|
|
@@ -85,12 +177,14 @@ const object = (fields) => {
|
|
|
85
177
|
for (const key of Object.keys(fields)) {
|
|
86
178
|
const part = compiledOf("object", fields[key]);
|
|
87
179
|
nodes[key] = part.node;
|
|
88
|
-
zods[key] = part.zod;
|
|
89
180
|
properties[key] = part.schema;
|
|
90
181
|
if (!part.optionalKey) {
|
|
91
182
|
required.push(key);
|
|
92
183
|
}
|
|
93
184
|
}
|
|
185
|
+
for (const key of contractKeyOrder(Object.keys(fields))) {
|
|
186
|
+
zods[key] = compiledOf("object", fields[key]).zod;
|
|
187
|
+
}
|
|
94
188
|
return build({ kind: "object", fields: nodes }, z.strictObject(zods), {
|
|
95
189
|
type: "object",
|
|
96
190
|
properties,
|
|
@@ -140,7 +234,9 @@ const record = (key, value) => {
|
|
|
140
234
|
required: [...keys],
|
|
141
235
|
additionalProperties: false,
|
|
142
236
|
};
|
|
143
|
-
return build({ kind: "record", value: valuePart.node }, z.record(
|
|
237
|
+
return build({ kind: "record", value: valuePart.node }, z.record(keyNode.kind === "enum"
|
|
238
|
+
? z.enum(contractKeyOrder(keyNode.values))
|
|
239
|
+
: keyPart.zod, valuePart.zod), schema);
|
|
144
240
|
};
|
|
145
241
|
const union = (options) => {
|
|
146
242
|
if (!Array.isArray(options) || options.length < 2) {
|
|
@@ -209,4 +305,50 @@ export class AvZ {
|
|
|
209
305
|
static discriminatedUnion = discriminatedUnion;
|
|
210
306
|
static optional = optional;
|
|
211
307
|
static nullable = nullable;
|
|
308
|
+
static lt = checks.lt;
|
|
309
|
+
static lte = checks.lte;
|
|
310
|
+
static gt = checks.gt;
|
|
311
|
+
static gte = checks.gte;
|
|
312
|
+
static positive = checks.positive;
|
|
313
|
+
static nonnegative = checks.nonnegative;
|
|
314
|
+
static negative = checks.negative;
|
|
315
|
+
static nonpositive = checks.nonpositive;
|
|
316
|
+
static multipleOf = checks.multipleOf;
|
|
317
|
+
static maxLength = checks.maxLength;
|
|
318
|
+
static minLength = checks.minLength;
|
|
319
|
+
static length = checks.length;
|
|
320
|
+
static maxItems = checks.maxItems;
|
|
321
|
+
static minItems = checks.minItems;
|
|
322
|
+
static maxSize = checks.maxSize;
|
|
323
|
+
static minSize = checks.minSize;
|
|
324
|
+
static size = checks.size;
|
|
325
|
+
static regex = checks.regex;
|
|
326
|
+
static includes = checks.includes;
|
|
327
|
+
static startsWith = checks.startsWith;
|
|
328
|
+
static endsWith = checks.endsWith;
|
|
329
|
+
static lowercase = checks.lowercase;
|
|
330
|
+
static uppercase = checks.uppercase;
|
|
331
|
+
static email = checks.email;
|
|
332
|
+
static url = checks.url;
|
|
333
|
+
static emoji = checks.emoji;
|
|
334
|
+
static uuid = checks.uuid;
|
|
335
|
+
static guid = checks.guid;
|
|
336
|
+
static nanoid = checks.nanoid;
|
|
337
|
+
static cuid = checks.cuid;
|
|
338
|
+
static cuid2 = checks.cuid2;
|
|
339
|
+
static ulid = checks.ulid;
|
|
340
|
+
static xid = checks.xid;
|
|
341
|
+
static ksuid = checks.ksuid;
|
|
342
|
+
static ipv4 = checks.ipv4;
|
|
343
|
+
static ipv6 = checks.ipv6;
|
|
344
|
+
static cidrv4 = checks.cidrv4;
|
|
345
|
+
static cidrv6 = checks.cidrv6;
|
|
346
|
+
static base64 = checks.base64;
|
|
347
|
+
static base64url = checks.base64url;
|
|
348
|
+
static jsonString = checks.jsonString;
|
|
349
|
+
static e164 = checks.e164;
|
|
350
|
+
static creditCard = checks.creditCard;
|
|
351
|
+
static iban = checks.iban;
|
|
352
|
+
static jwt = checks.jwt;
|
|
353
|
+
static iso = checks.iso;
|
|
212
354
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@aventara/core/
|
|
2
|
+
* `@aventara/core/avz` — `AvZ`, which builds the TypeScript shape of a Json
|
|
3
3
|
* field, and the types of the shapes it builds.
|
|
4
4
|
*/
|
|
5
|
+
export type { ShapedJsonSchema as AvZShapedSchema } from "../contracts/json-shape.js";
|
|
5
6
|
export type { AvZNullable, AvZObject, AvZOptional, AvZShape } from "./avz.js";
|
|
6
7
|
export { AvZ } from "./avz.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
2
|
+
import type { AvScalarField } from "../contracts/field.js";
|
|
3
3
|
import type { JsonSchema } from "../contracts/json-shape.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
5
5
|
/** What core may do with a Json Shape: read its Contract form, check a value. */
|
|
6
6
|
export type JsonShapeRuntime = {
|
|
7
7
|
/** The shape's Contract form. */
|
|
@@ -10,13 +10,13 @@ export type JsonShapeRuntime = {
|
|
|
10
10
|
* Every way `value` — a JSON value — does not conform, each at its path inside
|
|
11
11
|
* the value; none when it conforms.
|
|
12
12
|
*/
|
|
13
|
-
readonly validate: (value: unknown) => readonly
|
|
13
|
+
readonly validate: (value: unknown) => readonly AvValidationIssue[];
|
|
14
14
|
};
|
|
15
|
-
/** Records `shape` as a Json Shape. For `@aventara/core/
|
|
15
|
+
/** Records `shape` as a Json Shape. For `@aventara/core/avz` only. */
|
|
16
16
|
export declare function registerJsonShape(shape: object, runtime: JsonShapeRuntime): void;
|
|
17
17
|
/** The Json Shape `value` is, or `undefined` when `AvZ` did not build it. */
|
|
18
18
|
export declare function jsonShapeOf(value: unknown): JsonShapeRuntime | undefined;
|
|
19
19
|
/** Binds a compiled Contract field to the shape it enforces. Compiler only. */
|
|
20
|
-
export declare function bindShapedField(field:
|
|
20
|
+
export declare function bindShapedField(field: AvScalarField<AvContract>, shape: JsonShapeRuntime): void;
|
|
21
21
|
/** The shape a compiled Contract field enforces, or `undefined`. */
|
|
22
|
-
export declare function shapeOfField(field:
|
|
22
|
+
export declare function shapeOfField(field: AvScalarField<AvContract>): JsonShapeRuntime | undefined;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { JsonSchemaPrimitive } from "../contracts/json-shape.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
3
|
+
/**
|
|
4
|
+
* The key a shape node's failed check travels under in its Zod issue's `params`:
|
|
5
|
+
* the finished Aventara issue, path relative to the node (`avz.ts`).
|
|
6
|
+
*/
|
|
7
|
+
export declare const AVZ_CHECK_ISSUE = "aventara.check";
|
|
3
8
|
/** A shape as the translator reads it: its form and its parts, no Zod. */
|
|
4
9
|
export type AvZNode = {
|
|
5
10
|
readonly kind: "string" | "number" | "int" | "boolean" | "null";
|
|
@@ -42,10 +47,11 @@ type ZodIssueLike = {
|
|
|
42
47
|
readonly options?: readonly unknown[];
|
|
43
48
|
readonly minimum?: unknown;
|
|
44
49
|
readonly maximum?: unknown;
|
|
50
|
+
readonly params?: Readonly<Record<string, unknown>>;
|
|
45
51
|
};
|
|
46
52
|
/**
|
|
47
53
|
* Aventara's issues for the ones Zod raised judging `value` against the shape
|
|
48
54
|
* `root`: each at its path inside the value, in Zod's order.
|
|
49
55
|
*/
|
|
50
|
-
export declare function translateZodIssues(root: AvZNode, value: unknown, issues: readonly ZodIssueLike[]): readonly
|
|
56
|
+
export declare function translateZodIssues(root: AvZNode, value: unknown, issues: readonly ZodIssueLike[]): readonly AvValidationIssue[];
|
|
51
57
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export const AVZ_CHECK_ISSUE = "aventara.check";
|
|
1
2
|
const MISSING = Symbol("missing");
|
|
2
3
|
function issue(code, path, message) {
|
|
3
4
|
return { code, path, message };
|
|
@@ -104,6 +105,12 @@ function translateOne(root, value, zodIssue) {
|
|
|
104
105
|
return [issue("V1000", path, "Required value missing.")];
|
|
105
106
|
}
|
|
106
107
|
switch (zodIssue.code) {
|
|
108
|
+
case "custom": {
|
|
109
|
+
const checked = zodIssue.params?.[AVZ_CHECK_ISSUE];
|
|
110
|
+
return checked === undefined
|
|
111
|
+
? [issue("V1001", path, `Value does not match ${describe(node)}.`)]
|
|
112
|
+
: [{ ...checked, path: [...path, ...(checked.path ?? [])] }];
|
|
113
|
+
}
|
|
107
114
|
case "invalid_type":
|
|
108
115
|
return [issue("V1001", path, `Value must be ${describe(node)}.`)];
|
|
109
116
|
case "invalid_value":
|
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
/** Codes of {@link
|
|
2
|
-
export type
|
|
1
|
+
/** Codes of {@link AvContractCompilerDiagnostic}. */
|
|
2
|
+
export type AvContractCompilerDiagnosticCode = "COMPILER_UNKNOWN_RESOURCE" | "COMPILER_UNKNOWN_FIELD" | "COMPILER_RELATION_FIELD_CONFIG_UNSUPPORTED" | "COMPILER_INCOMPLETE_FIELD" | "COMPILER_STRUCTURAL_FIELD_OVERRIDE" | "COMPILER_MISSING_SCALAR" | "COMPILER_MISSING_ENUM" | "COMPILER_DANGLING_RELATION" | "COMPILER_UNAVAILABLE_OPERATION" | "COMPILER_UNAVAILABLE_CAPABILITY" | "COMPILER_INVALID_LIFECYCLE" | "COMPILER_MISSING_READ_COMPUTE" | "COMPILER_INVALID_COMPUTE_DEPENDENCY"
|
|
3
|
+
/**
|
|
4
|
+
* A Resource name the adapter model holds starts with `$`, which is reserved
|
|
5
|
+
* for the framework's own names (`ctx.$sql`, `$ref`, …).
|
|
6
|
+
*/
|
|
7
|
+
| "COMPILER_RESERVED_RESOURCE_NAME"
|
|
8
|
+
/**
|
|
9
|
+
* A layer exposes a unique operation variant (`find.unique`, `update.unique`,
|
|
10
|
+
* `delete.unique`, `upsert.unique`) and no complete identifier of its Resource:
|
|
11
|
+
* a Pick that did not pick one, or an Omit that hid every one.
|
|
12
|
+
*/
|
|
13
|
+
| "COMPILER_MISSING_IDENTIFIER"
|
|
14
|
+
/**
|
|
15
|
+
* A layer still creates a Resource (a create or upsert variant, or a nested
|
|
16
|
+
* create through a parent's relation) and leaves one of its create
|
|
17
|
+
* requirements unwritable on create: a required field hidden or with its
|
|
18
|
+
* `create` capability exempted and no `compute.create`, or a required relation
|
|
19
|
+
* not writable on create with a reference field neither writable nor computed.
|
|
20
|
+
*/
|
|
21
|
+
| "COMPILER_HIDDEN_REQUIRED_FIELD"
|
|
22
|
+
/**
|
|
23
|
+
* A field validator cannot apply: it is not a check built with `AvZ`, it does
|
|
24
|
+
* not fit the field's type (`AvZ.maxLength` on an `int` field, `AvZ.maxItems`
|
|
25
|
+
* on a field that is not a list), or the field is a relation or a Json field
|
|
26
|
+
* (whose checks are in its shape).
|
|
27
|
+
*/
|
|
28
|
+
| "COMPILER_INVALID_VALIDATOR"
|
|
3
29
|
/**
|
|
4
30
|
* A field's `json` shape cannot apply: the field is not a Json field the
|
|
5
31
|
* adapter discovered, the value is not a shape built with `AvZ`, or the shape
|
|
@@ -8,14 +34,14 @@ export type ContractCompilerDiagnosticCode = "COMPILER_UNKNOWN_RESOURCE" | "COMP
|
|
|
8
34
|
| "COMPILER_INVALID_JSON_SHAPE"
|
|
9
35
|
/**
|
|
10
36
|
* The finished, hashed client projection is not a structurally valid
|
|
11
|
-
* `
|
|
37
|
+
* `AvContractClient`. A framework-bug guard: the server never serves what its own
|
|
12
38
|
* generator would refuse. `path` is the JSONPath inside the ClientContract
|
|
13
39
|
* (`$.enums.status.values[1]`).
|
|
14
40
|
*/
|
|
15
41
|
| "COMPILER_INVALID_CLIENT_CONTRACT";
|
|
16
42
|
/** One reason a configuration could not be compiled into Contracts. */
|
|
17
|
-
export type
|
|
18
|
-
readonly code:
|
|
43
|
+
export type AvContractCompilerDiagnostic = {
|
|
44
|
+
readonly code: AvContractCompilerDiagnosticCode;
|
|
19
45
|
readonly path: string;
|
|
20
46
|
readonly message: string;
|
|
21
47
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ErrorCodeDescription } from "../runtime/error-guidance.js";
|
|
2
|
+
import type { AvContractCompilerDiagnosticCode } from "./contract-compiler-diagnostic.js";
|
|
3
|
+
/** Meaning, cause and fix of every contract-compilation diagnostic code. */
|
|
4
|
+
export declare const CONTRACT_COMPILER_DIAGNOSTIC_GUIDANCE: {
|
|
5
|
+
readonly [C in AvContractCompilerDiagnosticCode]: ErrorCodeDescription;
|
|
6
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export const CONTRACT_COMPILER_DIAGNOSTIC_GUIDANCE = {
|
|
2
|
+
COMPILER_UNKNOWN_RESOURCE: {
|
|
3
|
+
message: "Unknown Resource.",
|
|
4
|
+
cause: "A Resource name the adapter's model does not have, in resources or in exemptions.",
|
|
5
|
+
fix: "Use the model's exact name. After a schema change run `npm run aventara:prepare`.",
|
|
6
|
+
},
|
|
7
|
+
COMPILER_UNKNOWN_FIELD: {
|
|
8
|
+
message: "Unknown field.",
|
|
9
|
+
cause: "A field that is neither in the schema nor defined at the root.",
|
|
10
|
+
fix: "Fix the name, run aventara:prepare after a schema change, or add the field with a root definition.",
|
|
11
|
+
},
|
|
12
|
+
COMPILER_RELATION_FIELD_CONFIG_UNSUPPORTED: {
|
|
13
|
+
message: "A relation field takes write guards only.",
|
|
14
|
+
cause: "Field pipes or compute on a relation field.",
|
|
15
|
+
fix: "Put the stage on the relation's reference field, or use an operation pipe.",
|
|
16
|
+
},
|
|
17
|
+
COMPILER_INCOMPLETE_FIELD: {
|
|
18
|
+
message: "An added field is incomplete.",
|
|
19
|
+
cause: "A definition that adds a field leaves out type, nullable or list.",
|
|
20
|
+
fix: 'Spell out type, nullable and list, with lifecycle: ["VIRTUAL"] for a field that has no column.',
|
|
21
|
+
},
|
|
22
|
+
COMPILER_STRUCTURAL_FIELD_OVERRIDE: {
|
|
23
|
+
message: "A discovered field's structure was redefined.",
|
|
24
|
+
cause: "A definition on a field the adapter discovered changes its type, format or capabilities.",
|
|
25
|
+
fix: "Restate only its type, nullable and list. Change capabilities through exemptions and the column through the schema.",
|
|
26
|
+
},
|
|
27
|
+
COMPILER_MISSING_SCALAR: {
|
|
28
|
+
message: "Unknown scalar type.",
|
|
29
|
+
cause: "A definition names a scalar type that does not exist.",
|
|
30
|
+
fix: "Use a built-in scalar: string, boolean, int, float, bigint, decimal, datetime, bytes or json.",
|
|
31
|
+
},
|
|
32
|
+
COMPILER_MISSING_ENUM: {
|
|
33
|
+
message: "Unknown enum.",
|
|
34
|
+
cause: "A definition names an enum the model does not have.",
|
|
35
|
+
fix: "Use an enum of the schema, and run aventara:prepare after adding one.",
|
|
36
|
+
},
|
|
37
|
+
COMPILER_DANGLING_RELATION: {
|
|
38
|
+
message: "A visible relation points at a hidden Resource.",
|
|
39
|
+
cause: "A layer hides a Resource but still exposes a relation field that targets it.",
|
|
40
|
+
fix: "Hide the relation field too (`exemptions.resources.<R>.fields.<relation>: true`), or expose the target.",
|
|
41
|
+
},
|
|
42
|
+
COMPILER_UNAVAILABLE_OPERATION: {
|
|
43
|
+
message: "Operation not available.",
|
|
44
|
+
cause: "An operation the adapter does not offer (such as delete.many), or an overlay granting one that its parent hid.",
|
|
45
|
+
fix: "Remove it. To reach an operation from one overlay only, expose it at the root and hide it in the other overlay.",
|
|
46
|
+
},
|
|
47
|
+
COMPILER_UNAVAILABLE_CAPABILITY: {
|
|
48
|
+
message: "Capability not available.",
|
|
49
|
+
cause: "A capability or token the field does not offer, or an overlay (or the agent layer) granting one its parent hid. Overlays only narrow.",
|
|
50
|
+
fix: "Remove it, or expose it in the parent layer and hide it in the layer it must not reach.",
|
|
51
|
+
},
|
|
52
|
+
COMPILER_INVALID_LIFECYCLE: {
|
|
53
|
+
message: "Invalid field lifecycle.",
|
|
54
|
+
cause: "An added field declares a lifecycle other than VIRTUAL, a VIRTUAL field claims a database-generated lifecycle or a provider-side capability, or a definition redefines a discovered field's lifecycle.",
|
|
55
|
+
fix: 'Give an added field lifecycle: ["VIRTUAL"] and only the capabilities it can serve; computed lifecycles come from compute stages.',
|
|
56
|
+
},
|
|
57
|
+
COMPILER_MISSING_READ_COMPUTE: {
|
|
58
|
+
message: "A selectable virtual field has no compute.read.",
|
|
59
|
+
cause: "A VIRTUAL field that can be selected has no pipelines.compute.read stage.",
|
|
60
|
+
fix: "Add a compute.read stage, or make the field write-only with capabilities.select: false.",
|
|
61
|
+
},
|
|
62
|
+
COMPILER_INVALID_COMPUTE_DEPENDENCY: {
|
|
63
|
+
message: "Invalid compute.read dependency.",
|
|
64
|
+
cause: "A dependsOn entry that is not a stored scalar field of the same Resource.",
|
|
65
|
+
fix: "List only stored scalar fields of the Resource in dependsOn.",
|
|
66
|
+
},
|
|
67
|
+
COMPILER_RESERVED_RESOURCE_NAME: {
|
|
68
|
+
message: "Reserved Resource name.",
|
|
69
|
+
cause: "A model name starts with $, which is reserved for the framework's own names (ctx.$sql, $ref).",
|
|
70
|
+
fix: "Rename the model; the table it maps to can keep its name.",
|
|
71
|
+
},
|
|
72
|
+
COMPILER_MISSING_IDENTIFIER: {
|
|
73
|
+
message: "A unique operation has no identifier.",
|
|
74
|
+
cause: "A layer exposes a unique variant (find.unique, update.unique, delete.unique, upsert.unique) and no complete identifier of the Resource: a Pick that did not pick one, or an Omit that hid every one.",
|
|
75
|
+
fix: "Expose an identifier field (id, or every field of one unique), or exempt the unique variants.",
|
|
76
|
+
},
|
|
77
|
+
COMPILER_HIDDEN_REQUIRED_FIELD: {
|
|
78
|
+
message: "A layer that creates a Resource hides a required field.",
|
|
79
|
+
cause: "A layer still creates the Resource (a create or upsert variant, or a nested create) while a required field, or a required relation's reference field, is hidden or has its create capability exempted, and no compute.create fills it.",
|
|
80
|
+
fix: "Expose the field, give it a compute.create stage, or exempt the layer's create operations.",
|
|
81
|
+
},
|
|
82
|
+
COMPILER_INVALID_VALIDATOR: {
|
|
83
|
+
message: "A field validator cannot apply.",
|
|
84
|
+
cause: "A validator that is not built with AvZ, does not fit the field's type (AvZ.maxLength on an int, AvZ.maxItems on a field that is not a list), or sits on a relation or Json field.",
|
|
85
|
+
fix: "Use an AvZ check that fits the field's type; a Json field's checks go in its json shape.",
|
|
86
|
+
},
|
|
87
|
+
COMPILER_INVALID_JSON_SHAPE: {
|
|
88
|
+
message: "A Json shape cannot apply.",
|
|
89
|
+
cause: "A json shape on a field that is not a discovered Json field, a shape not built with AvZ, or one that admits null or absence at its top level.",
|
|
90
|
+
fix: "Put the shape on a Json field, build it with AvZ, and keep its top level non-null (the column's nullability decides null).",
|
|
91
|
+
},
|
|
92
|
+
COMPILER_INVALID_CLIENT_CONTRACT: {
|
|
93
|
+
message: "The compiled client contract is invalid.",
|
|
94
|
+
cause: "The finished client contract failed its own structural check: a framework defect.",
|
|
95
|
+
fix: "Report it with the diagnostic's path and message.",
|
|
96
|
+
},
|
|
97
|
+
};
|