@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,521 @@
1
+ export const FIELD_CHECK_SUBJECTS = {
2
+ string: "string",
3
+ int: "number",
4
+ float: "number",
5
+ bigint: "bigint",
6
+ decimal: "decimal",
7
+ datetime: "datetime",
8
+ bytes: "bytes",
9
+ };
10
+ const DATE_SOURCE = "(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))";
11
+ const HHMM = "(?:[01]\\d|2[0-3]):[0-5]\\d";
12
+ const IPV6_ALPHABET = /^[0-9a-fA-F:.]+$/;
13
+ const CREDIT_CARD = /^\d(?:[ -]?\d){11,18}$/;
14
+ const IBAN = /^[A-Z]{2}(?!00|01|99)\d{2}[A-Z0-9]{11,30}$/;
15
+ const FORMAT_PATTERNS = {
16
+ email: /^(?:[A-Za-z0-9_'+-]+\.)*[A-Za-z0-9_'+-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/,
17
+ emoji: new RegExp("^(?=[\\s\\S]*[\\p{Extended_Pictographic}\\p{Regional_Indicator}\\u20E3])[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$", "u"),
18
+ uuid: /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,
19
+ guid: /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,
20
+ nanoid: /^[a-zA-Z0-9_-]{21}$/,
21
+ cuid: /^[cC][0-9a-z]{6,}$/,
22
+ cuid2: /^[0-9a-z]+$/,
23
+ ulid: /^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/,
24
+ xid: /^[0-9a-vA-V]{20}$/,
25
+ ksuid: /^[A-Za-z0-9]{27}$/,
26
+ datetime: new RegExp(`^${DATE_SOURCE}T(?:${HHMM}:[0-5]\\d(?:\\.\\d+)?(?:Z))$`),
27
+ date: new RegExp(`^${DATE_SOURCE}$`),
28
+ time: new RegExp(`^${HHMM}(?::[0-5]\\d(?:\\.\\d+)?)?$`),
29
+ duration: /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,
30
+ ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,
31
+ cidrv4: /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,
32
+ e164: /^\+[1-9]\d{6,14}$/,
33
+ };
34
+ const platform = globalThis;
35
+ function canParseUrl(input) {
36
+ const Url = platform.URL;
37
+ if (Url === undefined) {
38
+ return false;
39
+ }
40
+ try {
41
+ if (typeof Url.canParse === "function") {
42
+ return Url.canParse(input);
43
+ }
44
+ new Url(input);
45
+ return true;
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
51
+ function decodeBase64(value) {
52
+ if (platform.atob === undefined) {
53
+ throw new TypeError("No atob is available here.");
54
+ }
55
+ return platform.atob(value);
56
+ }
57
+ function isIpv6(value) {
58
+ return IPV6_ALPHABET.test(value) && canParseUrl(`http://[${value}]`);
59
+ }
60
+ function isCidrv6(value) {
61
+ const parts = value.split("/");
62
+ if (parts.length !== 2) {
63
+ return false;
64
+ }
65
+ const [address, prefix] = parts;
66
+ const bits = Number(prefix);
67
+ return (prefix !== "" &&
68
+ `${bits}` === prefix &&
69
+ bits >= 0 &&
70
+ bits <= 128 &&
71
+ isIpv6(address));
72
+ }
73
+ function isBase64(value) {
74
+ if (value === "") {
75
+ return true;
76
+ }
77
+ if (/\s/.test(value) || value.length % 4 !== 0) {
78
+ return false;
79
+ }
80
+ try {
81
+ decodeBase64(value);
82
+ return true;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ function isBase64Url(value) {
89
+ if (!/^[A-Za-z0-9_-]*$/.test(value)) {
90
+ return false;
91
+ }
92
+ const base64 = value.replace(/[-_]/g, (char) => (char === "-" ? "+" : "/"));
93
+ return isBase64(base64.padEnd(Math.ceil(base64.length / 4) * 4, "="));
94
+ }
95
+ function isLuhn(digits) {
96
+ let length = digits.length;
97
+ let bit = 1;
98
+ let sum = 0;
99
+ while (length) {
100
+ const value = digits.charCodeAt(--length) - 48;
101
+ bit ^= 1;
102
+ sum += bit ? ([0, 2, 4, 6, 8, 1, 3, 5, 7, 9][value] ?? 0) : value;
103
+ }
104
+ return sum % 10 === 0;
105
+ }
106
+ function isIbanChecksum(iban) {
107
+ let remainder = 0;
108
+ const step = (code) => {
109
+ remainder =
110
+ (code >= 65
111
+ ? remainder * 100 + (code - 55)
112
+ : remainder * 10 + (code - 48)) % 97;
113
+ };
114
+ for (let index = 4; index < iban.length; index += 1) {
115
+ step(iban.charCodeAt(index));
116
+ }
117
+ for (let index = 0; index < 4; index += 1) {
118
+ step(iban.charCodeAt(index));
119
+ }
120
+ return remainder === 1;
121
+ }
122
+ function isJwt(token) {
123
+ try {
124
+ const parts = token.split(".");
125
+ if (parts.length !== 3 || !parts[0]) {
126
+ return false;
127
+ }
128
+ const header = JSON.parse(decodeBase64(parts[0]));
129
+ if ("typ" in header && header.typ !== "JWT") {
130
+ return false;
131
+ }
132
+ return Boolean(header.alg);
133
+ }
134
+ catch {
135
+ return false;
136
+ }
137
+ }
138
+ function isJsonString(value) {
139
+ try {
140
+ JSON.parse(value);
141
+ return true;
142
+ }
143
+ catch {
144
+ return false;
145
+ }
146
+ }
147
+ function matchesFormat(format, value) {
148
+ switch (format) {
149
+ case "url":
150
+ return canParseUrl(value.trim());
151
+ case "ipv6":
152
+ return isIpv6(value);
153
+ case "cidrv6":
154
+ return isCidrv6(value);
155
+ case "base64":
156
+ return isBase64(value);
157
+ case "base64url":
158
+ return isBase64Url(value);
159
+ case "credit_card":
160
+ return CREDIT_CARD.test(value) && isLuhn(value.replace(/[- ]/g, ""));
161
+ case "iban":
162
+ return IBAN.test(value) && isIbanChecksum(value);
163
+ case "jwt":
164
+ return isJwt(value);
165
+ case "json_string":
166
+ return isJsonString(value);
167
+ default: {
168
+ return FORMAT_PATTERNS[format]?.test(value) === true;
169
+ }
170
+ }
171
+ }
172
+ const DECIMAL = /^(-?)(\d+)(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
173
+ function decimalParts(text) {
174
+ const match = DECIMAL.exec(text);
175
+ if (match === null) {
176
+ return undefined;
177
+ }
178
+ const [, sign, whole = "", fraction = "", power = "0"] = match;
179
+ const all = `${whole}${fraction}`;
180
+ const leading = all.length - all.replace(/^0+/, "").length;
181
+ const digits = all.slice(leading).replace(/0+$/, "");
182
+ if (digits === "") {
183
+ return { negative: false, digits: "", exponent: 0 };
184
+ }
185
+ return {
186
+ negative: sign === "-",
187
+ digits,
188
+ exponent: whole.length - 1 - leading + Number(power),
189
+ };
190
+ }
191
+ function compareDecimals(a, b) {
192
+ const signOf = (parts) => parts.digits === "" ? 0 : parts.negative ? -1 : 1;
193
+ if (signOf(a) !== signOf(b)) {
194
+ return Math.sign(signOf(a) - signOf(b));
195
+ }
196
+ if (signOf(a) === 0) {
197
+ return 0;
198
+ }
199
+ let magnitude = 0;
200
+ if (a.exponent !== b.exponent) {
201
+ magnitude = a.exponent > b.exponent ? 1 : -1;
202
+ }
203
+ else {
204
+ const width = Math.max(a.digits.length, b.digits.length);
205
+ const left = a.digits.padEnd(width, "0");
206
+ const right = b.digits.padEnd(width, "0");
207
+ magnitude = left === right ? 0 : left > right ? 1 : -1;
208
+ }
209
+ return a.negative ? -magnitude : magnitude;
210
+ }
211
+ function modPow(base, power, modulus) {
212
+ let result = BigInt(1) % modulus;
213
+ let factor = base % modulus;
214
+ let remaining = power;
215
+ while (remaining > 0) {
216
+ if (remaining % 2 === 1) {
217
+ result = (result * factor) % modulus;
218
+ }
219
+ factor = (factor * factor) % modulus;
220
+ remaining = Math.floor(remaining / 2);
221
+ }
222
+ return result;
223
+ }
224
+ function isDecimalMultiple(a, b) {
225
+ if (b.digits === "") {
226
+ return false;
227
+ }
228
+ if (a.digits === "") {
229
+ return true;
230
+ }
231
+ const scaleA = a.exponent - (a.digits.length - 1);
232
+ const scaleB = b.exponent - (b.digits.length - 1);
233
+ if (!Number.isSafeInteger(scaleA) || !Number.isSafeInteger(scaleB)) {
234
+ return false;
235
+ }
236
+ const mantissaA = BigInt(a.digits);
237
+ const mantissaB = BigInt(b.digits);
238
+ if (scaleA >= scaleB) {
239
+ return (((mantissaA % mantissaB) *
240
+ modPow(BigInt(10), scaleA - scaleB, mantissaB)) %
241
+ mantissaB ===
242
+ BigInt(0));
243
+ }
244
+ return false;
245
+ }
246
+ function floatRemainder(value, step) {
247
+ const ratio = value / step;
248
+ const rounded = Math.round(ratio);
249
+ const tolerance = 4 * Number.EPSILON * Math.max(Math.abs(ratio), 1);
250
+ return Math.abs(ratio - rounded) < tolerance ? 0 : ratio - rounded;
251
+ }
252
+ function codePoints(value) {
253
+ let count = value.length;
254
+ for (let index = 0; index < value.length - 1; index += 1) {
255
+ if ((value.charCodeAt(index) & 0xfc00) === 0xd800 &&
256
+ (value.charCodeAt(index + 1) & 0xfc00) === 0xdc00) {
257
+ count -= 1;
258
+ index += 1;
259
+ }
260
+ }
261
+ return count;
262
+ }
263
+ const patterns = new WeakMap();
264
+ function patternOf(check) {
265
+ let pattern = patterns.get(check);
266
+ if (pattern === undefined) {
267
+ pattern = new RegExp(check.pattern.source, check.pattern.flags);
268
+ patterns.set(check, pattern);
269
+ }
270
+ pattern.lastIndex = 0;
271
+ return pattern;
272
+ }
273
+ function passesFormat(check, value) {
274
+ switch (check.format) {
275
+ case "regex":
276
+ return patternOf(check).test(value);
277
+ case "includes":
278
+ return value.includes(check.includes);
279
+ case "starts_with":
280
+ return value.startsWith(check.prefix);
281
+ case "ends_with":
282
+ return value.endsWith(check.suffix);
283
+ case "lowercase":
284
+ return /^[^A-Z]*$/.test(value);
285
+ case "uppercase":
286
+ return /^[^a-z]*$/.test(value);
287
+ default:
288
+ return matchesFormat(check.format, value);
289
+ }
290
+ }
291
+ function compareToBound(value, bound, subject) {
292
+ switch (subject) {
293
+ case "number":
294
+ return typeof value === "number" && typeof bound === "number"
295
+ ? Math.sign(value - bound)
296
+ : undefined;
297
+ case "bigint": {
298
+ if (typeof value !== "bigint") {
299
+ return undefined;
300
+ }
301
+ const limit = BigInt(bound);
302
+ return value === limit ? 0 : value > limit ? 1 : -1;
303
+ }
304
+ case "decimal": {
305
+ const left = decimalParts(String(value));
306
+ const right = decimalParts(String(bound));
307
+ return left === undefined || right === undefined
308
+ ? undefined
309
+ : compareDecimals(left, right);
310
+ }
311
+ case "datetime":
312
+ return value instanceof Date
313
+ ? Math.sign(value.getTime() - Date.parse(String(bound)))
314
+ : undefined;
315
+ default:
316
+ return undefined;
317
+ }
318
+ }
319
+ function isMultiple(value, step, subject) {
320
+ switch (subject) {
321
+ case "number":
322
+ return typeof value === "number" && typeof step === "number"
323
+ ? floatRemainder(value, step) === 0
324
+ : undefined;
325
+ case "bigint": {
326
+ if (typeof value !== "bigint") {
327
+ return undefined;
328
+ }
329
+ const divisor = BigInt(step);
330
+ return divisor !== BigInt(0) && value % divisor === BigInt(0);
331
+ }
332
+ case "decimal": {
333
+ const left = decimalParts(String(value));
334
+ const right = decimalParts(String(step));
335
+ return left === undefined || right === undefined
336
+ ? undefined
337
+ : isDecimalMultiple(left, right);
338
+ }
339
+ default:
340
+ return undefined;
341
+ }
342
+ }
343
+ export function passesFieldCheck(check, value, subject) {
344
+ switch (check.check) {
345
+ case "less_than":
346
+ case "greater_than": {
347
+ const order = compareToBound(value, check.value, subject);
348
+ if (order === undefined) {
349
+ return true;
350
+ }
351
+ const signed = check.check === "less_than" ? -order : order;
352
+ return signed > 0 || (check.inclusive && signed === 0);
353
+ }
354
+ case "multiple_of":
355
+ return isMultiple(value, check.value, subject) ?? true;
356
+ case "max_length":
357
+ case "min_length":
358
+ case "length_equals": {
359
+ const length = Array.isArray(value)
360
+ ? value.length
361
+ : typeof value === "string"
362
+ ? codePoints(value)
363
+ : undefined;
364
+ if (length === undefined) {
365
+ return true;
366
+ }
367
+ return check.check === "max_length"
368
+ ? length <= check.maximum
369
+ : check.check === "min_length"
370
+ ? length >= check.minimum
371
+ : length === check.length;
372
+ }
373
+ case "string_format":
374
+ return typeof value === "string" ? passesFormat(check, value) : true;
375
+ case "max_size":
376
+ case "min_size":
377
+ case "size_equals": {
378
+ if (!(value instanceof Uint8Array)) {
379
+ return true;
380
+ }
381
+ const size = value.byteLength;
382
+ return check.check === "max_size"
383
+ ? size <= check.maximum
384
+ : check.check === "min_size"
385
+ ? size >= check.minimum
386
+ : size === check.size;
387
+ }
388
+ }
389
+ }
390
+ const FORMAT_LABELS = {
391
+ email: "an email address",
392
+ url: "a URL",
393
+ emoji: "emoji",
394
+ uuid: "a UUID",
395
+ guid: "a GUID",
396
+ nanoid: "a Nano ID",
397
+ cuid: "a CUID",
398
+ cuid2: "a CUID2",
399
+ ulid: "a ULID",
400
+ xid: "an XID",
401
+ ksuid: "a KSUID",
402
+ datetime: "an ISO 8601 date-time in UTC",
403
+ date: "an ISO 8601 date",
404
+ time: "an ISO 8601 time",
405
+ duration: "an ISO 8601 duration",
406
+ ipv4: "an IPv4 address",
407
+ ipv6: "an IPv6 address",
408
+ cidrv4: "an IPv4 CIDR block",
409
+ cidrv6: "an IPv6 CIDR block",
410
+ base64: "base64",
411
+ base64url: "base64url",
412
+ json_string: "a JSON string",
413
+ e164: "an E.164 phone number",
414
+ credit_card: "a credit card number",
415
+ iban: "an IBAN",
416
+ jwt: "a JWT",
417
+ };
418
+ function plural(count, one, many) {
419
+ return `${count} ${count === 1 ? one : many}`;
420
+ }
421
+ function formatMessage(check) {
422
+ switch (check.format) {
423
+ case "regex":
424
+ return `Value must match the pattern /${check.pattern.source}/${check.pattern.flags}.`;
425
+ case "includes":
426
+ return `Value must include ${JSON.stringify(check.includes)}.`;
427
+ case "starts_with":
428
+ return `Value must start with ${JSON.stringify(check.prefix)}.`;
429
+ case "ends_with":
430
+ return `Value must end with ${JSON.stringify(check.suffix)}.`;
431
+ case "lowercase":
432
+ return "Value must be lowercase.";
433
+ case "uppercase":
434
+ return "Value must be uppercase.";
435
+ default:
436
+ return `Value must be ${FORMAT_LABELS[check.format]}.`;
437
+ }
438
+ }
439
+ function boundMessage(check, subject) {
440
+ const bound = String(check.value);
441
+ if (subject === "datetime") {
442
+ return check.check === "less_than"
443
+ ? `Value must be ${check.inclusive ? "on or before" : "before"} ${bound}.`
444
+ : `Value must be ${check.inclusive ? "on or after" : "after"} ${bound}.`;
445
+ }
446
+ return check.check === "less_than"
447
+ ? `Value must be ${check.inclusive ? "at most" : "less than"} ${bound}.`
448
+ : `Value must be ${check.inclusive ? "at least" : "greater than"} ${bound}.`;
449
+ }
450
+ function messageOf(check, subject) {
451
+ switch (check.check) {
452
+ case "less_than":
453
+ case "greater_than":
454
+ return boundMessage(check, subject);
455
+ case "multiple_of":
456
+ return `Value must be a multiple of ${check.value}.`;
457
+ case "max_length":
458
+ return check.list === true
459
+ ? `List must have at most ${plural(check.maximum, "entry", "entries")}.`
460
+ : `Value must be at most ${plural(check.maximum, "character", "characters")} long.`;
461
+ case "min_length":
462
+ return check.list === true
463
+ ? `List must have at least ${plural(check.minimum, "entry", "entries")}.`
464
+ : `Value must be at least ${plural(check.minimum, "character", "characters")} long.`;
465
+ case "length_equals":
466
+ return `Value must be exactly ${plural(check.length, "character", "characters")} long.`;
467
+ case "string_format":
468
+ return formatMessage(check);
469
+ case "max_size":
470
+ return `Value must be at most ${plural(check.maximum, "byte", "bytes")}.`;
471
+ case "min_size":
472
+ return `Value must be at least ${plural(check.minimum, "byte", "bytes")}.`;
473
+ case "size_equals":
474
+ return `Value must be exactly ${plural(check.size, "byte", "bytes")}.`;
475
+ }
476
+ }
477
+ export function fieldCheckIssue(check, subject, path) {
478
+ const { check: name, ...params } = check;
479
+ const code = name === "string_format" ? "V1003" : "V1004";
480
+ return {
481
+ code,
482
+ path,
483
+ message: messageOf(check, subject),
484
+ check: name,
485
+ params,
486
+ };
487
+ }
488
+ export function fieldCheckIssues(checks, value, subject, path, list) {
489
+ if (checks.length === 0 || value === null || value === undefined) {
490
+ return [];
491
+ }
492
+ const issues = [];
493
+ if (list && Array.isArray(value)) {
494
+ for (const check of checks) {
495
+ if (isListCheck(check) && !passesFieldCheck(check, value, subject)) {
496
+ issues.push(fieldCheckIssue(check, subject, path));
497
+ }
498
+ }
499
+ for (const [index, entry] of value.entries()) {
500
+ issues.push(...entryCheckIssues(checks, entry, subject, [...path, index]));
501
+ }
502
+ return issues;
503
+ }
504
+ return entryCheckIssues(checks, value, subject, path);
505
+ }
506
+ export function entryCheckIssues(checks, value, subject, path) {
507
+ if (value === null || value === undefined) {
508
+ return [];
509
+ }
510
+ const issues = [];
511
+ for (const check of checks) {
512
+ if (!isListCheck(check) && !passesFieldCheck(check, value, subject)) {
513
+ issues.push(fieldCheckIssue(check, subject, path));
514
+ }
515
+ }
516
+ return issues;
517
+ }
518
+ export function isListCheck(check) {
519
+ return ((check.check === "max_length" || check.check === "min_length") &&
520
+ check.list === true);
521
+ }
@@ -0,0 +1,64 @@
1
+ import type { AvAdapterModel } from "../adapters/adapter-model.js";
2
+ import type { AvAdapterFieldKey } from "../adapters/adapter-resource.js";
3
+ import type { AvConfigAny } from "../config/any-framework-config.js";
4
+ import type { AvEffectiveFieldKey } from "../config/effective-fields.js";
5
+ import type { AvConfigResourceKey } from "../config/framework-field-definition.js";
6
+ import type { AvComputeReads } from "../framework/operation-facade.js";
7
+ import type { AvContext } from "./pipeline.js";
8
+ import type { AvDeepReadonly } from "./readonly-value.js";
9
+ import type { AvState } from "./request-state.js";
10
+ /**
11
+ * The ctx a compute stage is told: the operation's `$` facts, a read-only view
12
+ * of the request's `$state`, and reads only (`ctx.<Resource>.find.<variant>(args)`,
13
+ * `find.count` included).
14
+ */
15
+ export type AvComputeContext<M extends AvAdapterModel = AvAdapterModel> = AvComputeReads<M> & Pick<AvContext<M>, "$operation" | "$args" | "$origin" | "$requestId" | "$transport" | "$contract"> & {
16
+ /** The request's state, read-only: a write throws a `TypeError`. */
17
+ readonly $state: AvDeepReadonly<AvState>;
18
+ };
19
+ /**
20
+ * What a write-stage compute callback is told about the field it is computing.
21
+ */
22
+ type ComputedWriteContext<M extends AvAdapterModel> = {
23
+ readonly field: string;
24
+ readonly value: unknown;
25
+ readonly data: Readonly<Record<string, unknown>>;
26
+ readonly ctx: AvComputeContext<M>;
27
+ };
28
+ /**
29
+ * Computes a field's value when a row is created, whether or not the caller sent
30
+ * it. It receives the incoming `data` and returns the value to store; returning
31
+ * `undefined` keeps the current value.
32
+ */
33
+ export type AvComputeCreate<M extends AvAdapterModel = AvAdapterModel> = (context: ComputedWriteContext<M>) => unknown | Promise<unknown>;
34
+ /**
35
+ * Computes a field's value when a row is updated, whether or not the caller sent
36
+ * it. It receives the incoming `data` and returns the value to store; returning
37
+ * `undefined` keeps the current value.
38
+ */
39
+ export type AvComputeUpdate<M extends AvAdapterModel = AvAdapterModel> = (context: ComputedWriteContext<M>) => unknown | Promise<unknown>;
40
+ /**
41
+ * Computes a field's value when a row is read. It receives the stored `record`
42
+ * and returns the value to return; returning `undefined` keeps the current value.
43
+ */
44
+ export type ComputeReadFunction<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny, R extends AvConfigResourceKey<M> = AvConfigResourceKey<M>> = (context: {
45
+ readonly field: AvEffectiveFieldKey<M, Cfg, R>;
46
+ readonly value: unknown;
47
+ readonly record: Readonly<Record<AvEffectiveFieldKey<M, Cfg, R>, unknown>>;
48
+ readonly ctx: AvComputeContext<M>;
49
+ }) => unknown | Promise<unknown>;
50
+ /** The fields of Resource `R` the adapter stores as scalars: what `dependsOn` may name. */
51
+ type StoredScalarKey<M extends AvAdapterModel, R extends AvConfigResourceKey<M>> = string extends AvAdapterFieldKey<M, R> ? string : {
52
+ [F in AvAdapterFieldKey<M, R>]: M["resources"][R]["fields"][F] extends {
53
+ readonly kind: "scalar";
54
+ } ? F : never;
55
+ }[AvAdapterFieldKey<M, R>];
56
+ /**
57
+ * A read compute stage: a compute function, or `{ compute, dependsOn }` naming
58
+ * the fields it reads.
59
+ */
60
+ export type AvComputeRead<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny, R extends AvConfigResourceKey<M> = AvConfigResourceKey<M>> = ComputeReadFunction<M, Cfg, R> | {
61
+ readonly dependsOn?: readonly StoredScalarKey<M, R>[];
62
+ readonly compute: ComputeReadFunction<M, Cfg, R>;
63
+ };
64
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { ResolvedPipelineTree } from "../config/pipeline-tree.resolver.js";
2
+ import type { AvContract } from "../contracts/contract.js";
3
+ /** One origin's field-stage dispatch, planned at startup. */
4
+ export type FieldStagePlan = {
5
+ /** Whether any Resource registers a field pipe. */
6
+ readonly anyPipes: boolean;
7
+ /** Whether any Resource registers a guard a nested target runs: its own, its family's or a field write guard. */
8
+ readonly nestedGuards: boolean;
9
+ /** `resource`'s fields with write guards, in the Resource's field order. */
10
+ readonly guarded: (resource: string) => readonly string[];
11
+ /** `resource`'s fields with field pipes, in the Resource's field order. */
12
+ readonly piped: (resource: string) => readonly string[];
13
+ };
14
+ /** Plans the field-stage dispatch of `tree` under `contract`. */
15
+ export declare function planFieldStages(tree: ResolvedPipelineTree, contract: AvContract): FieldStagePlan;
@@ -0,0 +1,27 @@
1
+ import { stagedFieldsOf } from "./field-stage.runtime.js";
2
+ const NONE = Object.freeze([]);
3
+ export function planFieldStages(tree, contract) {
4
+ const guarded = new Map();
5
+ const piped = new Map();
6
+ let nestedGuards = false;
7
+ for (const [resource, pipelines] of Object.entries(tree.resources)) {
8
+ const guards = stagedFieldsOf(contract, resource, pipelines.fields, "guards");
9
+ const pipes = stagedFieldsOf(contract, resource, pipelines.fields, "pipes");
10
+ if (guards.length > 0) {
11
+ guarded.set(resource, Object.freeze([...guards]));
12
+ }
13
+ if (pipes.length > 0) {
14
+ piped.set(resource, Object.freeze([...pipes]));
15
+ }
16
+ nestedGuards ||=
17
+ guards.length > 0 ||
18
+ pipelines.pipelines.some((level) => level.guards.length > 0) ||
19
+ Object.values(pipelines.families).some((family) => family.pipelines.some((level) => level.guards.length > 0));
20
+ }
21
+ return Object.freeze({
22
+ anyPipes: piped.size > 0,
23
+ nestedGuards,
24
+ guarded: (resource) => guarded.get(resource) ?? NONE,
25
+ piped: (resource) => piped.get(resource) ?? NONE,
26
+ });
27
+ }
@@ -0,0 +1,35 @@
1
+ import type { ResolvedFieldStages } from "../config/pipeline-tree.resolver.js";
2
+ import type { AvContract } from "../contracts/contract.js";
3
+ import type { AvOperationFamily } from "../operations/operation-identity.js";
4
+ import type { AvContext } from "./pipeline.js";
5
+ export type Path = readonly (string | number)[];
6
+ type UnknownRecord = Readonly<Record<string, unknown>>;
7
+ /** A plain object: what a write record, or a directive's operand, is. */
8
+ export declare function isPlainRecord(value: unknown): value is UnknownRecord;
9
+ /** The fields of `resource` with stages, in the Resource's field order. */
10
+ export declare function stagedFieldsOf(contract: AvContract, resource: string, stages: Readonly<Record<string, ResolvedFieldStages>>, kind: "pipes" | "guards"): readonly string[];
11
+ /** The value at `path` in `args`, or `undefined` when nothing is there. */
12
+ export declare function valueAt(args: unknown, path: Path): unknown;
13
+ /** `args` with the record at `path` replaced, every container on the way copied. */
14
+ export declare function replaceAt(args: unknown, path: Path, record: UnknownRecord): unknown;
15
+ export type PipedFields = {
16
+ readonly args: unknown;
17
+ /** Whether a field pipe returned a value: the arguments must be held to the server's rules again. */
18
+ readonly changed: boolean;
19
+ };
20
+ /** The paths of the top-level data records of a create, update or upsert. */
21
+ export declare function writeRecordPathsOf(family: AvOperationFamily, args: unknown): readonly Path[];
22
+ /**
23
+ * Runs the field pipes of every sent field `select` admits, in the records at
24
+ * `records`, field by field in the Resource's order, root's pipes then
25
+ * overlay's. A pipe returning `undefined` keeps the value. The arguments are
26
+ * copied where a value changes, never written.
27
+ */
28
+ export declare function pipeSentFields(stages: Readonly<Record<string, ResolvedFieldStages>>, fields: readonly string[], records: readonly Path[], args: unknown, select: (path: Path) => boolean): Promise<PipedFields>;
29
+ /**
30
+ * Runs the write guards of every sent field in the records at `records`, field
31
+ * by field in the Resource's order and, for several records, record by record;
32
+ * `false` as soon as one refuses.
33
+ */
34
+ export declare function guardSentFields(stages: Readonly<Record<string, ResolvedFieldStages>>, fields: readonly string[], records: readonly Path[], args: unknown, context: () => AvContext): Promise<boolean>;
35
+ export {};