@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.
Files changed (267) hide show
  1. package/CHANGELOG.md +1434 -0
  2. package/ERRORS.md +142 -0
  3. package/README.md +247 -57
  4. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  5. package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
  6. package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
  7. package/dist/adapters/adapter-field.d.ts +25 -11
  8. package/dist/adapters/adapter-identifier.d.ts +6 -6
  9. package/dist/adapters/adapter-model.d.ts +18 -9
  10. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  11. package/dist/adapters/adapter-operation.d.ts +3 -3
  12. package/dist/adapters/adapter-resource.d.ts +18 -9
  13. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  14. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  15. package/dist/adapters/adapter.interface.d.ts +59 -29
  16. package/dist/avz/avz-check.factory.d.ts +83 -0
  17. package/dist/avz/avz-check.factory.js +116 -0
  18. package/dist/avz/avz-check.registry.d.ts +35 -0
  19. package/dist/avz/avz-check.registry.js +9 -0
  20. package/dist/avz/avz.d.ts +203 -0
  21. package/dist/{json → avz}/avz.js +150 -8
  22. package/dist/{json → avz}/index.d.ts +2 -1
  23. package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
  24. package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
  25. package/dist/{json → avz}/zod-issue.translator.js +7 -0
  26. package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
  27. package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
  28. package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
  29. package/dist/compiler/contract.compiler.d.ts +18 -18
  30. package/dist/compiler/contract.compiler.js +637 -442
  31. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  32. package/dist/compiler/create-requirements.projector.js +423 -0
  33. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  34. package/dist/compiler/field-validator.compiler.js +238 -0
  35. package/dist/config/any-framework-config.d.ts +19 -12
  36. package/dist/config/computed-fields.d.ts +62 -0
  37. package/dist/config/computed-fields.js +80 -0
  38. package/dist/config/config-diagnostic.d.ts +11 -4
  39. package/dist/config/config-diagnostic.guidance.d.ts +6 -0
  40. package/dist/config/config-diagnostic.guidance.js +32 -0
  41. package/dist/config/config-layer.d.ts +15 -6
  42. package/dist/config/config.resolver.d.ts +74 -31
  43. package/dist/config/config.resolver.js +108 -44
  44. package/dist/config/config.validator.d.ts +7 -7
  45. package/dist/config/config.validator.js +581 -72
  46. package/dist/config/define-resource.d.ts +57 -0
  47. package/dist/config/define-resource.js +14 -0
  48. package/dist/config/effective-fields.d.ts +19 -23
  49. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  50. package/dist/config/exact-framework-config.d.ts +308 -0
  51. package/dist/config/field-compute.resolver.d.ts +21 -0
  52. package/dist/config/field-compute.resolver.js +123 -0
  53. package/dist/config/field-pipeline-config.d.ts +47 -0
  54. package/dist/config/forced-operation.validator.d.ts +10 -0
  55. package/dist/config/forced-operation.validator.js +66 -0
  56. package/dist/config/framework-config.d.ts +111 -39
  57. package/dist/config/framework-exemptions-config.d.ts +91 -0
  58. package/dist/config/framework-exemptions-config.js +1 -0
  59. package/dist/config/framework-field-definition.d.ts +78 -0
  60. package/dist/config/framework-field-definition.js +28 -0
  61. package/dist/config/framework-resources-config.d.ts +122 -0
  62. package/dist/config/framework-resources-config.js +1 -0
  63. package/dist/config/pipeline-config.d.ts +56 -20
  64. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  65. package/dist/config/pipeline-tree.resolver.js +220 -0
  66. package/dist/config/stage-type.eraser.d.ts +65 -0
  67. package/dist/config/stage-type.eraser.js +1 -0
  68. package/dist/contracts/capability.d.ts +21 -12
  69. package/dist/contracts/capability.js +2 -0
  70. package/dist/contracts/client-contract-structure.validator.d.ts +388 -63
  71. package/dist/contracts/client-contract-structure.validator.js +156 -10
  72. package/dist/contracts/contract-canonicalizer.d.ts +26 -3
  73. package/dist/contracts/contract-canonicalizer.js +156 -29
  74. package/dist/contracts/contract-hash.d.ts +12 -7
  75. package/dist/contracts/contract-hash.js +3 -2
  76. package/dist/contracts/contract-limits.d.ts +4 -1
  77. package/dist/contracts/contract-limits.js +1 -0
  78. package/dist/contracts/contract-lookup.d.ts +5 -5
  79. package/dist/contracts/contract-protocol.d.ts +4 -4
  80. package/dist/contracts/contract.d.ts +24 -16
  81. package/dist/contracts/create-requirements.d.ts +35 -0
  82. package/dist/contracts/create-requirements.js +1 -0
  83. package/dist/contracts/enum-definition.d.ts +1 -1
  84. package/dist/contracts/field-check.d.ts +101 -0
  85. package/dist/contracts/field-check.js +1 -0
  86. package/dist/contracts/field.d.ts +81 -42
  87. package/dist/contracts/identifier.d.ts +4 -4
  88. package/dist/contracts/json-shape.d.ts +12 -1
  89. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  90. package/dist/contracts/resource-operations.d.ts +28 -28
  91. package/dist/contracts/resource.d.ts +15 -9
  92. package/dist/contracts/scalar-value-type.d.ts +15 -15
  93. package/dist/contracts/scalar.d.ts +3 -3
  94. package/dist/contracts/transaction-capability.d.ts +1 -1
  95. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  96. package/dist/framework/contract-view.d.ts +213 -147
  97. package/dist/framework/framework-construction.error.d.ts +19 -10
  98. package/dist/framework/framework-construction.error.js +7 -3
  99. package/dist/framework/framework.d.ts +47 -23
  100. package/dist/framework/framework.factory.d.ts +8 -6
  101. package/dist/framework/framework.factory.js +49 -22
  102. package/dist/framework/operation-facade.d.ts +123 -52
  103. package/dist/framework/operation-facade.js +9 -1
  104. package/dist/index.d.ts +57 -50
  105. package/dist/index.js +7 -6
  106. package/dist/internal.d.ts +17 -10
  107. package/dist/internal.js +4 -1
  108. package/dist/operations/database-refusal.d.ts +51 -0
  109. package/dist/operations/database-refusal.js +45 -0
  110. package/dist/operations/operation-arguments.d.ts +343 -207
  111. package/dist/operations/operation-call.d.ts +27 -28
  112. package/dist/operations/operation-identity.d.ts +10 -10
  113. package/dist/operations/operation-result.d.ts +21 -21
  114. package/dist/operations/operation-validator-core.d.ts +6 -6
  115. package/dist/operations/operation-validator-core.js +99 -6
  116. package/dist/operations/operation-validator.d.ts +9 -9
  117. package/dist/operations/projection-scope.resolver.d.ts +6 -6
  118. package/dist/operations/structural-limits.walker.d.ts +6 -6
  119. package/dist/operations/structural-limits.walker.js +145 -0
  120. package/dist/operations/validation-code.d.ts +11 -6
  121. package/dist/operations/validation-code.guidance.d.ts +6 -0
  122. package/dist/operations/validation-code.guidance.js +90 -0
  123. package/dist/operations/validation-code.js +4 -0
  124. package/dist/operations/write-scope.resolver.d.ts +10 -6
  125. package/dist/operations/write-scope.resolver.js +2 -0
  126. package/dist/protocol/absent-route.responder.d.ts +13 -12
  127. package/dist/protocol/absent-route.responder.js +19 -19
  128. package/dist/protocol/contract-document.responder.d.ts +3 -3
  129. package/dist/protocol/contract-document.responder.js +2 -2
  130. package/dist/protocol/http-request.decoder.d.ts +17 -13
  131. package/dist/protocol/http-request.decoder.js +10 -10
  132. package/dist/protocol/http-request.reader.d.ts +3 -3
  133. package/dist/protocol/http-response.encoder.d.ts +4 -4
  134. package/dist/protocol/http-response.encoder.js +94 -55
  135. package/dist/protocol/http-status.table.d.ts +2 -2
  136. package/dist/protocol/operation-response.guard.d.ts +2 -2
  137. package/dist/protocol/protocol-surface.d.ts +4 -4
  138. package/dist/protocol/protocol.binder.d.ts +50 -27
  139. package/dist/protocol/protocol.binder.js +12 -9
  140. package/dist/protocol/protocol.handler.d.ts +22 -13
  141. package/dist/protocol/protocol.handler.js +91 -17
  142. package/dist/protocol/unmounted-route.error.d.ts +4 -4
  143. package/dist/protocol/unmounted-route.error.js +2 -2
  144. package/dist/runtime/caller-data.copier.d.ts +22 -5
  145. package/dist/runtime/caller-data.copier.js +31 -14
  146. package/dist/runtime/caller-data.door.d.ts +17 -11
  147. package/dist/runtime/caller-data.door.js +6 -4
  148. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  149. package/dist/runtime/computed-read-runtime.js +76 -50
  150. package/dist/runtime/computed-value.error.d.ts +7 -6
  151. package/dist/runtime/computed-value.error.js +5 -4
  152. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  153. package/dist/runtime/context-executor.runtime.js +275 -0
  154. package/dist/runtime/create-requirement.d.ts +44 -79
  155. package/dist/runtime/create-requirement.js +213 -73
  156. package/dist/runtime/decimal.d.ts +2 -2
  157. package/dist/runtime/decimal.js +1 -1
  158. package/dist/runtime/diagnostics-reporter.d.ts +54 -27
  159. package/dist/runtime/diagnostics-reporter.js +24 -0
  160. package/dist/runtime/error-boundary.d.ts +65 -8
  161. package/dist/runtime/error-boundary.js +49 -19
  162. package/dist/runtime/error-guidance.d.ts +12 -0
  163. package/dist/runtime/error-guidance.js +1 -0
  164. package/dist/runtime/error.catalog.d.ts +49 -0
  165. package/dist/runtime/error.catalog.js +49 -0
  166. package/dist/runtime/execution-options.d.ts +10 -2
  167. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  168. package/dist/runtime/field-check.evaluator.js +521 -0
  169. package/dist/runtime/field-compute.d.ts +64 -0
  170. package/dist/runtime/field-compute.js +1 -0
  171. package/dist/runtime/field-stage.plan.d.ts +15 -0
  172. package/dist/runtime/field-stage.plan.js +27 -0
  173. package/dist/runtime/field-stage.runtime.d.ts +37 -0
  174. package/dist/runtime/field-stage.runtime.js +147 -0
  175. package/dist/runtime/field-validator.runtime.d.ts +19 -0
  176. package/dist/runtime/field-validator.runtime.js +92 -0
  177. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  178. package/dist/runtime/framework-error-class.table.js +25 -0
  179. package/dist/runtime/framework-error.d.ts +68 -8
  180. package/dist/runtime/framework-error.factory.d.ts +4 -0
  181. package/dist/runtime/framework-error.factory.js +15 -0
  182. package/dist/runtime/framework-error.js +23 -2
  183. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  184. package/dist/runtime/interceptor-next.error.js +6 -0
  185. package/dist/runtime/json-value.d.ts +11 -6
  186. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  187. package/dist/runtime/level-lifecycle.runtime.js +39 -0
  188. package/dist/runtime/misuse-reporter.d.ts +12 -12
  189. package/dist/runtime/mutation-planner.d.ts +19 -10
  190. package/dist/runtime/mutation-planner.js +48 -35
  191. package/dist/runtime/nested-write.walker.d.ts +32 -0
  192. package/dist/runtime/nested-write.walker.js +73 -0
  193. package/dist/runtime/operation-code.guidance.d.ts +6 -0
  194. package/dist/runtime/operation-code.guidance.js +167 -0
  195. package/dist/runtime/operation-request.d.ts +33 -6
  196. package/dist/runtime/operation-response.d.ts +17 -17
  197. package/dist/runtime/operation-runtime.d.ts +127 -25
  198. package/dist/runtime/operation-runtime.js +441 -78
  199. package/dist/runtime/outcome-mapper.d.ts +16 -5
  200. package/dist/runtime/outcome-mapper.js +23 -6
  201. package/dist/runtime/output-validator.d.ts +10 -10
  202. package/dist/runtime/output-validator.js +3 -3
  203. package/dist/runtime/owned-execution.registry.d.ts +16 -6
  204. package/dist/runtime/pipe-output.validator.d.ts +43 -18
  205. package/dist/runtime/pipe-output.validator.js +15 -13
  206. package/dist/runtime/pipeline.d.ts +223 -34
  207. package/dist/runtime/readonly-value.d.ts +43 -0
  208. package/dist/runtime/readonly-value.js +150 -0
  209. package/dist/runtime/request-envelope.validator.d.ts +3 -3
  210. package/dist/runtime/request-envelope.validator.js +12 -7
  211. package/dist/runtime/request-id.d.ts +1 -1
  212. package/dist/runtime/request-state.d.ts +14 -0
  213. package/dist/runtime/request-state.js +1 -0
  214. package/dist/runtime/request-state.resolver.d.ts +12 -0
  215. package/dist/runtime/request-state.resolver.js +20 -0
  216. package/dist/runtime/scalar-runtime.d.ts +35 -16
  217. package/dist/runtime/scalar-runtime.js +102 -34
  218. package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
  219. package/dist/runtime/unsent-value.normalizer.js +128 -0
  220. package/dist/transactions/deferred-operation.d.ts +35 -20
  221. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  222. package/dist/transactions/operation-arguments-encoder.js +2 -2
  223. package/dist/transactions/operation-fingerprint.js +2 -2
  224. package/dist/transactions/sql-statement.d.ts +85 -0
  225. package/dist/transactions/sql-statement.js +47 -0
  226. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  227. package/dist/transactions/sql-statement.validator.js +167 -0
  228. package/dist/transactions/transaction-envelope.d.ts +4 -4
  229. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  230. package/dist/transactions/transaction-integrity-error.js +5 -2
  231. package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
  232. package/dist/transactions/transaction-plan-assembler.js +169 -32
  233. package/dist/transactions/transaction-plan-validator.d.ts +45 -20
  234. package/dist/transactions/transaction-plan-validator.js +96 -38
  235. package/dist/transactions/transaction-reference-collector.d.ts +5 -5
  236. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  237. package/dist/transactions/transaction-reference-resolver.js +26 -14
  238. package/dist/transactions/transaction-reference-validator.d.ts +76 -4
  239. package/dist/transactions/transaction-reference-validator.js +129 -71
  240. package/dist/transactions/transaction-reference.d.ts +13 -13
  241. package/dist/transactions/transaction-reference.js +5 -0
  242. package/dist/transactions/transaction-request.d.ts +18 -5
  243. package/dist/transactions/transaction-response.d.ts +6 -6
  244. package/dist/transactions/transaction-runtime.d.ts +8 -7
  245. package/dist/transactions/transaction-runtime.js +191 -50
  246. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  247. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  248. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  249. package/dist/transactions/transaction-slot-path-error.js +2 -2
  250. package/dist/transactions/transaction-slot-writer.js +2 -2
  251. package/dist/transactions/transaction-stage.runtime.d.ts +82 -0
  252. package/dist/transactions/transaction-stage.runtime.js +126 -0
  253. package/package.json +9 -7
  254. package/src/runtime/field-check.evaluator.ts +720 -0
  255. package/dist/config/define-fields.d.ts +0 -42
  256. package/dist/config/define-fields.js +0 -3
  257. package/dist/config/framework-behaviors-config.d.ts +0 -30
  258. package/dist/config/framework-fields-config.d.ts +0 -42
  259. package/dist/config/framework-restrictions-config.d.ts +0 -142
  260. package/dist/json/avz.d.ts +0 -96
  261. package/dist/runtime/field-behavior.d.ts +0 -48
  262. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  263. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  264. /package/dist/{json → avz}/index.js +0 -0
  265. /package/dist/{json → avz}/json-shape.registry.js +0 -0
  266. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  267. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -1,12 +1,14 @@
1
- import type { Contract } from "../contracts/contract.js";
1
+ import type { AvContract } from "../contracts/contract.js";
2
2
  import type { ScalarForms } from "../contracts/scalar-value-type.js";
3
- import type { OperationResponse } from "../runtime/operation-response.js";
4
- import type { Operation } from "../transactions/deferred-operation.js";
3
+ import type { AvOperation } from "../transactions/deferred-operation.js";
5
4
  import type { ReferenceableArgumentsFor } from "../transactions/transaction-reference.js";
6
- import type { OperationArgumentsFor, ResourceKey } from "./operation-arguments.js";
7
- import type { OperationFamily, OperationIdentity, OperationVariant } from "./operation-identity.js";
5
+ import type { AvOperationArgumentsFor, AvResourceKey } from "./operation-arguments.js";
6
+ import type { AvOperationFamily, AvOperationIdentity, AvOperationVariant } from "./operation-identity.js";
8
7
  import type { AdmittedOperationResult } from "./operation-result.js";
9
8
  type ProjectionKey = "select" | "include";
9
+ /** The origin of a deferred handle's builder (`AvOperationHandle`). */
10
+ type HandleOrigin = "application" | "client";
11
+ type AnyOrigin = any;
10
12
  type SelectOf<Args> = Args extends {
11
13
  readonly select?: infer Select;
12
14
  } ? Exclude<Select, undefined> : never;
@@ -30,15 +32,15 @@ type InferredProjection<Select, Include> = [Select] extends [never] ? [Include]
30
32
  type ArgumentList<Rest, Parameter> = Record<never, never> extends Rest ? [args?: Parameter] : [args: Parameter];
31
33
  /** A direct call's parameters: the argument, then the caller's per-call options. */
32
34
  type CallArgumentList<Rest, Parameter, Options> = Record<never, never> extends Rest ? [args?: Parameter, options?: Options] : [args: Parameter, options?: Options];
33
- type ResourceOperationsOf<C extends Contract, R extends ResourceKey<C>> = C["resources"][R]["operations"];
35
+ type ResourceOperationsOf<C extends AvContract, R extends AvResourceKey<C>> = C["resources"][R]["operations"];
34
36
  /**
35
37
  * The operations Contract `C` advertises: one property per Resource, one per
36
38
  * family under it, one identity per variant under that.
37
39
  */
38
- export type OperationGrammar<C extends Contract> = {
39
- readonly [R in ResourceKey<C>]: {
40
- readonly [F in Extract<keyof ResourceOperationsOf<C, R>, OperationFamily>]: {
41
- readonly [V in Extract<keyof NonNullable<ResourceOperationsOf<C, R>[F]>, OperationVariant<F>>]: Extract<OperationIdentity, {
40
+ export type AvOperationGrammar<C extends AvContract> = {
41
+ readonly [R in AvResourceKey<C>]: {
42
+ readonly [F in Extract<keyof ResourceOperationsOf<C, R>, AvOperationFamily>]: {
43
+ readonly [V in Extract<keyof NonNullable<ResourceOperationsOf<C, R>[F]>, AvOperationVariant<F>>]: Extract<AvOperationIdentity, {
42
44
  readonly family: F;
43
45
  readonly variant: V;
44
46
  }>;
@@ -50,33 +52,30 @@ export type OperationGrammar<C extends Contract> = {
50
52
  * This is the value a committed transaction or a remote call returns for the
51
53
  * operation.
52
54
  */
53
- export type OperationSlot<I extends OperationIdentity, Result> = I["variant"] extends "first" ? Result | null : Result;
54
- /**
55
- * What a direct call resolves, by its `Settlement`: `"response"` — the whole
56
- * `OperationResponse`, as core's façades answer in process, never throwing;
57
- * `"data"` — the slot, as a remote client answers, every failure thrown.
58
- */
59
- type Settled<Settlement extends "response" | "data", I extends OperationIdentity, Result> = Settlement extends "data" ? OperationSlot<I, Result> : OperationResponse<Result>;
60
- type ProjectingCall<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Args, ResultForms extends ScalarForms, Settlement extends "response" | "data", Options> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: CallArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>, Options>) => Promise<Settled<Settlement, I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>>;
61
- type PlainCall<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Args, ResultForms extends ScalarForms, Settlement extends "response" | "data", Options> = (...args: CallArgumentList<Args, Args, Options>) => Promise<Settled<Settlement, I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>>;
55
+ export type AvOperationSlot<I extends AvOperationIdentity, Result> = I["variant"] extends "first" ? Result | null : Result;
56
+ /** What a direct call resolves: the slot, every failure thrown. */
57
+ type Settled<I extends AvOperationIdentity, Result> = AvOperationSlot<I, Result>;
58
+ type ProjectingCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Options> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: CallArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>, Options>) => Promise<Settled<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>>;
59
+ type PlainCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Options> = (...args: CallArgumentList<Args, Args, Options>) => Promise<Settled<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>>;
62
60
  /**
63
61
  * One direct call: its arguments in `Forms`, its result in `ResultForms`,
64
- * resolving as `Settlement` says, taking `Options` per call — generic in its
62
+ * resolving the slot and throwing every failure, taking `Options` per call. It is generic in its
65
63
  * projection when it carries one.
66
64
  */
67
- export type OperationCall<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms, Settlement extends "response" | "data", Options> = "select" extends keyof OperationArgumentsFor<C, R, I, Forms> ? ProjectingCall<C, R, I, OperationArgumentsFor<C, R, I, Forms>, ResultForms, Settlement, Options> : PlainCall<C, R, I, OperationArgumentsFor<C, R, I, Forms>, ResultForms, Settlement, Options>;
65
+ export type AvOperationCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms, Options> = "select" extends keyof AvOperationArgumentsFor<C, R, I, Forms> ? ProjectingCall<C, R, I, AvOperationArgumentsFor<C, R, I, Forms>, ResultForms, Options> : PlainCall<C, R, I, AvOperationArgumentsFor<C, R, I, Forms>, ResultForms, Options>;
68
66
  /**
69
67
  * A deferred operation's arguments: `Forms`, with reference positions opened to a
70
68
  * `$ref` typed in `ResultForms` — the forms the source's final data is read in, so a
71
69
  * reference carries what its source resolves.
72
70
  */
73
- type DeferredArguments<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms> = ReferenceableArgumentsFor<C, R, I, Forms, ResultForms>;
74
- type DeferredProjectingCall<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Args, ResultForms extends ScalarForms> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: ArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>>) => Operation<OperationSlot<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>>;
75
- type DeferredPlainCall<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Args, ResultForms extends ScalarForms> = (...args: ArgumentList<Args, Args>) => Operation<OperationSlot<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>>;
71
+ type DeferredArguments<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms> = ReferenceableArgumentsFor<C, R, I, Forms, ResultForms>;
72
+ type DeferredProjectingCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Origin extends HandleOrigin> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: ArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>>) => AvOperation<AvOperationSlot<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>, Origin>;
73
+ type DeferredPlainCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Origin extends HandleOrigin> = (...args: ArgumentList<Args, Args>) => AvOperation<AvOperationSlot<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>, Origin>;
76
74
  /**
77
- * One deferred operation: a handle typed `Operation<OperationSlot<…>>` — `$ref`
78
- * present exactly where the result is one row. A handle is not a request and takes no
79
- * options.
75
+ * One deferred operation: a handle typed `AvOperation<AvOperationSlot<…>, Origin>`,
76
+ * with `$ref` present exactly where the result is one row. A handle is not a
77
+ * request and takes no options. `Origin` is the builder's: a transaction's
78
+ * handles all share one.
80
79
  */
81
- export type DeferredOperationCall<C extends Contract, R extends ResourceKey<C>, I extends OperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms> = "select" extends keyof DeferredArguments<C, R, I, Forms, ResultForms> ? DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, Forms, ResultForms>, ResultForms> : DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, Forms, ResultForms>, ResultForms>;
80
+ export type AvDeferredOperationCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms, Origin extends HandleOrigin = AnyOrigin> = "select" extends keyof DeferredArguments<C, R, I, Forms, ResultForms> ? DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, Forms, ResultForms>, ResultForms, Origin> : DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, Forms, ResultForms>, ResultForms, Origin>;
82
81
  export {};
@@ -1,18 +1,18 @@
1
- import type { ResourceOperations } from "../contracts/resource-operations.js";
1
+ import type { AvResourceOperations } from "../contracts/resource-operations.js";
2
2
  /** A standard operation family: `find`, `create`, `update`, `delete` or `upsert`. */
3
- export type OperationFamily = Extract<keyof ResourceOperations, string>;
3
+ export type AvOperationFamily = Extract<keyof AvResourceOperations, string>;
4
4
  /** The variants of operation family `F`, such as `many` or `unique`. */
5
- export type OperationVariant<F extends OperationFamily> = Extract<keyof NonNullable<ResourceOperations[F]>, string>;
5
+ export type AvOperationVariant<F extends AvOperationFamily> = Extract<keyof NonNullable<AvResourceOperations[F]>, string>;
6
6
  /** A standard operation's `family` and `variant`. */
7
- export type OperationIdentity = {
8
- [F in OperationFamily]: {
9
- [V in OperationVariant<F>]: {
7
+ export type AvOperationIdentity = {
8
+ [F in AvOperationFamily]: {
9
+ [V in AvOperationVariant<F>]: {
10
10
  readonly family: F;
11
11
  readonly variant: V;
12
12
  };
13
- }[OperationVariant<F>];
14
- }[OperationFamily];
15
- /** Parses a family and variant into an {@link OperationIdentity}, or `undefined` when they name no standard operation. */
16
- export declare function parseOperationIdentity(family: string, variant: string): OperationIdentity | undefined;
13
+ }[AvOperationVariant<F>];
14
+ }[AvOperationFamily];
15
+ /** Parses a family and variant into an {@link AvOperationIdentity}, or `undefined` when they name no standard operation. */
16
+ export declare function parseOperationIdentity(family: string, variant: string): AvOperationIdentity | undefined;
17
17
  /** Whether `family` names one of the standard operation families. */
18
18
  export declare function isOperationFamily(family: string): boolean;
@@ -1,21 +1,21 @@
1
- import type { Contract } from "../contracts/contract.js";
2
- import type { RelationField, ScalarField } from "../contracts/field.js";
3
- import type { ApplicationScalarForms, ScalarForms, ScalarValueType } from "../contracts/scalar-value-type.js";
4
- import type { FieldKey, OperationArgumentsFor, ResourceKey } from "./operation-arguments.js";
5
- import type { OperationIdentity } from "./operation-identity.js";
6
- type FieldOf<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>> = C["resources"][K]["fields"][F];
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvRelationField, AvScalarField } from "../contracts/field.js";
3
+ import type { AvApplicationScalarForms, AvScalarValueType, ScalarForms } from "../contracts/scalar-value-type.js";
4
+ import type { AvFieldKey, AvOperationArgumentsFor, AvResourceKey } from "./operation-arguments.js";
5
+ import type { AvOperationIdentity } from "./operation-identity.js";
6
+ type FieldOf<C extends AvContract, K extends AvResourceKey<C>, F extends AvFieldKey<C, K>> = C["resources"][K]["fields"][F];
7
7
  /**
8
8
  * The fields returned when no projection is given: the scalars whose `select`
9
9
  * is exactly `true`. A write-only field never appears.
10
10
  */
11
- type DefaultKey<C extends Contract, K extends ResourceKey<C>> = {
12
- [F in FieldKey<C, K>]: FieldOf<C, K, F> extends {
11
+ type DefaultKey<C extends AvContract, K extends AvResourceKey<C>> = {
12
+ [F in AvFieldKey<C, K>]: FieldOf<C, K, F> extends {
13
13
  readonly kind: "scalar";
14
14
  readonly capabilities: {
15
15
  readonly select: true;
16
16
  };
17
17
  } ? F : never;
18
- }[FieldKey<C, K>];
18
+ }[AvFieldKey<C, K>];
19
19
  /** The field one projection entry names: a bare key, or a relation entry's key. */
20
20
  type EntryKey<Entry> = Entry extends string ? Entry : Entry extends object ? Extract<keyof Entry, string> : never;
21
21
  /**
@@ -31,26 +31,26 @@ type EntryArguments<Entry, F extends string> = Entry extends object ? Entry exte
31
31
  * `Entries` carries the relation entries' own arguments down; the scalar branch
32
32
  * ignores them.
33
33
  */
34
- type ProjectedFields<C extends Contract, K extends ResourceKey<C>, Keys extends FieldKey<C, K>, Entries, Forms extends ScalarForms> = {
35
- readonly [F in Keys]: FieldOf<C, K, F> extends ScalarField<C> ? ScalarValueType<C, FieldOf<C, K, F>, Forms> : FieldOf<C, K, F> extends RelationField<C> ? RelationResult<C, Extract<FieldOf<C, K, F>["target"], ResourceKey<C>>, FieldOf<C, K, F>, EntryArguments<Entries, F>, Forms> : never;
34
+ type ProjectedFields<C extends AvContract, K extends AvResourceKey<C>, Keys extends AvFieldKey<C, K>, Entries, Forms extends ScalarForms> = {
35
+ readonly [F in Keys]: FieldOf<C, K, F> extends AvScalarField<C> ? AvScalarValueType<C, FieldOf<C, K, F>, Forms> : FieldOf<C, K, F> extends AvRelationField<C> ? RelationResult<C, Extract<FieldOf<C, K, F>["target"], AvResourceKey<C>>, FieldOf<C, K, F>, EntryArguments<Entries, F>, Forms> : never;
36
36
  };
37
37
  /**
38
38
  * One projection level: `select` returns exactly its entries, `include` the
39
39
  * default fields plus the named relations, and no projection the default fields.
40
40
  */
41
- type ProjectedRecord<C extends Contract, K extends ResourceKey<C>, Arguments, Forms extends ScalarForms> = [Arguments] extends [never] ? ProjectedFields<C, K, DefaultKey<C, K>, never, Forms> : [Arguments] extends [{
41
+ type ProjectedRecord<C extends AvContract, K extends AvResourceKey<C>, Arguments, Forms extends ScalarForms> = [Arguments] extends [never] ? ProjectedFields<C, K, DefaultKey<C, K>, never, Forms> : [Arguments] extends [{
42
42
  readonly select: readonly (infer Entry)[];
43
- }] ? ProjectedFields<C, K, Extract<EntryKey<Entry>, FieldKey<C, K>>, Entry, Forms> : [Arguments] extends [{
43
+ }] ? ProjectedFields<C, K, Extract<EntryKey<Entry>, AvFieldKey<C, K>>, Entry, Forms> : [Arguments] extends [{
44
44
  readonly include: readonly (infer Entry)[];
45
- }] ? ProjectedFields<C, K, DefaultKey<C, K> | Extract<EntryKey<Entry>, FieldKey<C, K>>, Entry, Forms> : ProjectedFields<C, K, DefaultKey<C, K>, never, Forms>;
45
+ }] ? ProjectedFields<C, K, DefaultKey<C, K> | Extract<EntryKey<Entry>, AvFieldKey<C, K>>, Entry, Forms> : ProjectedFields<C, K, DefaultKey<C, K>, never, Forms>;
46
46
  /**
47
47
  * A to-many entry whose `select` asks for `$count`: the value is an object with
48
48
  * the rows and the count, not the row array.
49
49
  */
50
- type CountEnvelope<C extends Contract, Target extends ResourceKey<C>, Entry, Forms extends ScalarForms> = [Exclude<Entry, "$count">] extends [never] ? {
50
+ type CountEnvelope<C extends AvContract, Target extends AvResourceKey<C>, Entry, Forms extends ScalarForms> = [Exclude<Entry, "$count">] extends [never] ? {
51
51
  readonly count: number;
52
52
  } : {
53
- readonly data: readonly ProjectedFields<C, Target, Extract<EntryKey<Entry>, FieldKey<C, Target>>, Exclude<Entry, "$count">, Forms>[];
53
+ readonly data: readonly ProjectedFields<C, Target, Extract<EntryKey<Entry>, AvFieldKey<C, Target>>, Exclude<Entry, "$count">, Forms>[];
54
54
  readonly count: number;
55
55
  };
56
56
  /** The entries of an argument's own `select`, or `never` when it has none. */
@@ -61,16 +61,16 @@ type SelectEntry<Arguments> = Arguments extends {
61
61
  * The value of one relation entry. A to-many entry is the rows-and-count object
62
62
  * when its own `select` asks for `$count`; otherwise the row array.
63
63
  */
64
- type RelationResult<C extends Contract, Target extends ResourceKey<C>, Relation extends RelationField<C>, Arguments, Forms extends ScalarForms> = Relation["cardinality"] extends "many" ? [Extract<SelectEntry<Arguments>, "$count">] extends [never] ? readonly ProjectedRecord<C, Target, Arguments, Forms>[] : CountEnvelope<C, Target, SelectEntry<Arguments>, Forms> : ProjectedRecord<C, Target, Arguments, Forms> | (true extends Relation["nullable"] ? null : never);
64
+ type RelationResult<C extends AvContract, Target extends AvResourceKey<C>, Relation extends AvRelationField<C>, Arguments, Forms extends ScalarForms> = Relation["cardinality"] extends "many" ? [Extract<SelectEntry<Arguments>, "$count">] extends [never] ? readonly ProjectedRecord<C, Target, Arguments, Forms>[] : CountEnvelope<C, Target, SelectEntry<Arguments>, Forms> : ProjectedRecord<C, Target, Arguments, Forms> | (true extends Relation["nullable"] ? null : never);
65
65
  /**
66
- * The value a standard operation returns in `OperationResponse.data` on success,
66
+ * The value a standard operation returns in `AvOperationResponse.data` on success,
67
67
  * derived from the Contract, the Resource, the operation identity and the projection
68
68
  * argument.
69
69
  */
70
- export type OperationResultFor<C extends Contract, K extends ResourceKey<C>, I extends OperationIdentity, Args extends OperationArgumentsFor<C, K, I>, Forms extends ScalarForms = ApplicationScalarForms> = AdmittedOperationResult<C, K, I, Args, Forms>;
70
+ export type AvOperationResultFor<C extends AvContract, K extends AvResourceKey<C>, I extends AvOperationIdentity, Args extends AvOperationArgumentsFor<C, K, I>, Forms extends ScalarForms = AvApplicationScalarForms> = AdmittedOperationResult<C, K, I, Args, Forms>;
71
71
  /**
72
- * {@link OperationResultFor}, for a projection already checked against the
72
+ * {@link AvOperationResultFor}, for a projection already checked against the
73
73
  * operation's argument type.
74
74
  */
75
- export type AdmittedOperationResult<C extends Contract, K extends ResourceKey<C>, I extends OperationIdentity, Args, Forms extends ScalarForms = ApplicationScalarForms> = I["variant"] extends "count" ? number : I["variant"] extends "many" ? readonly ProjectedRecord<C, K, Args, Forms>[] : ProjectedRecord<C, K, Args, Forms>;
75
+ export type AdmittedOperationResult<C extends AvContract, K extends AvResourceKey<C>, I extends AvOperationIdentity, Args, Forms extends ScalarForms = AvApplicationScalarForms> = I["variant"] extends "count" ? number : I["variant"] extends "many" ? readonly ProjectedRecord<C, K, Args, Forms>[] : ProjectedRecord<C, K, Args, Forms>;
76
76
  export {};
@@ -1,6 +1,6 @@
1
- import type { Contract } from "../contracts/contract.js";
2
- import { type OperationIdentity } from "./operation-identity.js";
3
- import type { ValidationIssue } from "./validation-code.js";
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import { type AvOperationIdentity } from "./operation-identity.js";
3
+ import type { AvValidationIssue } from "./validation-code.js";
4
4
  /** An operation's arguments as an object, before validation. */
5
5
  export type SemanticOperationArguments = Readonly<Record<string, unknown>>;
6
6
  type OperationValidationSuccess = {
@@ -9,7 +9,7 @@ type OperationValidationSuccess = {
9
9
  };
10
10
  type OperationValidationFailure = {
11
11
  readonly ok: false;
12
- readonly issues: readonly ValidationIssue[];
12
+ readonly issues: readonly AvValidationIssue[];
13
13
  };
14
14
  /** The answer of {@link validateOperationArguments}: success, or the issues found. */
15
15
  export type OperationValidationResult = OperationValidationSuccess | OperationValidationFailure;
@@ -21,8 +21,8 @@ export type OperationValidationOptions = {
21
21
  * Contract does not have (`V1005` at `["resource"]`, rolling up to `A2001`). The one
22
22
  * spelling — the protocol's absence answers build theirs with it.
23
23
  */
24
- export declare function resourceUnavailableIssue(resource: string): ValidationIssue;
25
- export declare function validateOperationArguments(contract: Contract, request: OperationIdentity & {
24
+ export declare function resourceUnavailableIssue(resource: string): AvValidationIssue;
25
+ export declare function validateOperationArguments(contract: AvContract, request: AvOperationIdentity & {
26
26
  readonly resource: string;
27
27
  readonly arguments: unknown;
28
28
  }, options?: OperationValidationOptions): OperationValidationResult;
@@ -1,10 +1,11 @@
1
+ import { FILTER_MODES, } from "../contracts/capability.js";
1
2
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
3
  import { advertisedDirectivesAt, advertisedReducers, advertisedReducersAt, holdsAt, } from "../contracts/field.js";
3
- import { isPlainRecord } from "../runtime/scalar-runtime.js";
4
+ import { isPlainRecord, unsentReadValueIssue, } from "../runtime/scalar-runtime.js";
4
5
  import { routeTransactionReferenceCandidate } from "../transactions/transaction-reference.js";
5
6
  import { isOperationFamily, } from "./operation-identity.js";
6
7
  import { NESTED_PROJECTION_SCOPE, resolveProjectionScope, } from "./projection-scope.resolver.js";
7
- import { NESTED_WRITE_SCOPE, resolveWriteScope, } from "./write-scope.resolver.js";
8
+ import { NESTED_WRITE_SCOPE, resolveWriteScope, TO_MANY_UPDATE_WRITE_SCOPE, } from "./write-scope.resolver.js";
8
9
  const OPERATION_ARGUMENT_RULES = {
9
10
  "find.first": {
10
11
  allowed: ["where", "orderBy", "select", "include"],
@@ -153,12 +154,15 @@ function checkDepth(contract, state, depth) {
153
154
  }
154
155
  return false;
155
156
  }
156
- function validateScalarFilter(fieldName, field, value, path, state) {
157
+ function validateScalarFilter(contract, fieldName, field, value, path, state, depth) {
157
158
  const supported = field.capabilities.filter;
158
159
  if (supported === undefined) {
159
160
  addIssue(state.issues, "V1006", path, `Filtering is not available on field "${fieldName}".`);
160
161
  return;
161
162
  }
163
+ validateScalarCondition(contract, fieldName, field, supported, value, path, state, depth);
164
+ }
165
+ function validateScalarCondition(contract, fieldName, field, supported, value, path, state, depth) {
162
166
  if (value === null) {
163
167
  if (!field.nullable) {
164
168
  addIssue(state.issues, "V1001", path, `Field "${fieldName}" is not nullable.`);
@@ -187,11 +191,63 @@ function validateScalarFilter(fieldName, field, value, path, state) {
187
191
  addIssue(state.issues, "V1001", path, `Filter object for field "${fieldName}" must contain an operator.`);
188
192
  return;
189
193
  }
194
+ refuseDanglingQualifiers(fieldName, value, path, state);
190
195
  for (const operator of operators) {
191
196
  if (!includes(supported, operator)) {
192
197
  addIssue(state.issues, "V1006", [...path, operator], `Filter operator "${operator}" is not available on field "${fieldName}".`);
198
+ continue;
199
+ }
200
+ if (operator === "mode") {
201
+ refuseUnavailableMode(field, fieldName, value, path, state);
202
+ continue;
193
203
  }
204
+ if (operator === "not") {
205
+ const operand = value[operator];
206
+ if (isPlainRecord(operand) && !checkDepth(contract, state, depth + 1)) {
207
+ continue;
208
+ }
209
+ validateScalarCondition(contract, fieldName, field, supported, operand, [...path, operator], state, isPlainRecord(operand) ? depth + 1 : depth);
210
+ }
211
+ }
212
+ }
213
+ function refuseDanglingQualifiers(fieldName, level, path, state) {
214
+ const qualifiers = DANGLING_QUALIFIERS.filter((key) => Object.hasOwn(level, key));
215
+ if (qualifiers.length === 0) {
216
+ return;
217
+ }
218
+ const compares = Object.entries(level).some(([operator, operand]) => !includes(DANGLING_QUALIFIERS, operator) &&
219
+ !(operator === "not" && isNegatedOperatorObject(operand, state)));
220
+ if (compares) {
221
+ return;
194
222
  }
223
+ for (const qualifier of qualifiers) {
224
+ addIssue(state.issues, "V1001", [...path, qualifier], `${qualifier} on field "${fieldName}" qualifies no operator: write it next to the operator it applies to (inside "not" to apply to a negated one).`);
225
+ }
226
+ }
227
+ const DANGLING_QUALIFIERS = ["mode", "path"];
228
+ function isNegatedOperatorObject(operand, state) {
229
+ return (isPlainRecord(operand) &&
230
+ !(state.transactionReferences === true &&
231
+ routeTransactionReferenceCandidate(operand).kind !== "ordinary"));
232
+ }
233
+ function refuseUnavailableMode(field, fieldName, level, path, state) {
234
+ const mode = level.mode;
235
+ if (mode === "default" ||
236
+ typeof mode !== "string" ||
237
+ !includes(FILTER_MODES, mode)) {
238
+ return;
239
+ }
240
+ const { filterModes = [], pathFilterModes } = field.capabilities;
241
+ const atPath = Object.hasOwn(level, "path") && pathFilterModes !== undefined;
242
+ if (includes(atPath ? pathFilterModes : filterModes, mode)) {
243
+ return;
244
+ }
245
+ const where = atPath
246
+ ? " at a path"
247
+ : pathFilterModes !== undefined && includes(pathFilterModes, mode)
248
+ ? " without a path"
249
+ : "";
250
+ addIssue(state.issues, "V1006", [...path, "mode"], `Filter mode "${mode}" is not available on field "${fieldName}"${where}.`);
195
251
  }
196
252
  function validateRelationFilter(contract, fieldName, field, value, path, state, depth) {
197
253
  const supported = field.capabilities.filter;
@@ -199,6 +255,10 @@ function validateRelationFilter(contract, fieldName, field, value, path, state,
199
255
  addIssue(state.issues, "V1006", path, `Filtering is not available on relation "${fieldName}".`);
200
256
  return;
201
257
  }
258
+ if (value === undefined) {
259
+ state.issues.push(unsentReadValueIssue(path));
260
+ return;
261
+ }
202
262
  if (field.cardinality === "one") {
203
263
  if (value === null) {
204
264
  if (!field.nullable || !includes(supported, "null")) {
@@ -238,10 +298,20 @@ function validateRelationFilter(contract, fieldName, field, value, path, state,
238
298
  validateWhere(contract, field.target, value[operator], [...path, operator], state, depth + 1);
239
299
  }
240
300
  }
301
+ const UNDEFINED_ARGUMENT_MESSAGES = {
302
+ where: "where must not be undefined: leave the key out to mean no filter.",
303
+ limit: "limit must not be undefined: leave the key out to mean no limit.",
304
+ offset: "offset must not be undefined: leave the key out to mean no offset.",
305
+ cursor: "cursor must not be undefined: leave the key out to mean no cursor.",
306
+ };
241
307
  function validateWhere(contract, resourceName, where, path, state, depth) {
242
308
  if (!checkDepth(contract, state, depth)) {
243
309
  return;
244
310
  }
311
+ if (where === undefined) {
312
+ state.issues.push(unsentReadValueIssue(path));
313
+ return;
314
+ }
245
315
  if (!isRecord(where)) {
246
316
  addIssue(state.issues, "V1001", path, "where must be an object.");
247
317
  return;
@@ -276,7 +346,7 @@ function validateWhere(contract, resourceName, where, path, state, depth) {
276
346
  }
277
347
  const fieldPath = [...path, key];
278
348
  if (field.kind === "scalar") {
279
- validateScalarFilter(key, field, value, fieldPath, state);
349
+ validateScalarFilter(contract, key, field, value, fieldPath, state, depth);
280
350
  }
281
351
  else if (state.scalarOnly === true) {
282
352
  addIssue(state.issues, "V1006", fieldPath, `Relation filter "${key}" is not available here: a nested $update or $delete filter on this relation takes scalar fields only.`);
@@ -355,7 +425,9 @@ function validateOrderBy(contract, resourceName, orderBy, path, issues) {
355
425
  valueKeys[1] !== "sort" ||
356
426
  (value.sort !== "asc" && value.sort !== "desc") ||
357
427
  (value.nulls !== "first" && value.nulls !== "last")) {
358
- addIssue(issues, "V1001", fieldPath, `Extended null ordering for "${fieldName}" must contain sort and nulls.`);
428
+ addIssue(issues, "V1001", fieldPath, Object.hasOwn(value, "$ref")
429
+ ? `A transaction reference cannot stand in orderBy: order "${fieldName}" by "asc", "desc" or { sort, nulls }.`
430
+ : `Null ordering for "${fieldName}" must be exactly { sort: "asc" | "desc", nulls: "first" | "last" }.`);
359
431
  continue;
360
432
  }
361
433
  if (!field.nullable || field.capabilities.orderNulls !== true) {
@@ -382,6 +454,10 @@ function validateOrderBy(contract, resourceName, orderBy, path, issues) {
382
454
  return analysis;
383
455
  }
384
456
  function validatePaginationValue(contract, name, value, path, issues) {
457
+ if (value === undefined) {
458
+ addIssue(issues, "V1001", path, UNDEFINED_ARGUMENT_MESSAGES[name]);
459
+ return;
460
+ }
385
461
  if (!Number.isInteger(value) || typeof value !== "number" || value < 0) {
386
462
  addIssue(issues, "V1001", path, `${name} must be a non-negative integer.`);
387
463
  return;
@@ -391,6 +467,10 @@ function validatePaginationValue(contract, name, value, path, issues) {
391
467
  }
392
468
  }
393
469
  function validateCursor(contract, resourceName, cursor, orderBy, path, issues) {
470
+ if (cursor === undefined) {
471
+ addIssue(issues, "V1009", path, UNDEFINED_ARGUMENT_MESSAGES.cursor);
472
+ return;
473
+ }
394
474
  if (!isRecord(cursor) || orderBy === undefined) {
395
475
  addIssue(issues, "V1009", path, "Cursor pagination requires an object cursor and explicit deterministic orderBy.");
396
476
  return;
@@ -502,6 +582,9 @@ function validateRelationProjection(contract, edge, scope, value, path, issues)
502
582
  if (!includes(edge.capabilities.filter, "nested")) {
503
583
  addIssue(issues, "V1006", [...path, "where"], "Nested returned-relation filtering is not available on this edge.");
504
584
  }
585
+ else if (value.where === undefined) {
586
+ addIssue(issues, "V1001", [...path, "where"], UNDEFINED_ARGUMENT_MESSAGES.where);
587
+ }
505
588
  else {
506
589
  const state = {
507
590
  issues,
@@ -575,11 +658,16 @@ function validateScalarMutation(fieldName, field, value, stage, path, issues, tr
575
658
  addIssue(issues, "V1001", path, "Scalar mutation action objects may contain only $-prefixed directive keys.");
576
659
  return;
577
660
  }
661
+ let unavailable = false;
578
662
  for (const directive of directiveKeys) {
579
663
  if (!includes(directives, directive)) {
664
+ unavailable = true;
580
665
  addIssue(issues, "V1006", [...path, directive], `Mutation directive "${directive}" is not available on field "${fieldName}".`);
581
666
  }
582
667
  }
668
+ if (!unavailable && directiveKeys.length > 1) {
669
+ addIssue(issues, "V1001", path, "Scalar mutation action objects may contain only one directive.");
670
+ }
583
671
  }
584
672
  function validateRelationMutationEntry(contract, edge, directive, value, path, issues, transactionReferences) {
585
673
  const target = edge.target;
@@ -669,7 +757,9 @@ function validateRelationMutationEntry(contract, edge, directive, value, path, i
669
757
  };
670
758
  validateWhere(contract, target, entry.where, [...path, "where"], state, 1);
671
759
  }
672
- validateMutationData(contract, target, entry.data, "update", NESTED_WRITE_SCOPE, [...path, "data"], issues, transactionReferences);
760
+ validateMutationData(contract, target, entry.data, "update", edge.cardinality === "many"
761
+ ? TO_MANY_UPDATE_WRITE_SCOPE
762
+ : NESTED_WRITE_SCOPE, [...path, "data"], issues, transactionReferences);
673
763
  }
674
764
  return;
675
765
  }
@@ -843,6 +933,9 @@ export function validateOperationArguments(contract, request, options) {
843
933
  if (isUniqueOperation(request)) {
844
934
  validateUniqueSelector(contract, request.resource, request.arguments.where, ["arguments", "where"], issues);
845
935
  }
936
+ else if (request.arguments.where === undefined) {
937
+ addIssue(issues, "V1001", ["arguments", "where"], UNDEFINED_ARGUMENT_MESSAGES.where);
938
+ }
846
939
  else {
847
940
  const state = {
848
941
  issues,
@@ -1,10 +1,10 @@
1
- import type { Contract } from "../contracts/contract.js";
2
- import { type OperationIdentity } from "./operation-identity.js";
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import { type AvOperationIdentity } from "./operation-identity.js";
3
3
  import { type OperationValidationOptions, type OperationValidationResult } from "./operation-validator-core.js";
4
- import type { ValidationIssue } from "./validation-code.js";
4
+ import type { AvValidationIssue } from "./validation-code.js";
5
5
  export type { OperationValidationOptions, OperationValidationResult, SemanticOperationArguments, } from "./operation-validator-core.js";
6
6
  /** The key of a request's operation identity that makes it unavailable. */
7
- export declare function unavailableOperationKey(contract: Contract, request: {
7
+ export declare function unavailableOperationKey(contract: AvContract, request: {
8
8
  readonly resource: string;
9
9
  readonly family: string;
10
10
  }): "family" | "variant";
@@ -15,25 +15,25 @@ export declare function unavailableOperationKey(contract: Contract, request: {
15
15
  * {@link unavailableOperationKey}). The one spelling — the protocol's absence
16
16
  * answers build theirs with it, so a caller cannot tell which layer answered.
17
17
  */
18
- export declare function operationUnavailableIssue(contract: Contract, request: {
18
+ export declare function operationUnavailableIssue(contract: AvContract, request: {
19
19
  readonly resource: string;
20
20
  readonly family: string;
21
21
  readonly variant: string;
22
- }): ValidationIssue;
22
+ }): AvValidationIssue;
23
23
  /**
24
24
  * The availability answer alone — `V1006` when the active Contract does not advertise
25
25
  * the operation on a Resource it has — read from the request's identity, never its
26
26
  * arguments. A door that refuses unreadable arguments asks this first, so an
27
27
  * unadvertised operation answers `A2002` whatever its arguments hold.
28
28
  */
29
- export declare function findOperationAvailabilityIssue(contract: Contract, request: OperationIdentity & {
29
+ export declare function findOperationAvailabilityIssue(contract: AvContract, request: AvOperationIdentity & {
30
30
  readonly resource: string;
31
- }): ValidationIssue | undefined;
31
+ }): AvValidationIssue | undefined;
32
32
  /**
33
33
  * Validates one standard operation's arguments against a Contract. Operation
34
34
  * availability and request limits are checked before the arguments' grammar.
35
35
  */
36
- export declare function validateOperationArguments(contract: Contract, request: OperationIdentity & {
36
+ export declare function validateOperationArguments(contract: AvContract, request: AvOperationIdentity & {
37
37
  readonly resource: string;
38
38
  readonly arguments: unknown;
39
39
  }, options?: OperationValidationOptions): OperationValidationResult;
@@ -1,7 +1,7 @@
1
- import type { ProjectionScope } from "../contracts/capability.js";
2
- import type { Contract } from "../contracts/contract.js";
3
- import type { Resource } from "../contracts/resource.js";
4
- import type { OperationIdentity } from "./operation-identity.js";
1
+ import type { AvProjectionScope } from "../contracts/capability.js";
2
+ import type { AvContract } from "../contracts/contract.js";
3
+ import type { AvResource } from "../contracts/resource.js";
4
+ import type { AvOperationIdentity } from "./operation-identity.js";
5
5
  /**
6
6
  * Which projection position one request's **top-level** projection arguments sit
7
7
  * in, read off the variant the Resource advertises.
@@ -21,9 +21,9 @@ import type { OperationIdentity } from "./operation-identity.js";
21
21
  * answering `"record"` for one keeps this function a projection question rather
22
22
  * than a second, weaker copy of the availability gate.
23
23
  */
24
- export declare function resolveProjectionScope(resource: Resource<Contract> | undefined, request: OperationIdentity): ProjectionScope;
24
+ export declare function resolveProjectionScope(resource: AvResource<AvContract> | undefined, request: AvOperationIdentity): AvProjectionScope;
25
25
  /**
26
26
  * The position a projection NESTED beneath an admitted relation sits in: the
27
27
  * unrestricted one, at every depth, under every top-level scope.
28
28
  */
29
- export declare const NESTED_PROJECTION_SCOPE: ProjectionScope;
29
+ export declare const NESTED_PROJECTION_SCOPE: AvProjectionScope;
@@ -1,19 +1,19 @@
1
- import type { Contract } from "../contracts/contract.js";
2
- import type { OperationIdentity } from "./operation-identity.js";
3
- import type { ValidationIssue } from "./validation-code.js";
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvOperationIdentity } from "./operation-identity.js";
3
+ import type { AvValidationIssue } from "./validation-code.js";
4
4
  type Readable = Readonly<Record<string, unknown>>;
5
5
  /** What one walk of an operation's arguments found. */
6
6
  export type StructuralLimitsFinding = {
7
7
  /** The nesting issue, which wins over any boolean-node issue. */
8
- readonly nesting: ValidationIssue | undefined;
8
+ readonly nesting: AvValidationIssue | undefined;
9
9
  /** The boolean-node issue, when there is no nesting issue. */
10
- readonly booleanNodes: ValidationIssue | undefined;
10
+ readonly booleanNodes: AvValidationIssue | undefined;
11
11
  };
12
12
  /**
13
13
  * Enforces the structural limits on one operation's argument object: the nesting
14
14
  * issue if there is one, otherwise the boolean-node issue if there is one.
15
15
  */
16
- export declare function findStructuralLimitIssues(contract: Contract, request: OperationIdentity & {
16
+ export declare function findStructuralLimitIssues(contract: AvContract, request: AvOperationIdentity & {
17
17
  readonly resource: string;
18
18
  }, args: Readable): StructuralLimitsFinding;
19
19
  export {};