@aventara/core 0.1.0-pilot.2 → 0.1.0-pilot.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +2 -0
- package/dist/adapters/adapter-field.d.ts +3 -26
- package/dist/adapters/adapter-identifier.d.ts +1 -11
- package/dist/adapters/adapter-model.d.ts +4 -0
- package/dist/adapters/adapter-operation-executor.interface.d.ts +5 -1
- package/dist/adapters/adapter-resource.d.ts +7 -28
- package/dist/adapters/adapter.interface.d.ts +21 -26
- package/dist/compiler/contract-compiler-diagnostic.d.ts +2 -0
- package/dist/compiler/contract.compiler.d.ts +11 -22
- package/dist/config/any-framework-config.d.ts +5 -26
- package/dist/config/config-diagnostic.d.ts +2 -0
- package/dist/config/config-layer.d.ts +6 -19
- package/dist/config/config.resolver.d.ts +6 -14
- package/dist/config/config.validator.d.ts +6 -3
- package/dist/config/define-fields.d.ts +6 -46
- package/dist/config/effective-fields.d.ts +6 -29
- package/dist/config/entrypoint.normalizer.d.ts +6 -18
- package/dist/config/framework-behaviors-config.d.ts +11 -10
- package/dist/config/framework-config.d.ts +15 -15
- package/dist/config/framework-fields-config.d.ts +14 -7
- package/dist/config/framework-restrictions-config.d.ts +41 -61
- package/dist/config/pipeline-config.d.ts +7 -17
- package/dist/contracts/capability.d.ts +13 -49
- package/dist/contracts/client-contract-structure.validator.d.ts +7 -53
- package/dist/contracts/contract-canonicalizer.d.ts +4 -6
- package/dist/contracts/contract-hash.d.ts +3 -2
- package/dist/contracts/contract-limits.d.ts +7 -1
- package/dist/contracts/contract-protocol.d.ts +7 -8
- package/dist/contracts/contract.d.ts +13 -4
- package/dist/contracts/enum-definition.d.ts +2 -0
- package/dist/contracts/field.d.ts +30 -167
- package/dist/contracts/identifier.d.ts +1 -16
- package/dist/contracts/lifecycle-trait.d.ts +4 -3
- package/dist/contracts/resource-operations.d.ts +2 -62
- package/dist/contracts/resource.d.ts +2 -0
- package/dist/contracts/scalar-value-type.d.ts +16 -47
- package/dist/contracts/scalar.d.ts +4 -3
- package/dist/contracts/transaction-capability.d.ts +2 -0
- package/dist/contracts/wire-scalar-format.d.ts +6 -21
- package/dist/framework/contract-view.d.ts +30 -113
- package/dist/framework/framework-construction.error.d.ts +6 -1
- package/dist/framework/framework.d.ts +31 -46
- package/dist/framework/framework.factory.d.ts +3 -17
- package/dist/framework/operation-facade.d.ts +3 -7
- package/dist/operations/operation-arguments.d.ts +52 -207
- package/dist/operations/operation-call.d.ts +13 -15
- package/dist/operations/operation-identity.d.ts +4 -2
- package/dist/operations/operation-result.d.ts +15 -61
- package/dist/operations/operation-validator-core.d.ts +5 -4
- package/dist/operations/operation-validator.d.ts +5 -7
- package/dist/operations/projection-scope.resolver.d.ts +0 -10
- package/dist/operations/validation-code.d.ts +5 -17
- package/dist/operations/write-scope.resolver.d.ts +3 -28
- package/dist/protocol/absent-route.responder.d.ts +23 -38
- package/dist/protocol/av-protocol.d.ts +2 -8
- package/dist/protocol/contract-document.responder.d.ts +5 -18
- package/dist/protocol/http-request.decoder.d.ts +12 -59
- package/dist/protocol/http-request.reader.d.ts +5 -5
- package/dist/protocol/http-response.encoder.d.ts +14 -20
- package/dist/protocol/http-status.table.d.ts +0 -8
- package/dist/protocol/index.d.ts +2 -7
- package/dist/protocol/operation-response.guard.d.ts +0 -15
- package/dist/protocol/protocol-failure.d.ts +8 -27
- package/dist/protocol/protocol-headers.d.ts +15 -42
- package/dist/protocol/protocol-surface.d.ts +0 -22
- package/dist/protocol/protocol.binder.d.ts +16 -26
- package/dist/protocol/protocol.handler.d.ts +15 -23
- package/dist/runtime/decimal.d.ts +5 -3
- package/dist/runtime/diagnostics-reporter.d.ts +14 -34
- package/dist/runtime/error-boundary.d.ts +6 -10
- package/dist/runtime/execution-options.d.ts +3 -7
- package/dist/runtime/field-behavior.d.ts +12 -19
- package/dist/runtime/framework-error.d.ts +2 -2
- package/dist/runtime/json-value.d.ts +7 -15
- package/dist/runtime/mutation-planner.d.ts +6 -12
- package/dist/runtime/operation-request.d.ts +7 -0
- package/dist/runtime/operation-response.d.ts +18 -23
- package/dist/runtime/operation-runtime.d.ts +12 -27
- package/dist/runtime/pipeline.d.ts +14 -29
- package/dist/runtime/referential-action.d.ts +1 -26
- package/dist/runtime/request-id.d.ts +3 -10
- package/dist/runtime/scalar-runtime.d.ts +12 -12
- package/dist/transactions/deferred-operation.d.ts +10 -21
- package/dist/transactions/operation-arguments-encoder.d.ts +1 -0
- package/dist/transactions/operation-fingerprint.d.ts +3 -1
- package/dist/transactions/transaction-envelope.d.ts +2 -4
- package/dist/transactions/transaction-integrity-error.d.ts +4 -15
- package/dist/transactions/transaction-plan-assembler.d.ts +1 -0
- package/dist/transactions/transaction-plan-validator.d.ts +3 -17
- package/dist/transactions/transaction-reference-resolver.d.ts +9 -12
- package/dist/transactions/transaction-reference.d.ts +23 -28
- package/dist/transactions/transaction-request.d.ts +3 -5
- package/dist/transactions/transaction-response.d.ts +5 -7
- package/dist/transactions/transaction-runtime.d.ts +3 -3
- package/dist/transactions/transaction-slot-path-error.d.ts +5 -15
- package/dist/transactions/transaction-slot-writer.d.ts +3 -13
- package/package.json +1 -1
|
@@ -4,7 +4,9 @@ import type { ProjectionScopes, ScalarField } from "../contracts/field.js";
|
|
|
4
4
|
import type { ScalarAtom, ScalarForms, ScalarValueType } from "../contracts/scalar-value-type.js";
|
|
5
5
|
import type { JsonValue } from "../runtime/json-value.js";
|
|
6
6
|
import type { OperationIdentity } from "./operation-identity.js";
|
|
7
|
+
/** The Resource names of Contract `C`. */
|
|
7
8
|
export type ResourceKey<C extends Contract> = Extract<keyof C["resources"], string>;
|
|
9
|
+
/** The field names of Resource `K` in Contract `C`. */
|
|
8
10
|
export type FieldKey<C extends Contract, K extends ResourceKey<C>> = Extract<keyof C["resources"][K]["fields"], string>;
|
|
9
11
|
type FieldAt<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>> = C["resources"][K]["fields"][F];
|
|
10
12
|
type ScalarFieldAt<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>> = Extract<FieldAt<C, K, F>, {
|
|
@@ -22,49 +24,15 @@ type RelationFieldKeyOf<C extends Contract, K extends ResourceKey<C>> = {
|
|
|
22
24
|
type CapabilitiesOf<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>> = FieldAt<C, K, F> extends {
|
|
23
25
|
readonly capabilities: infer Capabilities;
|
|
24
26
|
} ? Capabilities : never;
|
|
25
|
-
/**
|
|
26
|
-
* The argument scope a reader with no scope to thread reads a projection
|
|
27
|
-
* capability at.
|
|
28
|
-
*
|
|
29
|
-
* `filter`, `order`, `orderNulls` and `pagination` were measured uniform across
|
|
30
|
-
* every operation variant, so their readers have no scope to be given; and every
|
|
31
|
-
* variant that carries a filter, an order, a cursor or a pagination argument
|
|
32
|
-
* carries it in the unrestricted position — the bulk cells carry none of them.
|
|
33
|
-
* Named rather than inlined so that a member which stops being uniform is found
|
|
34
|
-
* by grepping one word instead of auditing `"record"` string literals.
|
|
35
|
-
*/
|
|
27
|
+
/** The projection position read when no position applies: `"record"`. */
|
|
36
28
|
type UnrestrictedProjection = "record";
|
|
37
|
-
/**
|
|
38
|
-
* The write mirror of {@link UnrestrictedProjection}, and the default for the
|
|
39
|
-
* public write surfaces: a write argument reached through a relation is the
|
|
40
|
-
* unrestricted position, because a scope qualifies the TOP LEVEL of an argument
|
|
41
|
-
* only and does not narrow recursively (see {@link WriteScope}).
|
|
42
|
-
*/
|
|
29
|
+
/** The write position read when no position applies, and the one nested writes use: `"nested"`. */
|
|
43
30
|
type UnrestrictedWrite = "nested";
|
|
44
|
-
/**
|
|
45
|
-
* Whether a capability member's answer holds at one argument scope.
|
|
46
|
-
*
|
|
47
|
-
* The qualified arms state where they hold: a scope list on `select`/`include`,
|
|
48
|
-
* a `scopes` member beside the tokens on `reducers`, `create` and `update`. The
|
|
49
|
-
* unqualified arms state no scope and therefore hold in every one of them —
|
|
50
|
-
* which is what keeps a Contract written before the axis existed meaning exactly
|
|
51
|
-
* what it meant, and what lets an adapter that has not measured the axis say so
|
|
52
|
-
* without losing a capability.
|
|
53
|
-
*
|
|
54
|
-
* Presence is deliberately NOT answered here: `false` and an absent member
|
|
55
|
-
* arrive as unqualified values and would be reported as holding.
|
|
56
|
-
* {@link HasCapability} owns the presence question and asks this one second.
|
|
57
|
-
*/
|
|
31
|
+
/** Whether a capability member's answer holds at one argument scope. */
|
|
58
32
|
type HoldsAtScope<Value, Scope extends ProjectionScope | WriteScope> = Value extends {
|
|
59
33
|
readonly scopes: readonly (infer Stated)[];
|
|
60
34
|
} ? Scope extends Stated ? true : false : Value extends ProjectionScopes ? Scope extends Value[number] ? true : false : true;
|
|
61
|
-
/**
|
|
62
|
-
* The tokens a capability member advertises, whichever arm it is written in — the
|
|
63
|
-
* type-level mirror of `advertisedDirectives` and `advertisedReducers`, and
|
|
64
|
-
* scope-blind for the same reason they are: reading the tokens and deciding where
|
|
65
|
-
* they hold are two questions, and a reader handed both in one answer answers the
|
|
66
|
-
* second by forgetting it. {@link CapabilityTokens} asks both.
|
|
67
|
-
*/
|
|
35
|
+
/** The tokens a capability member advertises, in any argument position. */
|
|
68
36
|
type AdvertisedTokens<Value> = Value extends {
|
|
69
37
|
readonly scopes: readonly WriteScope[];
|
|
70
38
|
readonly directives: readonly (infer Directive)[];
|
|
@@ -93,67 +61,38 @@ type KeysWithCapability<C extends Contract, K extends ResourceKey<C>, Keys exten
|
|
|
93
61
|
[F in Keys]: HasCapability<C, K, F, Capability, Scope> extends true ? F : never;
|
|
94
62
|
}[Keys];
|
|
95
63
|
/**
|
|
96
|
-
* The scalar-form map
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* It is `ScalarForms` itself — the constraint every map satisfies — so it tells a
|
|
100
|
-
* reader nothing about a built-in value, which is the surface every caller had
|
|
101
|
-
* before values were typed. An authoring mirror shared by both request origins (a
|
|
102
|
-
* transaction plan, a hand-written request) cannot know whether its `Date`
|
|
103
|
-
* travels as a `Date` or as an ISO string; a caller that does know passes
|
|
104
|
-
* `ApplicationScalarForms` or `WireScalarForms` and is held to it.
|
|
105
|
-
*
|
|
106
|
-
* Enum members are not a form: they are the same strings on both sides, so an
|
|
107
|
-
* enum-backed value is its member union under every map, this one included.
|
|
64
|
+
* The scalar-form map used when no side of a boundary is named: every built-in
|
|
65
|
+
* value is `unknown`. Pass `ApplicationScalarForms` or `WireScalarForms` to type
|
|
66
|
+
* values. Enum values are their member union under every map.
|
|
108
67
|
*/
|
|
109
68
|
type UnstatedForms = ScalarForms;
|
|
110
|
-
/**
|
|
111
|
-
* Field `F`'s value under `Forms`: the one derivation a result reads
|
|
112
|
-
* (`ScalarValueType`), read here for arguments, so an argument and a result
|
|
113
|
-
* cannot disagree about what a field's value is.
|
|
114
|
-
*/
|
|
69
|
+
/** Field `F`'s value under `Forms`, the same as in results. */
|
|
115
70
|
type ScalarValueAt<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>, Forms extends ScalarForms> = ScalarFieldAt<C, K, F> extends infer Field extends ScalarField<C> ? ScalarValueType<C, Field, Forms> : never;
|
|
116
71
|
/** One entry of field `F`'s value — the whole value when `F` is not a list. */
|
|
117
72
|
type ScalarAtomAt<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>, Forms extends ScalarForms> = ScalarAtom<C, ScalarFieldAt<C, K, F>["type"], Forms>;
|
|
118
73
|
/**
|
|
119
|
-
* A JSON object
|
|
120
|
-
* a
|
|
121
|
-
* `isPlainRecord`), so those positions' value arms leave it out.
|
|
74
|
+
* A JSON object. Positions that accept both a value and an object of operators
|
|
75
|
+
* read a JSON object as the operators, so their value forms leave it out.
|
|
122
76
|
*/
|
|
123
77
|
type JsonObject = Extract<JsonValue, {
|
|
124
78
|
readonly [key: string]: JsonValue;
|
|
125
79
|
}>;
|
|
126
80
|
/**
|
|
127
|
-
* The field-independent shape of one scalar filter: any value, or an object of
|
|
128
|
-
*
|
|
129
|
-
* field's operands through a scalar-form map (see `ScalarFilterFor`) — and it
|
|
130
|
-
* stays exported as the vocabulary's own shape for a caller that holds no
|
|
131
|
-
* Contract.
|
|
81
|
+
* The field-independent shape of one scalar filter: any value, or an object of the
|
|
82
|
+
* operator vocabulary.
|
|
132
83
|
*/
|
|
133
84
|
export type ScalarFilterInput = unknown | Readonly<Partial<Record<ScalarFilterOperator, unknown>>>;
|
|
134
85
|
/**
|
|
135
86
|
* A scalar filter's shorthand equality value: the field's value, minus a JSON
|
|
136
87
|
* object.
|
|
137
|
-
*
|
|
138
|
-
* Every reader of a filter position — the validation layer, the scalar runtime and
|
|
139
|
-
* the adapter — reads it through one discriminant (`runtime/scalar-runtime.ts`
|
|
140
|
-
* `isPlainRecord`): a plain record is an operator object, anything else is a
|
|
141
|
-
* value. So a `Date`, a `Decimal` and a `Uint8Array` are shorthand for their
|
|
142
|
-
* field, and a JSON object is an operator object by construction — `{ equals:
|
|
143
|
-
* document }` carries it. The same exclusion as `not`'s value arm below.
|
|
144
88
|
*/
|
|
145
89
|
type ScalarFilterShorthand<Value> = Exclude<Value, JsonObject>;
|
|
146
90
|
/**
|
|
147
|
-
* A scalar filter's operator object
|
|
148
|
-
* `
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* adapter un-normalized, so core states nothing about them.
|
|
153
|
-
*
|
|
154
|
-
* Which operators a field advertises stays the validation layer's question
|
|
155
|
-
* (`V1006`), exactly as before values were typed: this answers only what each
|
|
156
|
-
* operand is.
|
|
91
|
+
* A scalar filter's operator object: a comparison operand is the field's whole
|
|
92
|
+
* value; `in`, `notIn`, `hasEvery` and `hasSome` take a list of entries; `has`
|
|
93
|
+
* one entry; a `json` field's `string*`/`array*` operand a {@link JsonValue};
|
|
94
|
+
* `not` a value or a nested operator object. `mode`, `isEmpty` and `path` are
|
|
95
|
+
* passed to the adapter as given.
|
|
157
96
|
*/
|
|
158
97
|
type ScalarFilterOperators<Value, Atom, Json> = Readonly<{
|
|
159
98
|
equals?: Value;
|
|
@@ -211,9 +150,13 @@ type IdentifierObject<C extends Contract, K extends ResourceKey<C>, I extends re
|
|
|
211
150
|
} & {
|
|
212
151
|
[F in Exclude<FieldKey<C, K>, I[number]>]?: never;
|
|
213
152
|
}>;
|
|
153
|
+
/** A `where` argument for a unique operation: the values of one identifier. */
|
|
214
154
|
export type UniqueWhereInput<C extends Contract, K extends ResourceKey<C>, Forms extends ScalarForms = UnstatedForms> = ActiveIdentifier<C, K> extends infer I ? I extends readonly string[] ? IdentifierObject<C, K, I, Forms> : never : never;
|
|
155
|
+
/** `"asc"` or `"desc"`. */
|
|
215
156
|
export type SortDirection = "asc" | "desc";
|
|
157
|
+
/** Where `null`s sort: `"first"` or `"last"`. */
|
|
216
158
|
export type NullsOrder = "first" | "last";
|
|
159
|
+
/** How one scalar field sorts: a direction, or a direction and a `nulls` order. */
|
|
217
160
|
export type ScalarOrderInput = SortDirection | Readonly<{
|
|
218
161
|
sort: SortDirection;
|
|
219
162
|
nulls: NullsOrder;
|
|
@@ -223,40 +166,15 @@ type OrderableRelationKey<C extends Contract, K extends ResourceKey<C>> = KeysWi
|
|
|
223
166
|
type OrderableFieldKey<C extends Contract, K extends ResourceKey<C>> = OrderableScalarKey<C, K> | OrderableRelationKey<C, K>;
|
|
224
167
|
type ScalarOrderForField<C extends Contract, K extends ResourceKey<C>, F extends OrderableScalarKey<C, K>> = ScalarFieldAt<C, K, F>["nullable"] extends true ? HasCapability<C, K, F, "orderNulls", UnrestrictedProjection> extends true ? ScalarOrderInput : SortDirection : SortDirection;
|
|
225
168
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* `orderBy
|
|
229
|
-
* reader does not thread a scope.
|
|
230
|
-
*
|
|
231
|
-
* A to-one value is **one** target entry, not an {@link OrderByInput}: the
|
|
232
|
-
* runtime refuses a precedence list there (`validateOrderBy` requires a record
|
|
233
|
-
* at a relation position, V1001), so admitting one would advertise what the
|
|
234
|
-
* validation layer refuses.
|
|
169
|
+
* The `orderBy` value of a relation field: a to-many relation orders by
|
|
170
|
+
* `$count`; a to-one relation takes one entry of the related Resource's
|
|
171
|
+
* `orderBy`, not a list.
|
|
235
172
|
*/
|
|
236
173
|
type RelationOrderForField<C extends Contract, K extends ResourceKey<C>, F extends OrderableRelationKey<C, K> & RelationFieldKeyOf<C, K>> = RelationCardinality<C, K, F> extends "many" ? HasCapabilityToken<C, K, F, "reducers", UnrestrictedProjection, "$count"> extends true ? Readonly<{
|
|
237
174
|
$count: SortDirection;
|
|
238
175
|
}> : never : OrderByEntry<C, RelationTarget<C, K, F>>;
|
|
239
176
|
type OrderValue<C extends Contract, K extends ResourceKey<C>, F extends OrderableFieldKey<C, K>> = F extends OrderableScalarKey<C, K> ? ScalarOrderForField<C, K, F> : F extends OrderableRelationKey<C, K> & RelationFieldKeyOf<C, K> ? RelationOrderForField<C, K, F> : never;
|
|
240
|
-
/**
|
|
241
|
-
* One `orderBy` precedence entry: exactly one orderable field and its value.
|
|
242
|
-
*
|
|
243
|
-
* A to-one relation's value is the target's entry, so a self-relation
|
|
244
|
-
* (`Author.mentor → Author`) or a one-to-one pair makes this type recursive. A
|
|
245
|
-
* type argument is instantiated eagerly, so resolving `OrderByEntry<C, "Author">`
|
|
246
|
-
* needed `OrderValue<…, "mentor">`, which IS `OrderByEntry<C, "Author">`: TS2615,
|
|
247
|
-
* after which the entry degraded to `any` and refused nothing. A mapped property
|
|
248
|
-
* is resolved only when read, by which time the entry it recurses into exists. The
|
|
249
|
-
* projection walk never hit this because its recursion already sits behind an
|
|
250
|
-
* object property (`{ select?: … }`).
|
|
251
|
-
*
|
|
252
|
-
* **No type-level depth cap, deliberately.** The runtime bound is the Contract's
|
|
253
|
-
* `limits.maxNestingDepth` — each to-one hop counts one level, and one past it is
|
|
254
|
-
* V1013 (`operation-nesting.ts` `walkOrderBy`). That limit is a `number` in the
|
|
255
|
-
* Contract, resolved per scope at construction, so no literal exists for a type to
|
|
256
|
-
* count against; a fixed cap would refuse what a Contract with a larger limit
|
|
257
|
-
* accepts. `where` and `select` recurse uncapped for the same reason, and the
|
|
258
|
-
* validation layer refuses past the limit for all three.
|
|
259
|
-
*/
|
|
177
|
+
/** One `orderBy` precedence entry: exactly one orderable field and its value. */
|
|
260
178
|
export type OrderByEntry<C extends Contract, K extends ResourceKey<C>> = {
|
|
261
179
|
[F in OrderableFieldKey<C, K>]: {
|
|
262
180
|
readonly [Only in F]: OrderValue<C, K, Only>;
|
|
@@ -264,15 +182,13 @@ export type OrderByEntry<C extends Contract, K extends ResourceKey<C>> = {
|
|
|
264
182
|
readonly [Other in Exclude<OrderableFieldKey<C, K>, F>]?: never;
|
|
265
183
|
};
|
|
266
184
|
}[OrderableFieldKey<C, K>];
|
|
185
|
+
/** An `orderBy` argument: one entry, or a list in order of precedence. */
|
|
267
186
|
export type OrderByInput<C extends Contract, K extends ResourceKey<C>> = OrderByEntry<C, K> | readonly OrderByEntry<C, K>[];
|
|
187
|
+
/** A `cursor` argument: scalar field values of the row the page starts from. */
|
|
268
188
|
export type CursorInput<C extends Contract, K extends ResourceKey<C>, Forms extends ScalarForms = UnstatedForms> = Readonly<{
|
|
269
189
|
[F in ScalarFieldKeyOf<C, K>]?: ScalarValueAt<C, K, F, Forms>;
|
|
270
190
|
}>;
|
|
271
|
-
/**
|
|
272
|
-
* Scalar `select` carries no scope qualifier — the six scalar members were
|
|
273
|
-
* measured uniform — so the scope reaches this reader only to keep one projection
|
|
274
|
-
* walk asking one question.
|
|
275
|
-
*/
|
|
191
|
+
/** The scalar fields selectable at one projection position. */
|
|
276
192
|
type SelectableScalarKey<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope> = KeysWithCapability<C, K, ScalarFieldKeyOf<C, K>, "select", Scope>;
|
|
277
193
|
type SelectableRelationKey<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope> = KeysWithCapability<C, K, RelationFieldKeyOf<C, K>, "select", Scope>;
|
|
278
194
|
type IncludeRelationKey<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope> = KeysWithCapability<C, K, RelationFieldKeyOf<C, K>, "include", Scope>;
|
|
@@ -307,28 +223,14 @@ type ProjectionChoice<C extends Contract, K extends ResourceKey<C>, Scope extend
|
|
|
307
223
|
select?: never;
|
|
308
224
|
}>;
|
|
309
225
|
/**
|
|
310
|
-
* The argument object one relation entry carries inside a projection.
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* entry's own reducer question and nothing deeper: the target's projection is
|
|
314
|
-
* taken at {@link UnrestrictedProjection}, because a scope qualifies the top
|
|
315
|
-
* level of a projection only and the measurement is explicit that the full
|
|
316
|
-
* surface returns one level in (see {@link ProjectionScope}). A reader who
|
|
317
|
-
* narrowed it recursively would refuse what the ORM accepts.
|
|
226
|
+
* The argument object one relation entry carries inside a projection. `Scope`
|
|
227
|
+
* applies to this entry only; the related rows' own projection is
|
|
228
|
+
* unrestricted.
|
|
318
229
|
*/
|
|
319
230
|
export type RelationProjectionInput<C extends Contract, K extends ResourceKey<C>, F extends RelationFieldKeyOf<C, K> = RelationFieldKeyOf<C, K>, Scope extends ProjectionScope = UnrestrictedProjection, Forms extends ScalarForms = UnstatedForms> = F extends RelationFieldKeyOf<C, K> ? Readonly<NestedWhereArgument<C, K, F, Forms> & NestedOrderArgument<C, K, F> & NestedPaginationArgument<C, K, F, "limit", Forms> & NestedPaginationArgument<C, K, F, "offset", Forms> & NestedPaginationArgument<C, K, F, "cursor", Forms> & ProjectionChoice<C, RelationTarget<C, K, F>, UnrestrictedProjection, RelationAllowsCount<C, K, F, Scope>, Forms>> : never;
|
|
320
231
|
/**
|
|
321
232
|
* One relation entry of a projection: exactly relation `F` of `Keys`, with its
|
|
322
233
|
* argument object, and every other key of `Keys` absent.
|
|
323
|
-
*
|
|
324
|
-
* A projection's entry union is formed whenever its `select`/`include` constraint
|
|
325
|
-
* is — at every call, including one that passes no projection — and a type
|
|
326
|
-
* argument is instantiated when the union is: every relation's {@link
|
|
327
|
-
* RelationProjectionInput} (its nested `where`, `orderBy`, pagination and
|
|
328
|
-
* projection choice) for every relation the Resource has. A mapped property is
|
|
329
|
-
* resolved only when an entry names it, so a call pays for the relations it
|
|
330
|
-
* projects. Measured on the six-resource artifact shape: ≈4,500–6,700
|
|
331
|
-
* instantiations per call whose projection names no relation.
|
|
332
234
|
*/
|
|
333
235
|
type RelationProjectionEntry<C extends Contract, K extends ResourceKey<C>, Keys extends RelationFieldKeyOf<C, K>, F extends Keys, Scope extends ProjectionScope, Forms extends ScalarForms> = {
|
|
334
236
|
readonly [Only in F]: RelationProjectionInput<C, K, Only & RelationFieldKeyOf<C, K>, Scope, Forms>;
|
|
@@ -342,28 +244,23 @@ type IncludeRelationProjectionEntry<C extends Contract, K extends ResourceKey<C>
|
|
|
342
244
|
[F in IncludeRelationKey<C, K, Scope>]: RelationProjectionEntry<C, K, IncludeRelationKey<C, K, Scope>, F, Scope, Forms>;
|
|
343
245
|
}[IncludeRelationKey<C, K, Scope>];
|
|
344
246
|
/**
|
|
345
|
-
* One entry of a `select` argument, at one projection
|
|
346
|
-
*
|
|
347
|
-
* The scope precedes `AllowCount` because it qualifies which fields exist at
|
|
348
|
-
* this position at all, while `AllowCount` only says whether the carrying entry
|
|
349
|
-
* admits its parent's reducer. The default is the unrestricted position, so a
|
|
350
|
-
* reader that states no scope keeps today's surface exactly.
|
|
247
|
+
* One entry of a `select` argument, at one projection position. The default is
|
|
248
|
+
* the unrestricted position.
|
|
351
249
|
*/
|
|
352
250
|
export type ProjectionEntry<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope = UnrestrictedProjection, AllowCount extends boolean = false, Forms extends ScalarForms = UnstatedForms> = SelectableScalarKey<C, K, Scope> | SelectableRelationKey<C, K, Scope> | SelectRelationProjectionEntry<C, K, Scope, Forms> | (AllowCount extends true ? "$count" : never);
|
|
251
|
+
/** A `select` argument: the fields to return. */
|
|
353
252
|
export type SelectInput<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope = UnrestrictedProjection, AllowCount extends boolean = false, Forms extends ScalarForms = UnstatedForms> = readonly ProjectionEntry<C, K, Scope, AllowCount, Forms>[];
|
|
253
|
+
/** An `include` argument: the relations to return with each row. */
|
|
354
254
|
export type IncludeInput<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope = UnrestrictedProjection, Forms extends ScalarForms = UnstatedForms> = readonly (IncludeRelationKey<C, K, Scope> | IncludeRelationProjectionEntry<C, K, Scope, Forms>)[];
|
|
255
|
+
/** A scalar update directive and its operand, such as `{ $increment: 1 }`. */
|
|
355
256
|
export type ScalarMutationAction = Readonly<Partial<Record<ScalarMutationDirective, unknown>>>;
|
|
257
|
+
/** A relation write: one or more relation directives and their payloads. */
|
|
356
258
|
export type RelationMutationAction = Readonly<Partial<Record<RelationMutationDirective, unknown>>>;
|
|
357
|
-
/**
|
|
358
|
-
* Scalar write members carry no scope qualifier — all six scalar members were
|
|
359
|
-
* measured uniform — so the scope reaches this reader only to keep one mutation
|
|
360
|
-
* walk asking one question.
|
|
361
|
-
*/
|
|
259
|
+
/** The scalar fields writable at one stage and write position. */
|
|
362
260
|
type WritableScalarKey<C extends Contract, K extends ResourceKey<C>, Stage extends "create" | "update", Scope extends WriteScope> = KeysWithCapability<C, K, ScalarFieldKeyOf<C, K>, Stage, Scope>;
|
|
363
261
|
/**
|
|
364
|
-
* The relations writable at one stage
|
|
365
|
-
* the unrestricted position
|
|
366
|
-
* what a caller that states no scope means.
|
|
262
|
+
* The relations writable at one stage in one write position. The default is
|
|
263
|
+
* the unrestricted position.
|
|
367
264
|
*/
|
|
368
265
|
export type WritableRelationKey<C extends Contract, K extends ResourceKey<C>, Stage extends "create" | "update", Scope extends WriteScope = UnrestrictedWrite> = KeysWithCapability<C, K, RelationFieldKeyOf<C, K>, Stage, Scope>;
|
|
369
266
|
type ManyOrOne<C extends Contract, K extends ResourceKey<C>, F extends RelationFieldKeyOf<C, K>, Value> = RelationCardinality<C, K, F> extends "many" ? Value | readonly Value[] : Value;
|
|
@@ -399,16 +296,6 @@ type RelationDirectiveValue<C extends Contract, K extends ResourceKey<C>, F exte
|
|
|
399
296
|
declare const NO_ADVERTISED_MEMBER: unique symbol;
|
|
400
297
|
/**
|
|
401
298
|
* A write member that advertises nothing: it accepts `{}` and refuses every key.
|
|
402
|
-
*
|
|
403
|
-
* TypeScript runs no excess-property check against an object type with no known
|
|
404
|
-
* properties, so an empty mapped member would type as `{}` and accept any key
|
|
405
|
-
* silently, leaving it to `V1006` at runtime. One optional member on a
|
|
406
|
-
* module-private symbol keeps the type weak — `{}` still assigns — while giving
|
|
407
|
-
* the excess-property check something to measure against, so the diagnostic names
|
|
408
|
-
* the offending key.
|
|
409
|
-
*
|
|
410
|
-
* The empty case is reachable by design: `directives: []` means "writable, with no
|
|
411
|
-
* directive", distinct from an absent member (see `contracts/field.ts`).
|
|
412
299
|
*/
|
|
413
300
|
type NoAdvertisedMember = {
|
|
414
301
|
readonly [NO_ADVERTISED_MEMBER]?: never;
|
|
@@ -419,16 +306,14 @@ type RelationMutationActionFor<C extends Contract, K extends ResourceKey<C>, F e
|
|
|
419
306
|
[Directive in Extract<CapabilityTokens<C, K, F, Stage, Scope>, RelationMutationDirective>]: RelationDirectiveValue<C, K, F, Directive, Forms>;
|
|
420
307
|
}>>>;
|
|
421
308
|
/**
|
|
422
|
-
* One scalar mutation directive's operand
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
* about it.
|
|
309
|
+
* One scalar mutation directive's operand: one entry of the field (`$push` on a
|
|
310
|
+
* list also takes a list of them). `$unset`'s operand is passed to the adapter as
|
|
311
|
+
* given.
|
|
426
312
|
*/
|
|
427
313
|
type ScalarDirectiveOperand<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>, Directive extends ScalarMutationDirective, Forms extends ScalarForms> = Directive extends "$unset" ? unknown : Directive extends "$push" ? [ScalarFieldAt<C, K, F>["list"]] extends [false] ? ScalarAtomAt<C, K, F, Forms> : ScalarAtomAt<C, K, F, Forms> | readonly ScalarAtomAt<C, K, F, Forms>[] : ScalarAtomAt<C, K, F, Forms>;
|
|
428
314
|
/**
|
|
429
315
|
* The directive object a scalar field accepts at one stage, or `never` when it
|
|
430
|
-
* advertises no directive
|
|
431
|
-
* value would satisfy and so would let any value through beside the typed one.
|
|
316
|
+
* advertises no directive.
|
|
432
317
|
*/
|
|
433
318
|
type ScalarMutationActionFor<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>, Stage extends "create" | "update", Scope extends WriteScope, Forms extends ScalarForms> = [
|
|
434
319
|
Extract<CapabilityTokens<C, K, F, Stage, Scope>, ScalarMutationDirective>
|
|
@@ -446,48 +331,17 @@ type RelationMutationFields<C extends Contract, K extends ResourceKey<C>, Stage
|
|
|
446
331
|
[F in WritableRelationKey<C, K, Stage, Scope>]?: RelationMutationActionFor<C, K, F & RelationFieldKeyOf<C, K>, Stage, Scope, Forms>;
|
|
447
332
|
}>;
|
|
448
333
|
/**
|
|
449
|
-
* A `create` data argument, at one write position.
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* — a `$create` payload, a `$connectOrCreate`'s `create`, an upsert branch — is a
|
|
453
|
-
* write reached through a relation, and a scope qualifies the top level of a
|
|
454
|
-
* write argument only (see {@link WriteScope}).
|
|
334
|
+
* A `create` data argument, at one write position. A write position applies
|
|
335
|
+
* to the top level only; nested writes use the unrestricted position (see
|
|
336
|
+
* {@link WriteScope}).
|
|
455
337
|
*/
|
|
456
338
|
export type CreateDataInput<C extends Contract, K extends ResourceKey<C>, Scope extends WriteScope = UnrestrictedWrite, Forms extends ScalarForms = UnstatedForms> = RefuseEveryKeyWhenEmpty<Readonly<ScalarMutationFields<C, K, "create", Scope, Forms> & RelationMutationFields<C, K, "create", Scope, Forms>>>;
|
|
457
339
|
/** An `update` data argument, at one write position. See {@link CreateDataInput}. */
|
|
458
340
|
export type UpdateDataInput<C extends Contract, K extends ResourceKey<C>, Scope extends WriteScope = UnrestrictedWrite, Forms extends ScalarForms = UnstatedForms> = RefuseEveryKeyWhenEmpty<Readonly<ScalarMutationFields<C, K, "update", Scope, Forms> & RelationMutationFields<C, K, "update", Scope, Forms>>>;
|
|
459
341
|
type QueryProjectionArgs<C extends Contract, K extends ResourceKey<C>, Scope extends ProjectionScope, Forms extends ScalarForms> = ProjectionChoice<C, K, Scope, false, Forms>;
|
|
460
342
|
/**
|
|
461
|
-
* Every standard operation's argument object, with each argument
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
* The map is already keyed by `family.variant`, so binding the scope here is what
|
|
465
|
-
* makes an over-advertised projection or nested write **unrepresentable** at the
|
|
466
|
-
* authoring boundary rather than merely refused at runtime: twelve projection
|
|
467
|
-
* cells and eight data cells, and `create.many`/`update.many` no longer share
|
|
468
|
-
* their projection with `find.many` nor their data with `create.one`.
|
|
469
|
-
*
|
|
470
|
-
* **Two bulk-returning projections** — `create.many` and `update.many` are the
|
|
471
|
-
* row-returning bulk writes, so their projection sits in `"bulkWrite"`. Every
|
|
472
|
-
* other projection-carrying variant reads or writes one addressed record and sits
|
|
473
|
-
* in `"record"`, including a multi-row READ: the axis is the write being bulk, not
|
|
474
|
-
* the row count. `delete.many` is the one cell where that is a judgement rather
|
|
475
|
-
* than a measurement — it is a bulk write that core's grammar gives a projection,
|
|
476
|
-
* and no pilot engine answers it at all, so it keeps the surface it has today
|
|
477
|
-
* instead of being narrowed on a supposition.
|
|
478
|
-
*
|
|
479
|
-
* **Four flat bulk writes** — `create.many`, `create.count`, `update.many` and
|
|
480
|
-
* `update.count` carry a data argument of own columns and own reference fields;
|
|
481
|
-
* the rest admit nested writes. `upsert.unique`'s two branches are both nested.
|
|
482
|
-
*
|
|
483
|
-
* **This binding is core's grammar, not the adapter's routing.** A variant's real
|
|
484
|
-
* scope is an adapter fact and the adapter states it on the advertised variant
|
|
485
|
-
* (`OperationVariantScopes`); a host that routed, say, `update.first` through a
|
|
486
|
-
* bulk-returning call would make this map's `"record"` too generous.
|
|
487
|
-
*
|
|
488
|
-
* An unqualified capability holds in every scope, so a Contract whose adapter has
|
|
489
|
-
* not measured the axis is bound to the same surface it had before the axis
|
|
490
|
-
* existed.
|
|
343
|
+
* Every standard operation's argument object, with each argument at its
|
|
344
|
+
* projection or write position.
|
|
491
345
|
*/
|
|
492
346
|
export type OperationArgumentMap<C extends Contract, K extends ResourceKey<C>, Forms extends ScalarForms = UnstatedForms> = {
|
|
493
347
|
find: {
|
|
@@ -562,16 +416,7 @@ export type OperationArgumentMap<C extends Contract, K extends ResourceKey<C>, F
|
|
|
562
416
|
};
|
|
563
417
|
};
|
|
564
418
|
};
|
|
565
|
-
/**
|
|
566
|
-
* One standard operation's argument object.
|
|
567
|
-
*
|
|
568
|
-
* `Forms` is the scalar-form map its scalar VALUES are read through — data,
|
|
569
|
-
* filters, unique selectors and cursors, at every depth. Unstated, every built-in
|
|
570
|
-
* value is `unknown` ({@link UnstatedForms}); the application façade passes
|
|
571
|
-
* `ApplicationScalarForms`, so a `Date` handed to a `json` field or a number to a
|
|
572
|
-
* `string` one is refused where it is written rather than by `V1001` at runtime.
|
|
573
|
-
* The validation layer stays the guard either way.
|
|
574
|
-
*/
|
|
419
|
+
/** One standard operation's argument object. */
|
|
575
420
|
export type OperationArgumentsFor<C extends Contract, K extends ResourceKey<C>, I extends OperationIdentity, Forms extends ScalarForms = UnstatedForms> = I extends {
|
|
576
421
|
family: infer F;
|
|
577
422
|
variant: infer V;
|
|
@@ -13,12 +13,7 @@ type SelectOf<Args> = Args extends {
|
|
|
13
13
|
type IncludeOf<Args> = Args extends {
|
|
14
14
|
readonly include?: infer Include;
|
|
15
15
|
} ? Exclude<Include, undefined> : never;
|
|
16
|
-
/**
|
|
17
|
-
* The projection argument, held apart so the caller's literal is inferred and
|
|
18
|
-
* nothing else is: only `select`/`include` drive the result, and every other
|
|
19
|
-
* argument stays a plain declared type, which keeps its contextual typing and its
|
|
20
|
-
* excess-property check.
|
|
21
|
-
*/
|
|
16
|
+
/** The projection argument (`select`/`include`) of a call, which decides its result type. */
|
|
22
17
|
type ProjectionArgument<Select, Include> = {
|
|
23
18
|
readonly select?: Select;
|
|
24
19
|
readonly include?: never;
|
|
@@ -37,10 +32,8 @@ type ArgumentList<Rest, Parameter> = Record<never, never> extends Rest ? [args?:
|
|
|
37
32
|
type CallArgumentList<Rest, Parameter, Options> = Record<never, never> extends Rest ? [args?: Parameter, options?: Options] : [args: Parameter, options?: Options];
|
|
38
33
|
type ResourceOperationsOf<C extends Contract, R extends ResourceKey<C>> = C["resources"][R]["operations"];
|
|
39
34
|
/**
|
|
40
|
-
* The
|
|
41
|
-
*
|
|
42
|
-
* The one source every surface maps its calls over, so which operations exist is
|
|
43
|
-
* decided once.
|
|
35
|
+
* The operations Contract `C` advertises: one property per Resource, one per
|
|
36
|
+
* family under it, one identity per variant under that.
|
|
44
37
|
*/
|
|
45
38
|
export type OperationGrammar<C extends Contract> = {
|
|
46
39
|
readonly [R in ResourceKey<C>]: {
|
|
@@ -53,9 +46,9 @@ export type OperationGrammar<C extends Contract> = {
|
|
|
53
46
|
};
|
|
54
47
|
};
|
|
55
48
|
/**
|
|
56
|
-
* An operation's slot: its result, except that a first-style miss
|
|
57
|
-
*
|
|
58
|
-
*
|
|
49
|
+
* An operation's slot: its result, except that a first-style miss is `null`.
|
|
50
|
+
* This is the value a committed transaction or a remote call returns for the
|
|
51
|
+
* operation.
|
|
59
52
|
*/
|
|
60
53
|
export type OperationSlot<I extends OperationIdentity, Result> = I["variant"] extends "first" ? Result | null : Result;
|
|
61
54
|
/**
|
|
@@ -72,13 +65,18 @@ type PlainCall<C extends Contract, R extends ResourceKey<C>, I extends Operation
|
|
|
72
65
|
* projection when it carries one.
|
|
73
66
|
*/
|
|
74
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>;
|
|
68
|
+
/**
|
|
69
|
+
* A deferred operation's arguments: `Forms`, with reference positions opened to a
|
|
70
|
+
* `$ref` typed in `ResultForms` — the forms the source's final data is read in, so a
|
|
71
|
+
* reference carries what its source resolves.
|
|
72
|
+
*/
|
|
75
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>;
|
|
76
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>>>;
|
|
77
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>>>;
|
|
78
76
|
/**
|
|
79
77
|
* One deferred operation: a handle typed `Operation<OperationSlot<…>>` — `$ref`
|
|
80
|
-
* present exactly where the result is one row. A handle is not a request and takes
|
|
81
|
-
*
|
|
78
|
+
* present exactly where the result is one row. A handle is not a request and takes no
|
|
79
|
+
* options.
|
|
82
80
|
*/
|
|
83
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>;
|
|
84
82
|
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ResourceOperations } from "../contracts/resource-operations.js";
|
|
2
|
+
/** A standard operation family: `find`, `create`, `update`, `delete` or `upsert`. */
|
|
2
3
|
export type OperationFamily = Extract<keyof ResourceOperations, string>;
|
|
4
|
+
/** The variants of operation family `F`, such as `many` or `unique`. */
|
|
3
5
|
export type OperationVariant<F extends OperationFamily> = Extract<keyof NonNullable<ResourceOperations[F]>, string>;
|
|
4
|
-
/**
|
|
6
|
+
/** A standard operation's `family` and `variant`. */
|
|
5
7
|
export type OperationIdentity = {
|
|
6
8
|
[F in OperationFamily]: {
|
|
7
9
|
[V in OperationVariant<F>]: {
|
|
@@ -10,5 +12,5 @@ export type OperationIdentity = {
|
|
|
10
12
|
};
|
|
11
13
|
}[OperationVariant<F>];
|
|
12
14
|
}[OperationFamily];
|
|
13
|
-
/** Parses
|
|
15
|
+
/** Parses a family and variant into an {@link OperationIdentity}, or `undefined` when they name no standard operation. */
|
|
14
16
|
export declare function parseOperationIdentity(family: string, variant: string): OperationIdentity | undefined;
|
|
@@ -5,11 +5,8 @@ import type { FieldKey, OperationArgumentsFor, ResourceKey } from "./operation-a
|
|
|
5
5
|
import type { OperationIdentity } from "./operation-identity.js";
|
|
6
6
|
type FieldOf<C extends Contract, K extends ResourceKey<C>, F extends FieldKey<C, K>> = C["resources"][K]["fields"][F];
|
|
7
7
|
/**
|
|
8
|
-
* The
|
|
9
|
-
*
|
|
10
|
-
* Strict, as the runtime is: an absent member, `false`, and a member the Contract
|
|
11
|
-
* widened to `boolean` are all left out, so a write-only field never appears and a
|
|
12
|
-
* widened Contract under-promises rather than over-promises.
|
|
8
|
+
* The fields returned when no projection is given: the scalars whose `select`
|
|
9
|
+
* is exactly `true`. A write-only field never appears.
|
|
13
10
|
*/
|
|
14
11
|
type DefaultKey<C extends Contract, K extends ResourceKey<C>> = {
|
|
15
12
|
[F in FieldKey<C, K>]: FieldOf<C, K, F> extends {
|
|
@@ -19,16 +16,11 @@ type DefaultKey<C extends Contract, K extends ResourceKey<C>> = {
|
|
|
19
16
|
};
|
|
20
17
|
} ? F : never;
|
|
21
18
|
}[FieldKey<C, K>];
|
|
22
|
-
/**
|
|
23
|
-
* The field one projection entry names: a bare key, or a relation entry's key.
|
|
24
|
-
* `$count` passes through and is dropped where every caller intersects the result
|
|
25
|
-
* with the Resource's field keys, which is the one place that knows what a field is.
|
|
26
|
-
*/
|
|
19
|
+
/** The field one projection entry names: a bare key, or a relation entry's key. */
|
|
27
20
|
type EntryKey<Entry> = Entry extends string ? Entry : Entry extends object ? Extract<keyof Entry, string> : never;
|
|
28
21
|
/**
|
|
29
22
|
* The argument object a relation entry carries for field `F`, or `never` when
|
|
30
|
-
* the relation is only named.
|
|
31
|
-
* matching its own apparent members (`"length"` would otherwise).
|
|
23
|
+
* the relation is only named.
|
|
32
24
|
*/
|
|
33
25
|
type EntryArguments<Entry, F extends string> = Entry extends object ? Entry extends {
|
|
34
26
|
readonly [Key in F]: infer Arguments;
|
|
@@ -43,12 +35,8 @@ type ProjectedFields<C extends Contract, K extends ResourceKey<C>, Keys extends
|
|
|
43
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;
|
|
44
36
|
};
|
|
45
37
|
/**
|
|
46
|
-
* One projection level: `select`
|
|
47
|
-
* plus the named relations, and
|
|
48
|
-
*
|
|
49
|
-
* An absent argument (`never`, from {@link EntryArguments}) is tested first and
|
|
50
|
-
* explicitly: it would otherwise distribute to `never`, and inside a one-tuple it
|
|
51
|
-
* would match the `select` arm, because `never` extends everything.
|
|
38
|
+
* One projection level: `select` returns exactly its entries, `include` the
|
|
39
|
+
* default fields plus the named relations, and no projection the default fields.
|
|
52
40
|
*/
|
|
53
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 [{
|
|
54
42
|
readonly select: readonly (infer Entry)[];
|
|
@@ -56,10 +44,8 @@ type ProjectedRecord<C extends Contract, K extends ResourceKey<C>, Arguments, Fo
|
|
|
56
44
|
readonly include: readonly (infer Entry)[];
|
|
57
45
|
}] ? ProjectedFields<C, K, DefaultKey<C, K> | Extract<EntryKey<Entry>, FieldKey<C, K>>, Entry, Forms> : ProjectedFields<C, K, DefaultKey<C, K>, never, Forms>;
|
|
58
46
|
/**
|
|
59
|
-
* A to-many entry whose `select` asks for `$count`: the
|
|
60
|
-
*
|
|
61
|
-
* the row fields are separated here because they are separate facts — the rows
|
|
62
|
-
* are the target's projection, the count is the parent's reducer.
|
|
47
|
+
* A to-many entry whose `select` asks for `$count`: the value is an object with
|
|
48
|
+
* the rows and the count, not the row array.
|
|
63
49
|
*/
|
|
64
50
|
type CountEnvelope<C extends Contract, Target extends ResourceKey<C>, Entry, Forms extends ScalarForms> = [Exclude<Entry, "$count">] extends [never] ? {
|
|
65
51
|
readonly count: number;
|
|
@@ -67,56 +53,24 @@ type CountEnvelope<C extends Contract, Target extends ResourceKey<C>, Entry, For
|
|
|
67
53
|
readonly data: readonly ProjectedFields<C, Target, Extract<EntryKey<Entry>, FieldKey<C, Target>>, Exclude<Entry, "$count">, Forms>[];
|
|
68
54
|
readonly count: number;
|
|
69
55
|
};
|
|
70
|
-
/**
|
|
71
|
-
* The entries of an argument's own `select`, or `never` when it has none.
|
|
72
|
-
* Distributive on purpose: an absent argument (`never`) has no entries.
|
|
73
|
-
*/
|
|
56
|
+
/** The entries of an argument's own `select`, or `never` when it has none. */
|
|
74
57
|
type SelectEntry<Arguments> = Arguments extends {
|
|
75
58
|
readonly select: readonly (infer Entry)[];
|
|
76
59
|
} ? Entry : never;
|
|
77
60
|
/**
|
|
78
|
-
* The value of one relation entry.
|
|
79
|
-
*
|
|
80
|
-
* The nested projection is the target's own, at every depth: a scope qualifies
|
|
81
|
-
* the top level of a projection only (`contracts/capability.ts`
|
|
82
|
-
* `ProjectionScope`), and the argument constraint on {@link OperationResultFor}
|
|
83
|
-
* has already admitted the entry at the position it sits in.
|
|
84
|
-
*
|
|
85
|
-
* A to-many entry is the envelope exactly when its own `select` carries `$count`;
|
|
86
|
-
* otherwise — no argument, `include`, or a `select` without the reducer — it is
|
|
87
|
-
* the row array.
|
|
61
|
+
* The value of one relation entry. A to-many entry is the rows-and-count object
|
|
62
|
+
* when its own `select` asks for `$count`; otherwise the row array.
|
|
88
63
|
*/
|
|
89
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);
|
|
90
65
|
/**
|
|
91
66
|
* The value a standard operation returns in `OperationResponse.data` on success,
|
|
92
|
-
* derived from the Contract, the Resource, the operation identity and the
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* - `count` → `number`;
|
|
96
|
-
* - `many` → `readonly Record[]`;
|
|
97
|
-
* - `first`, `unique`, `one` → the record. **Not `| null`:** absence is an
|
|
98
|
-
* outcome, not a value — `A1001` answers `data: null` for a first-style miss and
|
|
99
|
-
* `A2003` refuses a strict unique one (`runtime/outcome-mapper.ts`
|
|
100
|
-
* `OUTCOME_TABLE`) — so folding `null` into the record would count it twice.
|
|
101
|
-
*
|
|
102
|
-
* `Args` is constrained to the operation's own argument type, so a projection
|
|
103
|
-
* entry the Contract does not advertise at that position — a write-only field, an
|
|
104
|
-
* unadvertised `$count`, a relation outside a bulk write's ceiling — is refused
|
|
105
|
-
* here instead of typed as present.
|
|
106
|
-
*
|
|
107
|
-
* `Forms` is the scalar-form map. It defaults to the application forms, which are
|
|
108
|
-
* what a framework-produced value is in either scope; a transport or a generated
|
|
109
|
-
* client passes the wire forms and gets the same derivation.
|
|
67
|
+
* derived from the Contract, the Resource, the operation identity and the projection
|
|
68
|
+
* argument.
|
|
110
69
|
*/
|
|
111
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>;
|
|
112
71
|
/**
|
|
113
|
-
* {@link OperationResultFor}
|
|
114
|
-
*
|
|
115
|
-
* application façade, which constrains its inferred `select`/`include` at the
|
|
116
|
-
* call. It reads only the projection, so a caller holding just that need not
|
|
117
|
-
* compute the whole argument object a second time to satisfy the constraint.
|
|
118
|
-
*
|
|
119
|
-
* Not exported from the package: one public spelling of the result rule.
|
|
72
|
+
* {@link OperationResultFor}, for a projection already checked against the
|
|
73
|
+
* operation's argument type.
|
|
120
74
|
*/
|
|
121
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>;
|
|
122
76
|
export {};
|