graphddb 0.2.4 → 0.3.0
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/README.md +322 -305
- package/dist/{chunk-GCPEUPAA.js → chunk-6AIAHP3A.js} +1129 -156
- package/dist/{chunk-IQEOJVHI.js → chunk-QEOFIXTN.js} +1194 -60
- package/dist/{chunk-LNESVUTO.js → chunk-QQNP43JL.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +275 -73
- package/dist/index.js +131 -7
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +2 -2
- package/dist/{types-BEeQ_nSd.d.ts → types-xJRn5qkv.d.ts} +1567 -237
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildBridgeBundle,
|
|
4
4
|
normalizeSelectSpec
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QEOFIXTN.js";
|
|
6
6
|
import {
|
|
7
7
|
MetadataRegistry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6AIAHP3A.js";
|
|
9
9
|
|
|
10
10
|
// src/cli.ts
|
|
11
11
|
import { createRequire } from "module";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SelectableOf, g as PrimaryKeyOf, E as Executor,
|
|
2
|
-
export {
|
|
1
|
+
import { S as SelectableOf, g as PrimaryKeyOf, h as RequestContext, i as Middleware, j as ReadRequestKind, k as CtxModel, l as ReadParams, m as ReadRequestCtx, D as DynamoDBOperation, I as Item, E as Executor, n as RetryPolicy, o as ExecutionPlanSpec, p as EntityMetadata, K as KeyDefinition, G as GsiDefinition, F as FieldOptions, q as DynamoType, r as RelationOptions, A as AggregateOptions, s as AggregateValue, t as SelectBuilderSpec, u as RawCondition, v as TransactionSpec, w as Manifest, x as RetryOverride, y as ExecutionPlan, z as FieldMetadata, H as ResolvedKey, R as ReadExecOptions, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, e as BatchExecOptions, T as TransactWriteExecItem, J as CdcEmulatorOptions, L as ChangeHandler, N as Unsubscribe, O as FaultSpec, Q as ConcurrentRecomputeRef, C as ChangeEvent, V as EventLog, X as ReplayOptions, Y as ShardId, Z as RelationMetadata, _ as TransactionItemSpec, $ as Param, a0 as ParamDescriptor, a1 as DefinitionMap, a2 as OperationDefinition, f as DDBModel, M as ModelStatic, a3 as WriteDefinitionOptions, a4 as PartialQueryKeyOf, a5 as StrictSelectSpec, a6 as EntityInput, a7 as UniqueQueryKeyOf, a8 as EntityRef, a9 as ConditionInput, aa as QueryModelContract, ab as QueryMethodSpec, ac as CommandModelContract, ad as CommandMethodSpec, ae as ContractSpec, af as QuerySpec, ag as CommandSpec, ah as ContextSpec, ai as OperationsDocument, aj as AnyOperationDefinition, ak as BridgeBundle, al as ConditionSpec } from './types-xJRn5qkv.js';
|
|
2
|
+
export { am as AggregateMetadata, an as BatchDeleteRequest, ao as BatchGetOptions, ap as BatchGetRequest, aq as BatchGetResult, ar as BatchPutRequest, as as BatchResult, at as BatchWriteRequest, au as CONTRACT_RANGE_FANOUT_CONCURRENCY, av as CdcMode, aw as Change, ax as ChangeBatch, ay as ChangeEventName, az as ClockMode, aA as CollectionEffect, aB as CollectionOptions, aC as Column, aD as ColumnMap, aE as CommandContractMethodSpec, aF as CommandInputShape, aG as CommandMethod, aH as CommandPlan, aI as CommandResolutionTarget, aJ as CommandResultKind, aK as CommandSelectShape, aL as CompiledFragment, aM as ComposeSpec, aN as CondSlot, aO as ConditionCheckInput, aP as Connection, aQ as ContractCallSignature, aR as ContractCardinality, aS as ContractCommandParams, aT as ContractCommandResult, aU as ContractComposeNode, aV as ContractFromRef, aW as ContractInputArity, aX as ContractItem, aY as ContractKeyFieldRef, aZ as ContractKeyInput, a_ as ContractKeyRef, a$ as ContractKeySpec, b0 as ContractKind, b1 as ContractMethodOp, b2 as ContractParamRef, b3 as ContractQueryParams, b4 as ContractResolution, b5 as CounterAggregate, b6 as CounterEffect, b7 as CtxBase, b8 as DEFAULT_MAX_ATTEMPTS, b9 as DEFAULT_RETRY_POLICY, ba as DeleteOptions, bb as DeriveEffect, bc as DerivedEdgeWrite, bd as DerivedUpdate, be as DescriptorBinding, bf as ENTITY_WRITES_MARKER, bg as EdgeEffect, bh as EffectPath, bi as EmbeddedMetadata, bj as EmitEffect, bk as EntityWritesDefinition, bl as EntityWritesShape, bm as ExecutableCommandContract, bn as ExecutableQueryContract, bo as FilterInput, bp as FilterSpec, bq as FragmentInput, br as GsiDefinitionMarker, bs as GsiOptions, bt as IdempotencyEffect, bu as InProcessWriteDescriptor, bv as InputArity, bw as KeyDefinitionMarker, bx as KeySegment, by as KeySlot, bz as KeyStructure, bA as KeyedResult, bB as LIFECYCLE_CONTRACT_MARKER, bC as LifecycleContract, bD as LifecycleEffects, bE as LiteralParam, bF as MaintainConsistency, bG as MaintainEffect, bH as MaintainEvent, bI as MaintainItem, bJ as MaintainTrigger, bK as MaintainUpdateMode, bL as MaintenanceGraph, bM as ManifestEntity, bN as ManifestField, bO as ManifestFieldType, bP as ManifestGsi, bQ as ManifestKey, bR as ManifestRelation, bS as ManifestTable, bT as ModelRef, bU as MutateMode, bV as MutateOptions, bW as MutateParallelResult, bX as MutateTransactionResult, bY as MutationBody, bZ as MutationDescriptorMap, b_ as MutationFragment, b$ as MutationInputProxy, c0 as MutationInputRef, c1 as MutationIntent, c2 as NumberParam, c3 as OperationKind, c4 as OperationSpec, c5 as ParallelOpResult, c6 as ParamKind, c7 as ParamSpec, c8 as ParamStructure, c9 as PersistCtx, ca as PersistOrigin, cb as PlannedCommandMethod, cc as ProjectionMap, cd as ProjectionTransform, ce as ProjectionTransformOp, cf as PutOptions, cg as QueryContractMethodSpec, ch as QueryEnvelopeResult, ci as QueryKeyOf, cj as QueryMethod, ck as QueryResult, cl as RangeConditionSpec, cm as ReadEnvelope, cn as ReadOpCtx, co as ReadOpKind, cp as ReadOperationType, cq as ReadRouteDescriptor, cr as ReadRouteOptions, cs as ReadRouteResult, ct as RecordedCompose, cu as RelationBuilder, cv as RelationConsistency, cw as RelationLimitOptions, cx as RelationPattern, cy as RelationProjection, cz as RelationReadOptions, cA as RelationSelect, cB as RelationSpec, cC as RelationUpdateMode, cD as RelationWriteOptions, cE as RequiresEffect, cF as Resolution, cG as RetryInfo, cH as RetryOperationKind, cI as SPEC_VERSION, cJ as SegmentSpec, cK as SegmentedKey, cL as SelectBuilder, cM as SelectOf, cN as SnapshotEffect, cO as StartingPosition, cP as StreamViewType, cQ as StringParam, cR as TransactionContext, cS as TransactionItemType, cT as UniqueEffect, cU as Updatable, cV as UpdateOptions, cW as WhenSpec, cX as WriteCtx, cY as WriteDescriptor, cZ as WriteEnvelope, c_ as WriteInput, c$ as WriteKind, d0 as WriteLifecyclePhase, d1 as WriteMiddleware, d2 as WriteOperationType, d3 as WriteRecorder, d4 as WriteResultProjection, d5 as attachModelClass, d6 as buildDeleteInput, d7 as buildMaintenanceGraph, d8 as buildPutInput, d9 as buildUpdateInput, da as compileFragment, db as compileMutationPlan, dc as compileSingleFragmentPlan, dd as cond, de as contractOfMethodSpec, df as definePlan, dg as entityWrites, dh as executeBatchGet, di as executeBatchWrite, dj as executeCommandMethod, dk as executeDelete, dl as executeKeyedBatchGet, dm as executePut, dn as executeQueryMethod, dp as executeRangeFanout, dq as executeTransaction, dr as executeUpdate, ds as from, dt as getEntityWrites, du as gsi, dv as identity, dw as isColumn, dx as isCommandModelContract, dy as isCommandPlan, dz as isContractComposeNode, dA as isContractFromRef, dB as isContractKeyFieldRef, dC as isContractKeyRef, dD as isContractParamRef, dE as isEntityWritesDefinition, dF as isKeySegment, dG as isLifecycleContract, dH as isMaintainTrigger, dI as isMutationFragment, dJ as isMutationInputRef, dK as isParam, dL as isPlannedCommandMethod, dM as isQueryModelContract, dN as isRetryableError, dO as isRetryableTransactionCancellation, dP as k, dQ as key, dR as lifecyclePhaseForIntent, dS as maintainTrigger, dT as mintContractKeyFieldRef, dU as mintContractParamRef, dV as mutation, dW as param, dX as preview, dY as publicCommandModel, dZ as publicQueryModel, d_ as query, d$ as resolveLifecycle, e0 as wholeKeysSentinel } from './types-xJRn5qkv.js';
|
|
3
3
|
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
4
4
|
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
|
|
5
5
|
|
|
@@ -32,6 +32,99 @@ type ListOptions<T, S extends SelectableOf<T> = SelectableOf<T>> = {
|
|
|
32
32
|
order?: 'ASC' | 'DESC';
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Read-middleware runtime (issue #138). Drives the registered {@link Middleware}
|
|
37
|
+
* list through the read hook points R1–R5 with the ordering docs/middleware.md
|
|
38
|
+
* specifies:
|
|
39
|
+
*
|
|
40
|
+
* - `before*` (R1 / R2) run **first-registered-first** (FIFO);
|
|
41
|
+
* - `afterFetch` (R3 / R4) and `onError` (R5) run **last-registered-first**
|
|
42
|
+
* (LIFO) — onion nesting without a `next()` callback.
|
|
43
|
+
*
|
|
44
|
+
* All hooks are async-first: each is always `await`ed, so a sync hook (returns
|
|
45
|
+
* `void` / a value) and an async hook (returns a `Promise`) compose uniformly.
|
|
46
|
+
*
|
|
47
|
+
* A {@link MiddlewareRuntime} is constructed ONCE per read at the request entry
|
|
48
|
+
* (R1) from the snapshot of registered middleware + the per-call `context`, then
|
|
49
|
+
* threaded — unchanged — through the root read and every relation fan-out op
|
|
50
|
+
* (the same way `retry` is threaded, see `RelationTraversalOptions`). Threading
|
|
51
|
+
* an immutable runtime (not re-reading the registry per op) keeps a read's hook
|
|
52
|
+
* set stable even if middleware is (un)registered mid-flight, and is
|
|
53
|
+
* concurrency-safe under parallel fan-out (#31).
|
|
54
|
+
*
|
|
55
|
+
* @see docs/middleware.md
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The per-read middleware runtime. Immutable wrt the middleware list and the
|
|
60
|
+
* request `context`; threaded by reference into every fan-out op. A read with no
|
|
61
|
+
* registered middleware is represented by an EMPTY runtime whose `active` is
|
|
62
|
+
* `false`, so the hot read path can skip all hook plumbing with one check.
|
|
63
|
+
*/
|
|
64
|
+
declare class MiddlewareRuntime {
|
|
65
|
+
/** The frozen, registration-ordered middleware snapshot for this read. */
|
|
66
|
+
private readonly chain;
|
|
67
|
+
/** The host-injected per-call context (`{}` when the read passed none). */
|
|
68
|
+
readonly context: RequestContext;
|
|
69
|
+
constructor(chain: readonly Middleware[], context: RequestContext);
|
|
70
|
+
/** `true` when at least one middleware is registered for this read. */
|
|
71
|
+
get active(): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Build the request-level context (R1 / R4 / R5 share it). Pure — no hooks run
|
|
74
|
+
* — so a caller can create it up front and still reference it from R5 even if
|
|
75
|
+
* R1 throws mid-chain.
|
|
76
|
+
*/
|
|
77
|
+
requestCtx(kind: ReadRequestKind, model: CtxModel, params: ReadParams): ReadRequestCtx;
|
|
78
|
+
/**
|
|
79
|
+
* R1 — request entry, before key-resolution / plan. Builds the
|
|
80
|
+
* {@link ReadRequestCtx} then runs every `read.before` FIFO; a hook may mutate
|
|
81
|
+
* `ctx.params` and may `throw` to cancel the read. Returns the (possibly
|
|
82
|
+
* hook-mutated) ctx so the caller can re-read `params` and reuse the SAME ctx
|
|
83
|
+
* for R4 / R5 (shared `state`).
|
|
84
|
+
*/
|
|
85
|
+
runRequestBefore(kind: ReadRequestKind, model: CtxModel, params: ReadParams): Promise<ReadRequestCtx>;
|
|
86
|
+
/**
|
|
87
|
+
* R4 — final hydrated, relation-merged result. Runs every `read.afterFetch`
|
|
88
|
+
* LIFO, threading each hook's return value into the next (onion), and returns
|
|
89
|
+
* the final (possibly replaced) result. `ctx` is the SAME object R1 produced,
|
|
90
|
+
* so a `before`/`afterFetch` pair shares `ctx.state`.
|
|
91
|
+
*/
|
|
92
|
+
runRequestAfter<T>(ctx: ReadRequestCtx, result: T): Promise<T>;
|
|
93
|
+
/**
|
|
94
|
+
* R5 (request-level) — runs every `read.onError` LIFO. A hook may **recover**
|
|
95
|
+
* by RETURNING a non-`undefined` value: it becomes the read's resolved result
|
|
96
|
+
* in place of throwing, and the FIRST such hook (in LIFO order) wins and
|
|
97
|
+
* short-circuits the rest of the chain. If every hook declines (returns
|
|
98
|
+
* `undefined`/`void`), the original error rethrows — preserving the
|
|
99
|
+
* "failed read still rejects" default. (Proposal R5 + appendix A: onError may
|
|
100
|
+
* "rethrow / recover"; hooks are unrestricted.)
|
|
101
|
+
*
|
|
102
|
+
* The recovered value is returned as `T` (the read's result type); its shape
|
|
103
|
+
* is the host's responsibility — a hook recovering a `query` should return an
|
|
104
|
+
* item / `null`, one recovering a `list` a `{ items, cursor }`.
|
|
105
|
+
*/
|
|
106
|
+
runRequestError<T>(ctx: ReadRequestCtx, err: unknown): Promise<T>;
|
|
107
|
+
/**
|
|
108
|
+
* Drive ONE physical op (root read or any fan-out fetch) through R2 → send →
|
|
109
|
+
* R3, with R5 (op-level) on failure:
|
|
110
|
+
*
|
|
111
|
+
* 1. R2 (`read.op.before`, FIFO) — may mutate `ctx.operation`, may `throw`;
|
|
112
|
+
* 2. the caller's `send` runs against the (possibly mutated) operation;
|
|
113
|
+
* 3. R3 (`read.op.afterFetch`, LIFO) — transforms the raw items (onion);
|
|
114
|
+
* 4. on any throw from `send` (or R2 / R3), R5 (`read.op.onError`, LIFO) runs:
|
|
115
|
+
* a hook may **recover** by RETURNING an `Item[]` (those become this op's
|
|
116
|
+
* items and the pipeline continues); the FIRST hook that returns items wins
|
|
117
|
+
* and short-circuits the chain. If none recovers, the original error
|
|
118
|
+
* rethrows.
|
|
119
|
+
*
|
|
120
|
+
* Returns the (possibly R3-replaced, or R5-recovered) items. The `send` closure
|
|
121
|
+
* receives the final operation so a caller that built its operation from
|
|
122
|
+
* `ctx.operation` before this call still observes an R2 mutation (the caller
|
|
123
|
+
* MUST send `ctx.operation`, which this method passes through).
|
|
124
|
+
*/
|
|
125
|
+
runOp(operation: DynamoDBOperation, relationPath: readonly string[], model: CtxModel, send: (operation: DynamoDBOperation) => Promise<Item[]>): Promise<Item[]>;
|
|
126
|
+
}
|
|
127
|
+
|
|
35
128
|
/**
|
|
36
129
|
* The ONE shared `TransactWriteItems` commit orchestration (issue #97).
|
|
37
130
|
*
|
|
@@ -99,6 +192,15 @@ declare class ClientManager {
|
|
|
99
192
|
* read at call time by the default {@link RetryingExecutor}.
|
|
100
193
|
*/
|
|
101
194
|
private static retryPolicy;
|
|
195
|
+
/**
|
|
196
|
+
* The host-runtime read-middleware registry (issue #50 / #138) — a process-wide
|
|
197
|
+
* ordered list of {@link Middleware}, the same global-config + injectable-seam
|
|
198
|
+
* pattern as {@link retryPolicy} / {@link executor}. Registered via
|
|
199
|
+
* {@link DDBModel.use} / {@link use}, snapshotted per read, and NEVER serialized
|
|
200
|
+
* (it never touches the planner / spec / `operations.json`, so the bridge #48 is
|
|
201
|
+
* unaffected). {@link reset} clears it.
|
|
202
|
+
*/
|
|
203
|
+
private static middleware;
|
|
102
204
|
static setClient(client: DynamoDBClient): void;
|
|
103
205
|
static getClient(): DynamoDBClient;
|
|
104
206
|
static getDocumentClient(): Promise<DynamoDBDocumentClient>;
|
|
@@ -129,6 +231,21 @@ declare class ClientManager {
|
|
|
129
231
|
static setRetryPolicy(policy: RetryPolicy | null): void;
|
|
130
232
|
/** The globally-configured retry policy, or `null` for the built-in default. */
|
|
131
233
|
static getRetryPolicy(): RetryPolicy | null;
|
|
234
|
+
/**
|
|
235
|
+
* Register a read {@link Middleware} (issue #50 / #138). Appended last, so its
|
|
236
|
+
* `before*` hooks run last (FIFO) and its `afterFetch` / `onError` hooks run
|
|
237
|
+
* first (LIFO). Mirrors {@link setRetryPolicy}; backs {@link DDBModel.use}.
|
|
238
|
+
*/
|
|
239
|
+
static use(mw: Middleware): void;
|
|
240
|
+
/** Remove every registered read middleware (teardown / tests). Backs {@link DDBModel.clearMiddleware}. */
|
|
241
|
+
static clearMiddleware(): void;
|
|
242
|
+
/**
|
|
243
|
+
* A point-in-time, registration-ordered snapshot of the registered read
|
|
244
|
+
* middleware. A read takes this once at entry (R1) and threads it down, so the
|
|
245
|
+
* read's hook set stays stable even if middleware is registered / cleared
|
|
246
|
+
* mid-flight.
|
|
247
|
+
*/
|
|
248
|
+
static getMiddleware(): readonly Middleware[];
|
|
132
249
|
/** @internal — for testing only */
|
|
133
250
|
static reset(): void;
|
|
134
251
|
}
|
|
@@ -196,71 +313,6 @@ interface RelationExecutionPlan {
|
|
|
196
313
|
readonly resultPaths: readonly string[];
|
|
197
314
|
}
|
|
198
315
|
|
|
199
|
-
type DynamoType = 'S' | 'N' | 'BOOL' | 'B' | 'SS' | 'NS' | 'L' | 'M';
|
|
200
|
-
interface FieldOptions {
|
|
201
|
-
format?: 'datetime' | 'date';
|
|
202
|
-
readonly?: boolean;
|
|
203
|
-
serialize?: (value: unknown) => unknown;
|
|
204
|
-
deserialize?: (value: unknown) => unknown;
|
|
205
|
-
}
|
|
206
|
-
interface FieldMetadata {
|
|
207
|
-
propertyName: string;
|
|
208
|
-
dynamoType: DynamoType;
|
|
209
|
-
options?: FieldOptions;
|
|
210
|
-
/**
|
|
211
|
-
* For a `@literal(...)` field — a `string`-stored field whose value is one of a
|
|
212
|
-
* known, finite set — the allowed literal values, in declaration order (issue
|
|
213
|
-
* #75). Recorded purely as model metadata so a Contract param bound into the
|
|
214
|
-
* field can recover the precise `literal` param-kind from its bind position
|
|
215
|
-
* (`src/spec/contracts.ts`), serializing as `{ type: 'literal', literals: [...] }`
|
|
216
|
-
* instead of the imprecise `'string'`. JSON-safe by construction (a non-empty
|
|
217
|
-
* array of strings). `undefined` for every other field decorator (`@string`,
|
|
218
|
-
* `@number`, …), so plain fields are byte-for-byte unchanged (backward compat).
|
|
219
|
-
*/
|
|
220
|
-
literals?: readonly string[];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
interface KeyDefinition {
|
|
224
|
-
/** The canonical structured key (PK/SK segment lists). */
|
|
225
|
-
segmented: SegmentedKey;
|
|
226
|
-
inputFieldNames: string[];
|
|
227
|
-
}
|
|
228
|
-
interface GsiDefinition {
|
|
229
|
-
indexName: string;
|
|
230
|
-
/** The canonical structured key (PK/SK segment lists). */
|
|
231
|
-
segmented: SegmentedKey;
|
|
232
|
-
inputFieldNames: string[];
|
|
233
|
-
unique: boolean;
|
|
234
|
-
}
|
|
235
|
-
interface RelationLimitOptions {
|
|
236
|
-
default: number;
|
|
237
|
-
max: number;
|
|
238
|
-
}
|
|
239
|
-
interface RelationOptions {
|
|
240
|
-
limit?: RelationLimitOptions;
|
|
241
|
-
order?: 'ASC' | 'DESC';
|
|
242
|
-
}
|
|
243
|
-
interface RelationMetadata {
|
|
244
|
-
type: 'hasMany' | 'hasOne' | 'belongsTo';
|
|
245
|
-
propertyName: string;
|
|
246
|
-
targetFactory: () => new (...args: unknown[]) => unknown;
|
|
247
|
-
keyBinding: Record<string, string>;
|
|
248
|
-
options?: RelationOptions;
|
|
249
|
-
}
|
|
250
|
-
interface EmbeddedMetadata {
|
|
251
|
-
propertyName: string;
|
|
252
|
-
modelFactory: () => new (...args: unknown[]) => unknown;
|
|
253
|
-
}
|
|
254
|
-
interface EntityMetadata {
|
|
255
|
-
tableName: string;
|
|
256
|
-
prefix: string;
|
|
257
|
-
fields: FieldMetadata[];
|
|
258
|
-
primaryKey: KeyDefinition | null;
|
|
259
|
-
gsiDefinitions: GsiDefinition[];
|
|
260
|
-
relations: RelationMetadata[];
|
|
261
|
-
embeddedFields: EmbeddedMetadata[];
|
|
262
|
-
}
|
|
263
|
-
|
|
264
316
|
interface LintRule {
|
|
265
317
|
id: string;
|
|
266
318
|
severity: 'error' | 'warning';
|
|
@@ -284,6 +336,22 @@ declare class Linter {
|
|
|
284
336
|
declare class MetadataRegistry {
|
|
285
337
|
private static store;
|
|
286
338
|
private static _linter;
|
|
339
|
+
/**
|
|
340
|
+
* A monotonically-increasing counter bumped on every change to the set of
|
|
341
|
+
* registered models ({@link register} / {@link clear}). It lets a consumer that
|
|
342
|
+
* caches a structure derived from the whole registry (e.g. the maintenance graph
|
|
343
|
+
* in `src/spec/mutation-command.ts`) detect that the registry has changed since
|
|
344
|
+
* the cache was built and rebuild — closing the silent-drop window where a model
|
|
345
|
+
* registered after a cache build would be invisible to it. Only the membership
|
|
346
|
+
* of {@link store} changes here; per-model lazy finalize ({@link finalize}) does
|
|
347
|
+
* not bump it (it adds no relations/triggers, so it cannot change the graph).
|
|
348
|
+
*/
|
|
349
|
+
private static _generation;
|
|
350
|
+
/**
|
|
351
|
+
* The current registry generation (see {@link _generation}). A consumer caches
|
|
352
|
+
* the value it built against and rebuilds when it no longer matches.
|
|
353
|
+
*/
|
|
354
|
+
static get generation(): number;
|
|
287
355
|
static register(target: Function, metadata: EntityMetadata): void;
|
|
288
356
|
static get(target: Function): EntityMetadata;
|
|
289
357
|
static has(target: Function): boolean;
|
|
@@ -414,9 +482,92 @@ declare const map: FieldDecorator<Record<string, unknown>>;
|
|
|
414
482
|
declare function embedded(modelFactory: () => new (...args: unknown[]) => unknown): (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
415
483
|
|
|
416
484
|
declare function hasMany(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>, options?: RelationOptions): (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
417
|
-
declare function belongsTo(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string
|
|
485
|
+
declare function belongsTo(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>, options?: RelationOptions): (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
418
486
|
declare function hasOne(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>): (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
419
487
|
|
|
488
|
+
/**
|
|
489
|
+
* `@aggregate` — a **scalar-aggregate** field decorator (Epic #118 §5.2 counter /
|
|
490
|
+
* latest preset; issue #122).
|
|
491
|
+
*
|
|
492
|
+
* Where `@hasMany` / `@belongsTo` declare a *navigation* (a relation yielding
|
|
493
|
+
* model instances) and `@string` / `@number` declare a *stored* attribute,
|
|
494
|
+
* `@aggregate` declares a **scalar value derived by aggregating a source
|
|
495
|
+
* entity's rows**. It is a field (the decorated property holds a `number` /
|
|
496
|
+
* `string`), but — like a relation — it carries a source `targetFactory` +
|
|
497
|
+
* `keyBinding` selecting the rows it aggregates. The declaration surface mirrors
|
|
498
|
+
* the RFC §5.2 example:
|
|
499
|
+
*
|
|
500
|
+
* ```ts
|
|
501
|
+
* @model({ table: 'AppTable', prefix: 'THREAD' })
|
|
502
|
+
* class ThreadSummaryModel extends DDBModel {
|
|
503
|
+
* @string threadId!: string;
|
|
504
|
+
*
|
|
505
|
+
* @aggregate(() => PostModel, { threadId: 'threadId' }, {
|
|
506
|
+
* pattern: 'counter', value: count(),
|
|
507
|
+
* write: { maintainedOn: ['Post.created', 'Post.removed'] },
|
|
508
|
+
* })
|
|
509
|
+
* postCount!: number;
|
|
510
|
+
*
|
|
511
|
+
* @aggregate(() => PostModel, { threadId: 'threadId' }, {
|
|
512
|
+
* pattern: 'counter', value: max('createdAt'),
|
|
513
|
+
* write: { maintainedOn: ['Post.created'] },
|
|
514
|
+
* })
|
|
515
|
+
* lastPostAt!: string;
|
|
516
|
+
* }
|
|
517
|
+
* ```
|
|
518
|
+
*
|
|
519
|
+
* ## Scope (issue #122)
|
|
520
|
+
*
|
|
521
|
+
* This is the **declaration surface only** — the decorator records an
|
|
522
|
+
* {@link AggregateMetadata} into its own collector array (drained by `@model`
|
|
523
|
+
* into `EntityMetadata.aggregates`), exactly as the relation decorators push to
|
|
524
|
+
* the relation collector. The aggregation *effect* (maintenance graph #124,
|
|
525
|
+
* compile injection #125, runtime #127) is out of scope and consumes this
|
|
526
|
+
* metadata later.
|
|
527
|
+
*
|
|
528
|
+
* ## Vocabulary reuse (no double definition)
|
|
529
|
+
*
|
|
530
|
+
* `options.pattern` is the shared {@link RelationPattern} (typically `'counter'`)
|
|
531
|
+
* and `options.write` is the shared {@link RelationWriteOptions} — `maintainedOn`
|
|
532
|
+
* triggers on the `created|updated|removed` event vocabulary plus
|
|
533
|
+
* `consistency` (`transactional|eventual`) / `updateMode` (`mutation|stream`).
|
|
534
|
+
* Both were defined by B (#121) in `src/metadata/types.ts` and are **reused**
|
|
535
|
+
* here, never re-defined.
|
|
536
|
+
*
|
|
537
|
+
* @param targetFactory - Resolves the source entity whose rows are aggregated
|
|
538
|
+
* (lazy, mirroring the relation decorators, to tolerate circular imports).
|
|
539
|
+
* @param keyBinding - The key binding selecting the source rows
|
|
540
|
+
* (target key field → source field).
|
|
541
|
+
* @param options - The aggregate preset / value / maintenance-write declaration.
|
|
542
|
+
*/
|
|
543
|
+
declare function aggregate(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>, options: AggregateOptions): (_value: undefined, context: ClassFieldDecoratorContext) => void;
|
|
544
|
+
/**
|
|
545
|
+
* Value helper for an `@aggregate` field: the **count** aggregation — the
|
|
546
|
+
* cardinality of source rows matched by the key binding (Epic #118 §5.2
|
|
547
|
+
* `counter` preset, `count()`). It takes no source field (it counts rows, not a
|
|
548
|
+
* value), so the decorated field is a `number` (e.g. `postCount!: number`).
|
|
549
|
+
*
|
|
550
|
+
* Produces the {@link AggregateValue} IR node `{ op: 'count' }`. This is the
|
|
551
|
+
* standalone, recorder-free authoring helper used directly in the decorator
|
|
552
|
+
* argument (mirroring the standalone `preview(...)` / `identity(...)` projection
|
|
553
|
+
* helpers A (#120) exposes for relation options).
|
|
554
|
+
*/
|
|
555
|
+
declare function count(): AggregateValue;
|
|
556
|
+
/**
|
|
557
|
+
* Value helper for an `@aggregate` field: the **max** aggregation — the maximum
|
|
558
|
+
* value of a named source `field` across the rows matched by the key binding
|
|
559
|
+
* (Epic #118 §5.2 `counter` / latest preset, `max('createdAt')`). The decorated
|
|
560
|
+
* field's type matches the source field's (e.g. `lastPostAt!: string` ←
|
|
561
|
+
* `max('createdAt')`).
|
|
562
|
+
*
|
|
563
|
+
* Produces the {@link AggregateValue} IR node `{ op: 'max', field }`.
|
|
564
|
+
*
|
|
565
|
+
* @param field - The source field whose maximum is tracked (e.g. `'createdAt'`).
|
|
566
|
+
* @throws if `field` is not a non-empty string (an aggregation over no source
|
|
567
|
+
* field is meaningless — a defensive runtime check mirroring `@literal`'s).
|
|
568
|
+
*/
|
|
569
|
+
declare function max(field: string): AggregateValue;
|
|
570
|
+
|
|
420
571
|
declare class TableMapping {
|
|
421
572
|
private static mapping;
|
|
422
573
|
static set(mapping: Record<string, string>): void;
|
|
@@ -558,6 +709,14 @@ interface QueryOptions {
|
|
|
558
709
|
* "What to fetch" stays declarative; "what object to load it onto" is host-side.
|
|
559
710
|
*/
|
|
560
711
|
hydrate?: (raw: Record<string, unknown> | null) => unknown;
|
|
712
|
+
/**
|
|
713
|
+
* Host-injected per-call read context (issue #50 / #138) — exposed to every
|
|
714
|
+
* read hook (R1–R5) as `ctx.context`, and threaded UNCHANGED to every relation
|
|
715
|
+
* fan-out op so a hook (e.g. a tenant-scope R2 filter) applies across the root
|
|
716
|
+
* read AND the fan-out fetches. A host-language value, NEVER serialized into the
|
|
717
|
+
* SSoT / `operations.json` (the bridge #48 is unaffected). Absent ⇒ `{}`.
|
|
718
|
+
*/
|
|
719
|
+
context?: RequestContext;
|
|
561
720
|
}
|
|
562
721
|
declare function executeQuery(modelClass: Function, key: Record<string, unknown>, selectSpec: Record<string, unknown>, options?: QueryOptions): Promise<Record<string, unknown> | null>;
|
|
563
722
|
|
|
@@ -580,6 +739,28 @@ interface ListInput {
|
|
|
580
739
|
* retry. Omit to use the configured (or built-in default) policy.
|
|
581
740
|
*/
|
|
582
741
|
retry?: RetryOverride;
|
|
742
|
+
/**
|
|
743
|
+
* Host-injected per-call read context (issue #50 / #138) — exposed to every
|
|
744
|
+
* read hook as `ctx.context`. Used only when this `list` is the read ENTRY
|
|
745
|
+
* point (the public `DDBModel.list` / a `list` envelope route): a fresh
|
|
746
|
+
* {@link MiddlewareRuntime} is built from it. Ignored when a relation fan-out
|
|
747
|
+
* threads an already-built {@link mw} (the runtime then carries the root read's
|
|
748
|
+
* context). Absent ⇒ `{}`.
|
|
749
|
+
*/
|
|
750
|
+
context?: RequestContext;
|
|
751
|
+
/**
|
|
752
|
+
* @internal The per-read middleware runtime, threaded UNCHANGED from a relation
|
|
753
|
+
* fan-out (issue #138) so the hasMany Query's op-level hooks (R2/R3/R5) fire
|
|
754
|
+
* with the root read's context + the fan-out's {@link relationPath}. When absent
|
|
755
|
+
* at the entry point, one is built from {@link context}.
|
|
756
|
+
*/
|
|
757
|
+
mw?: MiddlewareRuntime;
|
|
758
|
+
/**
|
|
759
|
+
* @internal The relation path to THIS list read — `[]` (or absent) for a
|
|
760
|
+
* top-level `list`; the fan-out leg (e.g. `['orders']`) for a hasMany Query.
|
|
761
|
+
* Populates the op-level ctx's `relationPath` (issue #138).
|
|
762
|
+
*/
|
|
763
|
+
relationPath?: readonly string[];
|
|
583
764
|
}
|
|
584
765
|
/**
|
|
585
766
|
* Public list result returned by `DDBModel.list()`. Contains exactly the
|
|
@@ -978,10 +1159,14 @@ declare function decodePerKeyCursor(cursor: string, expectedKey: Record<string,
|
|
|
978
1159
|
/**
|
|
979
1160
|
* Creates a Linter pre-loaded with rules safe for Entity registration.
|
|
980
1161
|
*
|
|
981
|
-
* Rules included: no-scan, require-limit, gsi-ambiguity, missing-gsi,
|
|
982
|
-
*
|
|
983
|
-
*
|
|
984
|
-
*
|
|
1162
|
+
* Rules included: no-scan, require-limit, gsi-ambiguity, missing-gsi,
|
|
1163
|
+
* relation-depth, same-partition-preset, plus the Epic #118 Phase 1 maintenance
|
|
1164
|
+
* validators (issue #126): missing-context, 400kb, hot-partition, fan-out,
|
|
1165
|
+
* multi-maintainer-same-row. The maintenance validators are no-ops for any
|
|
1166
|
+
* relation that does not declare `write.maintainedOn`, so unannotated models are
|
|
1167
|
+
* unaffected. query-boundary is excluded because it flags non-unique GSIs which
|
|
1168
|
+
* are valid for list() operations; boundary enforcement is handled at runtime by
|
|
1169
|
+
* the planner's boundary-check.
|
|
985
1170
|
*/
|
|
986
1171
|
declare function createDefaultLinter(): Linter;
|
|
987
1172
|
|
|
@@ -1031,6 +1216,23 @@ interface RelationTraversalOptions {
|
|
|
1031
1216
|
* grouping / bound and observe the traversal execute accordingly.
|
|
1032
1217
|
*/
|
|
1033
1218
|
plan?: RelationExecutionPlan;
|
|
1219
|
+
/**
|
|
1220
|
+
* The per-read middleware runtime (issue #50 / #138), threaded UNCHANGED from
|
|
1221
|
+
* the read's entry point into every relation fan-out fetch — exactly like
|
|
1222
|
+
* `retry`. Each fan-out send is wrapped so the op-level hooks R2 (before send) /
|
|
1223
|
+
* R3 (raw items) / R5 (op error) fire for that physical op too, with
|
|
1224
|
+
* `ctx.relationPath` identifying the fan-out leg (`['orders']`,
|
|
1225
|
+
* `['orders','product']`, …) and `ctx.model` the relation's target model.
|
|
1226
|
+
* Absent → {@link NO_MIDDLEWARE} (no hooks).
|
|
1227
|
+
*/
|
|
1228
|
+
mw?: MiddlewareRuntime;
|
|
1229
|
+
/**
|
|
1230
|
+
* The relation path from the root read to the CURRENT traversal level — `[]`
|
|
1231
|
+
* at the root, extended by each relation's property name as the traversal
|
|
1232
|
+
* recurses. Used only to populate `ctx.relationPath` for the op-level hooks
|
|
1233
|
+
* (R2/R3/R5). Threaded alongside {@link mw}.
|
|
1234
|
+
*/
|
|
1235
|
+
relationPath?: readonly string[];
|
|
1034
1236
|
}
|
|
1035
1237
|
/**
|
|
1036
1238
|
* Validates that the select depth does not exceed maxDepth.
|
|
@@ -2126,4 +2328,4 @@ declare function assertBundleSerializable(bundle: BridgeBundle): void;
|
|
|
2126
2328
|
*/
|
|
2127
2329
|
declare function buildBridgeBundle(queries?: DefinitionMap, commands?: DefinitionMap, registry?: typeof MetadataRegistry, transactions?: Record<string, TransactionDefinition>, contractInputs?: ContractInputs): BridgeBundle;
|
|
2128
2330
|
|
|
2129
|
-
export { type AnyModelContract, AnyOperationDefinition, BATCH_GET_MAX_KEYS, BATCH_WRITE_MAX_ITEMS, BatchExecOptions, BatchGetExecInput, BatchWriteExecItem, BridgeBundle, type BuiltContracts, CdcEmulator, CdcEmulatorOptions, ChangeEvent, ChangeHandler, ClientManager, type CollectParams, CommandMethodSpec, CommandModelContract, CommandSpec, ConcurrentRecomputeRef, type ConditionExpressionResult, ConditionInput, ConditionSpec, type ContextOwnership, type ContextOwnershipMap, ContextSpec, type ContractBoundaryViolation, type ContractInputs, type ContractMap, type ContractN1Violation, ContractSpec, DDBModel, DefinitionMap, DeleteInput, DynamoDBOperation, DynamoExecutor,
|
|
2331
|
+
export { AggregateOptions, AggregateValue, type AnyModelContract, AnyOperationDefinition, BATCH_GET_MAX_KEYS, BATCH_WRITE_MAX_ITEMS, BatchExecOptions, BatchGetExecInput, BatchWriteExecItem, BridgeBundle, type BuiltContracts, CdcEmulator, CdcEmulatorOptions, ChangeEvent, ChangeHandler, ClientManager, type CollectParams, CommandMethodSpec, CommandModelContract, CommandSpec, ConcurrentRecomputeRef, type ConditionExpressionResult, ConditionInput, ConditionSpec, type ContextOwnership, type ContextOwnershipMap, ContextSpec, type ContractBoundaryViolation, type ContractInputs, type ContractMap, type ContractN1Violation, ContractSpec, CtxModel, DDBModel, DefinitionMap, DeleteInput, DynamoDBOperation, DynamoExecutor, DynamoType, EDGE_WRITES_MARKER, type EdgeLifecycle, type EdgeWriteDeclaration, type EdgeWriteRecorder, type EdgeWritesDefinition, EntityMetadata, EntityRef, EventLog, ExecutionPlan, Executor, ExecutorResult, type ExplainInput, FaultSpec, FieldMetadata, FieldOptions, type FilterExpressionResult, GsiDefinition, Item, KeyDefinition, type LintResult, type LintRule, Linter, type ListInput, type ListOptions, MAX_TRANSACT_ITEMS, Manifest, MetadataRegistry, Middleware, type ModelOptions, ModelStatic, OLD_VALUE_NAMESPACE, OperationDefinition, OperationsDocument, Param, ParamDescriptor, type Parameterize, PartialQueryKeyOf, type PerKeyCursorEnvelope, type PlanInput, PrimaryKeyOf, type ProjectionResult, PutInput, QueryMethodSpec, QueryModelContract, type QueryOptions$1 as QueryOptions, QuerySpec, RawCondition, ReadExecOptions, ReadParams, ReadRequestCtx, ReadRequestKind, RelationMetadata, RelationOptions, type RelationTraversalOptions, ReplayOptions, RequestContext, ResolvedKey, RetryOverride, RetryPolicy, RetryingExecutor, SelectableOf, ShardId, TableMapping, TransactWriteExecItem, type TransactionDefinition, TransactionItemSpec, type TransactionParamShape, type TransactionRef, TransactionSpec, type TxConditionCheckOptions, type TxForEachInstruction, type TxForEachOptions, type TxInstruction, type TxRecorder, type TxWriteInstruction, type TxWriteOptions, UniqueQueryKeyOf, type UpdateExpressionResult, UpdateInput, type WhenComparison, WriteDefinitionOptions, WriteExecOptions, WriteResult, aggregate, assertBundleSerializable, assertContractBoundaries, assertContractN1Safe, assertJsonSerializable, assertSupportedCondition, belongsTo, binary, boolean, buildBridgeBundle, buildConditionExpression, buildContexts, buildContracts, buildManifest, buildOperations, buildProjection, buildQuerySpec, buildTransactionSpec, buildTransactions, buildUpdateExpression, collectContractBoundaryViolations, collectContractN1Violations, compileFilterExpression, count, createCdcEmulator, createDefaultLinter, datetime, decodeCursor, decodePerKeyCursor, defineCommands, defineDelete, defineList, definePut, defineQueries, defineQuery, defineTransaction, defineTransactions, defineUpdate, deriveEdgeWriteItems, deriveEdgeWriteItemsFor, deriveModelEdgeWriteItems, derivePrefix, detectRelationFields, edgeWrites, embedded, encodeCursor, encodePerKeyCursor, evaluateFilter, execute, executeDeclarativeTransaction, executeExplain, executeList, executeQuery, expandTransaction, field, getEdgeWrites, getImplicitKeyFields, gsiAmbiguityRule, hasMany, hasOne, hydrate, isEdgeWritesDefinition, isSelectBuilder, isTransactionRef, list, literal, map, max, missingGsiRule, model, noScanRule, number, numberSet, plan, queryBoundaryRule, relationDepthRule, requireLimitRule, resolveKey, resolveRelations, serializeContractKey, serializeFieldValue, string, stringSet, validateDepth, validateGsiAmbiguity, when };
|