@aventara/core 0.1.0-pilot.4 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/CHANGELOG.md +1478 -0
  2. package/README.md +275 -11
  3. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  4. package/dist/adapters/adapter-field.d.ts +11 -11
  5. package/dist/adapters/adapter-identifier.d.ts +6 -6
  6. package/dist/adapters/adapter-model.d.ts +17 -9
  7. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  8. package/dist/adapters/adapter-operation.d.ts +3 -3
  9. package/dist/adapters/adapter-resource.d.ts +18 -9
  10. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  11. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  12. package/dist/adapters/adapter.interface.d.ts +49 -25
  13. package/dist/avz/avz-check.factory.d.ts +83 -0
  14. package/dist/avz/avz-check.factory.js +116 -0
  15. package/dist/avz/avz-check.registry.d.ts +35 -0
  16. package/dist/avz/avz-check.registry.js +9 -0
  17. package/dist/avz/avz.d.ts +203 -0
  18. package/dist/avz/avz.js +354 -0
  19. package/dist/avz/index.d.ts +7 -0
  20. package/dist/avz/index.js +1 -0
  21. package/dist/avz/json-shape.registry.d.ts +22 -0
  22. package/dist/avz/json-shape.registry.js +16 -0
  23. package/dist/avz/zod-issue.translator.d.ts +57 -0
  24. package/dist/avz/zod-issue.translator.js +149 -0
  25. package/dist/compiler/contract-compiler-diagnostic.d.ts +37 -5
  26. package/dist/compiler/contract.compiler.d.ts +18 -18
  27. package/dist/compiler/contract.compiler.js +595 -421
  28. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  29. package/dist/compiler/create-requirements.projector.js +423 -0
  30. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  31. package/dist/compiler/field-validator.compiler.js +238 -0
  32. package/dist/config/any-framework-config.d.ts +19 -12
  33. package/dist/config/config-diagnostic.d.ts +11 -4
  34. package/dist/config/config-layer.d.ts +15 -6
  35. package/dist/config/config.resolver.d.ts +75 -29
  36. package/dist/config/config.resolver.js +109 -44
  37. package/dist/config/config.validator.d.ts +7 -7
  38. package/dist/config/config.validator.js +586 -71
  39. package/dist/config/define-resource.d.ts +57 -0
  40. package/dist/config/define-resource.js +14 -0
  41. package/dist/config/effective-fields.d.ts +19 -23
  42. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  43. package/dist/config/exact-framework-config.d.ts +280 -0
  44. package/dist/config/field-compute.resolver.d.ts +19 -0
  45. package/dist/config/field-compute.resolver.js +115 -0
  46. package/dist/config/field-pipeline-config.d.ts +47 -0
  47. package/dist/config/forced-operation.validator.d.ts +10 -0
  48. package/dist/config/forced-operation.validator.js +66 -0
  49. package/dist/config/framework-config.d.ts +111 -37
  50. package/dist/config/framework-exemptions-config.d.ts +91 -0
  51. package/dist/config/framework-exemptions-config.js +1 -0
  52. package/dist/config/framework-field-definition.d.ts +78 -0
  53. package/dist/config/framework-field-definition.js +28 -0
  54. package/dist/config/framework-resources-config.d.ts +116 -0
  55. package/dist/config/framework-resources-config.js +1 -0
  56. package/dist/config/pipeline-config.d.ts +56 -20
  57. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  58. package/dist/config/pipeline-tree.resolver.js +220 -0
  59. package/dist/config/stage-type.eraser.d.ts +65 -0
  60. package/dist/config/stage-type.eraser.js +1 -0
  61. package/dist/contracts/capability.d.ts +11 -11
  62. package/dist/contracts/client-contract-structure.validator.d.ts +344 -29
  63. package/dist/contracts/client-contract-structure.validator.js +248 -7
  64. package/dist/contracts/contract-canonicalizer.d.ts +19 -3
  65. package/dist/contracts/contract-canonicalizer.js +172 -27
  66. package/dist/contracts/contract-hash.d.ts +12 -7
  67. package/dist/contracts/contract-hash.js +3 -2
  68. package/dist/contracts/contract-limits.d.ts +4 -1
  69. package/dist/contracts/contract-limits.js +1 -0
  70. package/dist/contracts/contract-lookup.d.ts +5 -5
  71. package/dist/contracts/contract-protocol.d.ts +4 -4
  72. package/dist/contracts/contract.d.ts +31 -16
  73. package/dist/contracts/create-requirements.d.ts +35 -0
  74. package/dist/contracts/create-requirements.js +1 -0
  75. package/dist/contracts/enum-definition.d.ts +1 -1
  76. package/dist/contracts/field-check.d.ts +101 -0
  77. package/dist/contracts/field-check.js +1 -0
  78. package/dist/contracts/field.d.ts +61 -41
  79. package/dist/contracts/identifier.d.ts +4 -4
  80. package/dist/contracts/json-shape.d.ts +76 -0
  81. package/dist/contracts/json-shape.js +1 -0
  82. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  83. package/dist/contracts/reference-write-limit.d.ts +7 -0
  84. package/dist/contracts/reference-write-limit.js +1 -0
  85. package/dist/contracts/resource-operations.d.ts +28 -28
  86. package/dist/contracts/resource.d.ts +15 -9
  87. package/dist/contracts/scalar-value-type.d.ts +25 -14
  88. package/dist/contracts/scalar.d.ts +3 -3
  89. package/dist/contracts/transaction-capability.d.ts +1 -1
  90. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  91. package/dist/framework/contract-view.d.ts +234 -63
  92. package/dist/framework/framework-construction.error.d.ts +10 -10
  93. package/dist/framework/framework-construction.error.js +2 -2
  94. package/dist/framework/framework.d.ts +50 -24
  95. package/dist/framework/framework.factory.d.ts +8 -6
  96. package/dist/framework/framework.factory.js +95 -32
  97. package/dist/framework/operation-facade.d.ts +123 -52
  98. package/dist/framework/operation-facade.js +9 -1
  99. package/dist/index.d.ts +55 -82
  100. package/dist/index.js +6 -26
  101. package/dist/internal.d.ts +40 -0
  102. package/dist/internal.js +18 -0
  103. package/dist/operations/operation-arguments.d.ts +316 -201
  104. package/dist/operations/operation-call.d.ts +27 -28
  105. package/dist/operations/operation-identity.d.ts +12 -10
  106. package/dist/operations/operation-identity.js +3 -0
  107. package/dist/operations/operation-result.d.ts +21 -21
  108. package/dist/operations/operation-validator-core.d.ts +6 -6
  109. package/dist/operations/operation-validator-core.js +41 -12
  110. package/dist/operations/operation-validator.d.ts +24 -9
  111. package/dist/operations/operation-validator.js +26 -10
  112. package/dist/operations/projection-scope.resolver.d.ts +7 -7
  113. package/dist/operations/structural-limits.walker.d.ts +19 -0
  114. package/dist/operations/structural-limits.walker.js +489 -0
  115. package/dist/operations/validation-code.d.ts +11 -6
  116. package/dist/operations/validation-code.js +4 -0
  117. package/dist/operations/write-scope.resolver.d.ts +6 -6
  118. package/dist/protocol/absent-route.responder.d.ts +13 -11
  119. package/dist/protocol/absent-route.responder.js +42 -16
  120. package/dist/protocol/contract-document.responder.d.ts +3 -3
  121. package/dist/protocol/contract-document.responder.js +2 -2
  122. package/dist/protocol/http-request.decoder.d.ts +23 -13
  123. package/dist/protocol/http-request.decoder.js +19 -11
  124. package/dist/protocol/http-request.reader.d.ts +3 -3
  125. package/dist/protocol/http-response.encoder.d.ts +4 -4
  126. package/dist/protocol/http-response.encoder.js +94 -55
  127. package/dist/protocol/http-status.table.d.ts +2 -2
  128. package/dist/protocol/operation-response.guard.d.ts +2 -2
  129. package/dist/protocol/protocol-surface.d.ts +4 -4
  130. package/dist/protocol/protocol.binder.d.ts +52 -27
  131. package/dist/protocol/protocol.binder.js +14 -9
  132. package/dist/protocol/protocol.handler.d.ts +28 -15
  133. package/dist/protocol/protocol.handler.js +55 -10
  134. package/dist/protocol/unmounted-route.error.d.ts +19 -0
  135. package/dist/protocol/unmounted-route.error.js +10 -0
  136. package/dist/runtime/caller-data.copier.d.ts +59 -0
  137. package/dist/runtime/caller-data.copier.js +470 -0
  138. package/dist/runtime/caller-data.door.d.ts +56 -0
  139. package/dist/runtime/caller-data.door.js +67 -0
  140. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  141. package/dist/runtime/computed-read-runtime.js +61 -55
  142. package/dist/runtime/computed-value.error.d.ts +13 -0
  143. package/dist/runtime/computed-value.error.js +9 -0
  144. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  145. package/dist/runtime/context-executor.runtime.js +275 -0
  146. package/dist/runtime/create-requirement.d.ts +22 -57
  147. package/dist/runtime/create-requirement.js +140 -37
  148. package/dist/runtime/decimal.d.ts +2 -2
  149. package/dist/runtime/decimal.js +1 -1
  150. package/dist/runtime/diagnostics-reporter.d.ts +64 -22
  151. package/dist/runtime/diagnostics-reporter.js +35 -4
  152. package/dist/runtime/error-boundary.d.ts +73 -8
  153. package/dist/runtime/error-boundary.js +104 -48
  154. package/dist/runtime/execution-options.d.ts +10 -2
  155. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  156. package/dist/runtime/field-check.evaluator.js +521 -0
  157. package/dist/runtime/field-compute.d.ts +64 -0
  158. package/dist/runtime/field-compute.js +1 -0
  159. package/dist/runtime/field-stage.plan.d.ts +15 -0
  160. package/dist/runtime/field-stage.plan.js +27 -0
  161. package/dist/runtime/field-stage.runtime.d.ts +35 -0
  162. package/dist/runtime/field-stage.runtime.js +143 -0
  163. package/dist/runtime/field-validator.runtime.d.ts +11 -0
  164. package/dist/runtime/field-validator.runtime.js +87 -0
  165. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  166. package/dist/runtime/framework-error-class.table.js +25 -0
  167. package/dist/runtime/framework-error.d.ts +79 -7
  168. package/dist/runtime/framework-error.factory.d.ts +4 -0
  169. package/dist/runtime/framework-error.factory.js +15 -0
  170. package/dist/runtime/framework-error.js +23 -2
  171. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  172. package/dist/runtime/interceptor-next.error.js +6 -0
  173. package/dist/runtime/json-value.d.ts +3 -3
  174. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  175. package/dist/runtime/level-lifecycle.runtime.js +42 -0
  176. package/dist/runtime/misuse-reporter.d.ts +32 -0
  177. package/dist/runtime/misuse-reporter.js +19 -0
  178. package/dist/runtime/mutation-planner.d.ts +19 -10
  179. package/dist/runtime/mutation-planner.js +62 -36
  180. package/dist/runtime/nested-write.walker.d.ts +32 -0
  181. package/dist/runtime/nested-write.walker.js +73 -0
  182. package/dist/runtime/operation-request.d.ts +35 -15
  183. package/dist/runtime/operation-response.d.ts +17 -17
  184. package/dist/runtime/operation-runtime.d.ts +125 -30
  185. package/dist/runtime/operation-runtime.js +423 -83
  186. package/dist/runtime/outcome-mapper.d.ts +16 -5
  187. package/dist/runtime/outcome-mapper.js +35 -8
  188. package/dist/runtime/output-validator.d.ts +16 -6
  189. package/dist/runtime/output-validator.js +12 -1
  190. package/dist/runtime/owned-execution.registry.d.ts +13 -0
  191. package/dist/runtime/owned-execution.registry.js +7 -0
  192. package/dist/runtime/pipe-output.validator.d.ts +33 -18
  193. package/dist/runtime/pipe-output.validator.js +12 -12
  194. package/dist/runtime/pipeline.d.ts +202 -28
  195. package/dist/runtime/readonly-value.d.ts +32 -0
  196. package/dist/runtime/readonly-value.js +141 -0
  197. package/dist/runtime/referential-action.d.ts +7 -0
  198. package/dist/runtime/request-envelope.validator.d.ts +5 -0
  199. package/dist/runtime/request-envelope.validator.js +123 -0
  200. package/dist/runtime/request-id.d.ts +1 -1
  201. package/dist/runtime/request-state.d.ts +14 -0
  202. package/dist/runtime/request-state.js +1 -0
  203. package/dist/runtime/request-state.resolver.d.ts +12 -0
  204. package/dist/runtime/request-state.resolver.js +20 -0
  205. package/dist/runtime/scalar-runtime.d.ts +56 -13
  206. package/dist/runtime/scalar-runtime.js +167 -86
  207. package/dist/transactions/deferred-operation.d.ts +35 -20
  208. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  209. package/dist/transactions/operation-arguments-encoder.js +2 -2
  210. package/dist/transactions/sql-statement.d.ts +77 -0
  211. package/dist/transactions/sql-statement.js +47 -0
  212. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  213. package/dist/transactions/sql-statement.validator.js +134 -0
  214. package/dist/transactions/transaction-envelope.d.ts +4 -4
  215. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  216. package/dist/transactions/transaction-integrity-error.js +5 -2
  217. package/dist/transactions/transaction-plan-assembler.d.ts +23 -9
  218. package/dist/transactions/transaction-plan-assembler.js +195 -82
  219. package/dist/transactions/transaction-plan-validator.d.ts +53 -21
  220. package/dist/transactions/transaction-plan-validator.js +246 -163
  221. package/dist/transactions/transaction-reference-collector.d.ts +30 -0
  222. package/dist/transactions/transaction-reference-collector.js +204 -0
  223. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  224. package/dist/transactions/transaction-reference-resolver.js +27 -10
  225. package/dist/transactions/transaction-reference-validator.d.ts +34 -4
  226. package/dist/transactions/transaction-reference-validator.js +82 -43
  227. package/dist/transactions/transaction-reference.d.ts +30 -58
  228. package/dist/transactions/transaction-request.d.ts +20 -7
  229. package/dist/transactions/transaction-response.d.ts +12 -7
  230. package/dist/transactions/transaction-response.js +24 -1
  231. package/dist/transactions/transaction-runtime.d.ts +11 -8
  232. package/dist/transactions/transaction-runtime.js +167 -50
  233. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  234. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  235. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  236. package/dist/transactions/transaction-slot-path-error.js +2 -2
  237. package/dist/transactions/transaction-slot-writer.js +2 -2
  238. package/dist/transactions/transaction-stage.runtime.d.ts +81 -0
  239. package/dist/transactions/transaction-stage.runtime.js +123 -0
  240. package/package.json +18 -3
  241. package/src/runtime/field-check.evaluator.ts +720 -0
  242. package/dist/config/define-fields.d.ts +0 -35
  243. package/dist/config/define-fields.js +0 -3
  244. package/dist/config/framework-behaviors-config.d.ts +0 -30
  245. package/dist/config/framework-fields-config.d.ts +0 -36
  246. package/dist/config/framework-restrictions-config.d.ts +0 -142
  247. package/dist/operations/operation-boolean-nodes.d.ts +0 -11
  248. package/dist/operations/operation-boolean-nodes.js +0 -283
  249. package/dist/operations/operation-nesting.d.ts +0 -8
  250. package/dist/operations/operation-nesting.js +0 -307
  251. package/dist/runtime/field-behavior.d.ts +0 -48
  252. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  253. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  254. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  255. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -0,0 +1,354 @@
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";
5
+ import { registerJsonShape } from "./json-shape.registry.js";
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
+ };
24
+ const compiled = new WeakMap();
25
+ function compiledOf(builder, value) {
26
+ const found = typeof value === "object" && value !== null
27
+ ? compiled.get(value)
28
+ : undefined;
29
+ if (found === undefined) {
30
+ throw new TypeError(`AvZ.${builder}: every part of a shape must be built with AvZ (a Zod schema or any other value is not accepted).`);
31
+ }
32
+ return found;
33
+ }
34
+ function requiredPart(builder, value) {
35
+ const part = compiledOf(builder, value);
36
+ if (part.optionalKey) {
37
+ throw new TypeError(`AvZ.${builder}: AvZ.optional marks an object key that may be left out; use it only for a field of AvZ.object.`);
38
+ }
39
+ return part;
40
+ }
41
+ function build(node, zod, schema, optionalKey = false, checked) {
42
+ const shape = Object.freeze(Object.assign(Object.create(SHAPE_PROTOTYPE), { kind: node.kind }));
43
+ const frozenSchema = deepFreeze(schema);
44
+ compiled.set(shape, {
45
+ node,
46
+ zod,
47
+ schema: frozenSchema,
48
+ optionalKey,
49
+ unchecked: checked?.unchecked ?? zod,
50
+ checks: checked?.checks ?? [],
51
+ });
52
+ registerJsonShape(shape, {
53
+ schema: frozenSchema,
54
+ validate: (value) => {
55
+ const result = zod.safeParse(value);
56
+ return result.success
57
+ ? []
58
+ : translateZodIssues(node, value, result.error.issues);
59
+ },
60
+ });
61
+ return shape;
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 }));
126
+ function deepFreeze(value) {
127
+ if (typeof value === "object" && value !== null) {
128
+ for (const child of Object.values(value)) {
129
+ deepFreeze(child);
130
+ }
131
+ Object.freeze(value);
132
+ }
133
+ return value;
134
+ }
135
+ function isLiteralValue(value) {
136
+ return (value === null ||
137
+ typeof value === "string" ||
138
+ typeof value === "boolean" ||
139
+ (typeof value === "number" && Number.isFinite(value)));
140
+ }
141
+ const string = () => build({ kind: "string" }, z.string(), { type: "string" });
142
+ const number = () => build({ kind: "number" }, z.number(), { type: "number" });
143
+ const int = () => build({ kind: "int" }, z.int(), { type: "integer" });
144
+ const boolean = () => build({ kind: "boolean" }, z.boolean(), { type: "boolean" });
145
+ const nullShape = () => build({ kind: "null" }, z.null(), { type: "null" });
146
+ const literal = (value) => {
147
+ if (!isLiteralValue(value)) {
148
+ throw new TypeError("AvZ.literal: the value must be a string, a finite number, a boolean or null.");
149
+ }
150
+ return build({ kind: "literal", value }, z.literal(value), { const: value });
151
+ };
152
+ const enumShape = (values) => {
153
+ if (!Array.isArray(values) ||
154
+ values.length === 0 ||
155
+ values.some((value) => typeof value !== "string") ||
156
+ new Set(values).size !== values.length) {
157
+ throw new TypeError("AvZ.enum: the values must be a non-empty list of distinct strings.");
158
+ }
159
+ const copy = [...values];
160
+ return build({ kind: "enum", values: copy }, z.enum(copy), {
161
+ type: "string",
162
+ enum: copy,
163
+ });
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
+ }
169
+ const object = (fields) => {
170
+ if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
171
+ throw new TypeError("AvZ.object: the fields must be an object of shapes.");
172
+ }
173
+ const nodes = {};
174
+ const zods = {};
175
+ const properties = {};
176
+ const required = [];
177
+ for (const key of Object.keys(fields)) {
178
+ const part = compiledOf("object", fields[key]);
179
+ nodes[key] = part.node;
180
+ properties[key] = part.schema;
181
+ if (!part.optionalKey) {
182
+ required.push(key);
183
+ }
184
+ }
185
+ for (const key of contractKeyOrder(Object.keys(fields))) {
186
+ zods[key] = compiledOf("object", fields[key]).zod;
187
+ }
188
+ return build({ kind: "object", fields: nodes }, z.strictObject(zods), {
189
+ type: "object",
190
+ properties,
191
+ ...(required.length > 0 ? { required } : {}),
192
+ additionalProperties: false,
193
+ });
194
+ };
195
+ const array = (item) => {
196
+ const part = requiredPart("array", item);
197
+ return build({ kind: "array", item: part.node }, z.array(part.zod), {
198
+ type: "array",
199
+ items: part.schema,
200
+ });
201
+ };
202
+ const tuple = (items) => {
203
+ if (!Array.isArray(items) || items.length === 0) {
204
+ throw new TypeError("AvZ.tuple: the items must be a non-empty list of shapes.");
205
+ }
206
+ const parts = items.map((item) => requiredPart("tuple", item));
207
+ return build({ kind: "tuple", items: parts.map((part) => part.node) }, z.tuple(parts.map((part) => part.zod)), {
208
+ type: "array",
209
+ prefixItems: parts.map((part) => part.schema),
210
+ items: false,
211
+ minItems: parts.length,
212
+ maxItems: parts.length,
213
+ });
214
+ };
215
+ const record = (key, value) => {
216
+ const keyPart = requiredPart("record", key);
217
+ const valuePart = requiredPart("record", value);
218
+ const keyNode = keyPart.node;
219
+ const keys = keyNode.kind === "enum"
220
+ ? keyNode.values
221
+ : keyNode.kind === "literal" && typeof keyNode.value === "string"
222
+ ? [keyNode.value]
223
+ : keyNode.kind === "string"
224
+ ? undefined
225
+ : null;
226
+ if (keys === null) {
227
+ throw new TypeError("AvZ.record: the key must be AvZ.string(), AvZ.enum([...]) or a string AvZ.literal(...).");
228
+ }
229
+ const schema = keys === undefined
230
+ ? { type: "object", additionalProperties: valuePart.schema }
231
+ : {
232
+ type: "object",
233
+ properties: Object.fromEntries(keys.map((entry) => [entry, valuePart.schema])),
234
+ required: [...keys],
235
+ additionalProperties: false,
236
+ };
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);
240
+ };
241
+ const union = (options) => {
242
+ if (!Array.isArray(options) || options.length < 2) {
243
+ throw new TypeError("AvZ.union: the options must be a list of at least two shapes.");
244
+ }
245
+ const parts = options.map((option) => requiredPart("union", option));
246
+ return build({ kind: "union", options: parts.map((part) => part.node) }, z.union(parts.map((part) => part.zod)), {
247
+ anyOf: parts.map((part) => part.schema),
248
+ });
249
+ };
250
+ const discriminatedUnion = (discriminator, options) => {
251
+ if (typeof discriminator !== "string" ||
252
+ !Array.isArray(options) ||
253
+ options.length === 0) {
254
+ throw new TypeError("AvZ.discriminatedUnion: give the discriminator key and a non-empty list of object shapes.");
255
+ }
256
+ const parts = options.map((option) => requiredPart("discriminatedUnion", option));
257
+ const tags = new Map();
258
+ parts.forEach((part, index) => {
259
+ const tag = part.node.kind === "object" ? part.node.fields[discriminator] : undefined;
260
+ const values = tag?.kind === "literal"
261
+ ? [tag.value]
262
+ : tag?.kind === "enum"
263
+ ? tag.values
264
+ : undefined;
265
+ if (values === undefined) {
266
+ throw new TypeError(`AvZ.discriminatedUnion: option ${index} must be an AvZ.object whose "${discriminator}" is an AvZ.literal or an AvZ.enum.`);
267
+ }
268
+ for (const value of values) {
269
+ if (tags.has(value)) {
270
+ throw new TypeError(`AvZ.discriminatedUnion: options ${tags.get(value)} and ${index} both match "${discriminator}" ${JSON.stringify(value)}.`);
271
+ }
272
+ tags.set(value, index);
273
+ }
274
+ });
275
+ return build({
276
+ kind: "discriminatedUnion",
277
+ discriminator,
278
+ options: parts.map((part) => part.node),
279
+ }, z.discriminatedUnion(discriminator, parts.map((part) => part.zod)), {
280
+ oneOf: parts.map((part) => part.schema),
281
+ });
282
+ };
283
+ const optional = (inner) => {
284
+ const part = compiledOf("optional", inner);
285
+ return build({ kind: "optional", inner: part.node }, z.optional(part.zod), part.schema, true);
286
+ };
287
+ const nullable = (inner) => {
288
+ const part = compiledOf("nullable", inner);
289
+ return build({ kind: "nullable", inner: part.node }, z.nullable(part.zod), { anyOf: [part.schema, { type: "null" }] }, part.optionalKey);
290
+ };
291
+ export class AvZ {
292
+ constructor() { }
293
+ static string = string;
294
+ static number = number;
295
+ static int = int;
296
+ static boolean = boolean;
297
+ static null = nullShape;
298
+ static literal = literal;
299
+ static enum = enumShape;
300
+ static object = object;
301
+ static array = array;
302
+ static tuple = tuple;
303
+ static record = record;
304
+ static union = union;
305
+ static discriminatedUnion = discriminatedUnion;
306
+ static optional = optional;
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;
354
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `@aventara/core/avz` — `AvZ`, which builds the TypeScript shape of a Json
3
+ * field, and the types of the shapes it builds.
4
+ */
5
+ export type { ShapedJsonSchema as AvZShapedSchema } from "../contracts/json-shape.js";
6
+ export type { AvZNullable, AvZObject, AvZOptional, AvZShape } from "./avz.js";
7
+ export { AvZ } from "./avz.js";
@@ -0,0 +1 @@
1
+ export { AvZ } from "./avz.js";
@@ -0,0 +1,22 @@
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvScalarField } from "../contracts/field.js";
3
+ import type { JsonSchema } from "../contracts/json-shape.js";
4
+ import type { AvValidationIssue } from "../operations/validation-code.js";
5
+ /** What core may do with a Json Shape: read its Contract form, check a value. */
6
+ export type JsonShapeRuntime = {
7
+ /** The shape's Contract form. */
8
+ readonly schema: JsonSchema;
9
+ /**
10
+ * Every way `value` — a JSON value — does not conform, each at its path inside
11
+ * the value; none when it conforms.
12
+ */
13
+ readonly validate: (value: unknown) => readonly AvValidationIssue[];
14
+ };
15
+ /** Records `shape` as a Json Shape. For `@aventara/core/avz` only. */
16
+ export declare function registerJsonShape(shape: object, runtime: JsonShapeRuntime): void;
17
+ /** The Json Shape `value` is, or `undefined` when `AvZ` did not build it. */
18
+ export declare function jsonShapeOf(value: unknown): JsonShapeRuntime | undefined;
19
+ /** Binds a compiled Contract field to the shape it enforces. Compiler only. */
20
+ export declare function bindShapedField(field: AvScalarField<AvContract>, shape: JsonShapeRuntime): void;
21
+ /** The shape a compiled Contract field enforces, or `undefined`. */
22
+ export declare function shapeOfField(field: AvScalarField<AvContract>): JsonShapeRuntime | undefined;
@@ -0,0 +1,16 @@
1
+ const shapes = new WeakMap();
2
+ const fields = new WeakMap();
3
+ export function registerJsonShape(shape, runtime) {
4
+ shapes.set(shape, runtime);
5
+ }
6
+ export function jsonShapeOf(value) {
7
+ return typeof value === "object" && value !== null
8
+ ? shapes.get(value)
9
+ : undefined;
10
+ }
11
+ export function bindShapedField(field, shape) {
12
+ fields.set(field, shape);
13
+ }
14
+ export function shapeOfField(field) {
15
+ return fields.get(field);
16
+ }
@@ -0,0 +1,57 @@
1
+ import type { JsonSchemaPrimitive } from "../contracts/json-shape.js";
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";
8
+ /** A shape as the translator reads it: its form and its parts, no Zod. */
9
+ export type AvZNode = {
10
+ readonly kind: "string" | "number" | "int" | "boolean" | "null";
11
+ } | {
12
+ readonly kind: "literal";
13
+ readonly value: JsonSchemaPrimitive;
14
+ } | {
15
+ readonly kind: "enum";
16
+ readonly values: readonly string[];
17
+ } | {
18
+ readonly kind: "object";
19
+ readonly fields: Readonly<Record<string, AvZNode>>;
20
+ } | {
21
+ readonly kind: "array";
22
+ readonly item: AvZNode;
23
+ } | {
24
+ readonly kind: "tuple";
25
+ readonly items: readonly AvZNode[];
26
+ } | {
27
+ readonly kind: "record";
28
+ readonly value: AvZNode;
29
+ } | {
30
+ readonly kind: "union";
31
+ readonly options: readonly AvZNode[];
32
+ } | {
33
+ readonly kind: "discriminatedUnion";
34
+ readonly discriminator: string;
35
+ readonly options: readonly AvZNode[];
36
+ } | {
37
+ readonly kind: "optional" | "nullable";
38
+ readonly inner: AvZNode;
39
+ };
40
+ /** The members of a Zod issue this module reads. */
41
+ type ZodIssueLike = {
42
+ readonly code: string;
43
+ readonly path: readonly PropertyKey[];
44
+ readonly origin?: string;
45
+ readonly keys?: readonly string[];
46
+ readonly note?: string;
47
+ readonly options?: readonly unknown[];
48
+ readonly minimum?: unknown;
49
+ readonly maximum?: unknown;
50
+ readonly params?: Readonly<Record<string, unknown>>;
51
+ };
52
+ /**
53
+ * Aventara's issues for the ones Zod raised judging `value` against the shape
54
+ * `root`: each at its path inside the value, in Zod's order.
55
+ */
56
+ export declare function translateZodIssues(root: AvZNode, value: unknown, issues: readonly ZodIssueLike[]): readonly AvValidationIssue[];
57
+ export {};
@@ -0,0 +1,149 @@
1
+ export const AVZ_CHECK_ISSUE = "aventara.check";
2
+ const MISSING = Symbol("missing");
3
+ function issue(code, path, message) {
4
+ return { code, path, message };
5
+ }
6
+ function valueAt(root, path) {
7
+ let current = root;
8
+ for (const segment of path) {
9
+ if (typeof current !== "object" ||
10
+ current === null ||
11
+ !Object.hasOwn(current, segment)) {
12
+ return MISSING;
13
+ }
14
+ current = current[segment];
15
+ }
16
+ return current;
17
+ }
18
+ function unwrap(node) {
19
+ return node.kind === "optional" || node.kind === "nullable"
20
+ ? unwrap(node.inner)
21
+ : node;
22
+ }
23
+ function selectedOption(node, value) {
24
+ const tag = valueAt(value, [node.discriminator]);
25
+ return node.options.find((option) => {
26
+ const field = option.kind === "object" ? option.fields[node.discriminator] : undefined;
27
+ const inner = field === undefined ? undefined : unwrap(field);
28
+ return inner?.kind === "literal"
29
+ ? Object.is(inner.value, tag)
30
+ : inner?.kind === "enum" && inner.values.includes(tag);
31
+ });
32
+ }
33
+ function nodeAt(root, value, path) {
34
+ let node = root;
35
+ let current = value;
36
+ for (const segment of path) {
37
+ node = node === undefined ? undefined : unwrap(node);
38
+ if (node?.kind === "discriminatedUnion") {
39
+ node = selectedOption(node, current);
40
+ }
41
+ switch (node?.kind) {
42
+ case "object":
43
+ node = node.fields[segment];
44
+ break;
45
+ case "array":
46
+ node = node.item;
47
+ break;
48
+ case "tuple":
49
+ node = typeof segment === "number" ? node.items[segment] : undefined;
50
+ break;
51
+ case "record":
52
+ node = node.value;
53
+ break;
54
+ default:
55
+ return undefined;
56
+ }
57
+ current = valueAt(current, [segment]);
58
+ }
59
+ return node;
60
+ }
61
+ function describe(node) {
62
+ if (node === undefined) {
63
+ return "the field's shape";
64
+ }
65
+ switch (node.kind) {
66
+ case "string":
67
+ return "a string";
68
+ case "number":
69
+ return "a number";
70
+ case "int":
71
+ return "an integer";
72
+ case "boolean":
73
+ return "a boolean";
74
+ case "null":
75
+ return "null";
76
+ case "literal":
77
+ return JSON.stringify(node.value);
78
+ case "enum":
79
+ return `one of ${node.values.map((value) => JSON.stringify(value)).join(", ")}`;
80
+ case "object":
81
+ case "record":
82
+ return "an object";
83
+ case "array":
84
+ return "a list";
85
+ case "tuple":
86
+ return `a list of exactly ${node.items.length} entries`;
87
+ case "union":
88
+ case "discriminatedUnion":
89
+ return [...new Set(node.options.map(describe))].join(" or ");
90
+ case "optional":
91
+ return describe(node.inner);
92
+ case "nullable":
93
+ return `${describe(node.inner)} or null`;
94
+ }
95
+ }
96
+ function pathOf(path) {
97
+ return path.map((segment) => typeof segment === "symbol" ? String(segment) : segment);
98
+ }
99
+ function translateOne(root, value, zodIssue) {
100
+ const path = pathOf(zodIssue.path);
101
+ const node = nodeAt(root, value, path);
102
+ const absent = path.length > 0 && valueAt(value, path) === MISSING;
103
+ if (absent &&
104
+ (zodIssue.code === "invalid_type" || zodIssue.code === "invalid_value")) {
105
+ return [issue("V1000", path, "Required value missing.")];
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
+ }
114
+ case "invalid_type":
115
+ return [issue("V1001", path, `Value must be ${describe(node)}.`)];
116
+ case "invalid_value":
117
+ return [issue("V1002", path, `Value must be ${describe(node)}.`)];
118
+ case "unrecognized_keys":
119
+ return (zodIssue.keys ?? []).map((key) => issue("V1005", [...path, key], "Key is not part of the shape."));
120
+ case "invalid_union": {
121
+ if (zodIssue.note !== undefined && Array.isArray(zodIssue.options)) {
122
+ if (absent) {
123
+ return [issue("V1000", path, "Required value missing.")];
124
+ }
125
+ const allowed = zodIssue.options
126
+ .map((option) => JSON.stringify(option))
127
+ .join(", ");
128
+ return [issue("V1002", path, `Value must be one of ${allowed}.`)];
129
+ }
130
+ return [issue("V1001", path, `Value must be ${describe(node)}.`)];
131
+ }
132
+ case "too_big":
133
+ case "too_small":
134
+ if (zodIssue.origin === "array" && node !== undefined) {
135
+ return [issue("V1001", path, `Value must be ${describe(node)}.`)];
136
+ }
137
+ if (zodIssue.origin === "int" || zodIssue.origin === "number") {
138
+ return [
139
+ issue("V1004", path, "Value must be a safe integer (between -9007199254740991 and 9007199254740991)."),
140
+ ];
141
+ }
142
+ return [issue("V1001", path, `Value does not match ${describe(node)}.`)];
143
+ default:
144
+ return [issue("V1001", path, `Value does not match ${describe(node)}.`)];
145
+ }
146
+ }
147
+ export function translateZodIssues(root, value, issues) {
148
+ return issues.flatMap((zodIssue) => translateOne(root, value, zodIssue));
149
+ }
@@ -1,15 +1,47 @@
1
- /** Codes of {@link ContractCompilerDiagnostic}. */
2
- export type ContractCompilerDiagnosticCode = "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_BEHAVIOR" | "COMPILER_INVALID_BEHAVIOR_DEPENDENCY"
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"
29
+ /**
30
+ * A field's `json` shape cannot apply: the field is not a Json field the
31
+ * adapter discovered, the value is not a shape built with `AvZ`, or the shape
32
+ * admits `null` or absence at its top level.
33
+ */
34
+ | "COMPILER_INVALID_JSON_SHAPE"
3
35
  /**
4
36
  * The finished, hashed client projection is not a structurally valid
5
- * `ClientContract`. A framework-bug guard: the server never serves what its own
37
+ * `AvContractClient`. A framework-bug guard: the server never serves what its own
6
38
  * generator would refuse. `path` is the JSONPath inside the ClientContract
7
39
  * (`$.enums.status.values[1]`).
8
40
  */
9
41
  | "COMPILER_INVALID_CLIENT_CONTRACT";
10
42
  /** One reason a configuration could not be compiled into Contracts. */
11
- export type ContractCompilerDiagnostic = {
12
- readonly code: ContractCompilerDiagnosticCode;
43
+ export type AvContractCompilerDiagnostic = {
44
+ readonly code: AvContractCompilerDiagnosticCode;
13
45
  readonly path: string;
14
46
  readonly message: string;
15
47
  };