graphddb 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
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, q as ModelKind, F as FieldOptions, r as DynamoType, s as ProjectionTransform, t as MaintainEvent, u as MembershipPredicate, v as MaintainConsistency, w as MaintainUpdateMode, x as MembershipPredicateOp, y as RelationOptions, A as AggregateOptions, z as AggregateValue, H as SelectBuilderSpec, J as RawCondition, L as TransactionSpec, N as Manifest, O as RetryOverride, Q as ExecutionPlan, V as FieldMetadata, X 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, Y as CdcEmulatorOptions, Z as ChangeHandler, _ as Unsubscribe, $ as FaultSpec, a0 as ConcurrentRecomputeRef, C as ChangeEvent, a1 as EventLog, a2 as ReplayOptions, a3 as ShardId, a4 as ViewDefinition, a5 as RelationMetadata, a6 as TransactionItemSpec, a7 as MaintainEffect, M as ModelStatic, f as DDBModel, a8 as Param, a9 as ParamDescriptor, aa as DefinitionMap, ab as OperationDefinition, ac as WriteDefinitionOptions, ad as PartialQueryKeyOf, ae as StrictSelectSpec, af as ReadDefinitionOptions, ag as EntityInput, ah as UniqueQueryKeyOf, ai as EntityRef, aj as ConditionInput, ak as QueryModelContract, al as QueryMethodSpec, am as CommandModelContract, an as CommandMethodSpec, ao as ContractSpec, ap as QuerySpec, aq as CommandSpec, ar as ContextSpec, as as OperationsDocument, at as AnyOperationDefinition, au as BridgeBundle, av as ConditionSpec } from './types-BWOrWcbd.js';
2
- export { aw as AggregateMetadata, ax as BatchDeleteRequest, ay as BatchGetOptions, az as BatchGetRequest, aA as BatchGetResult, aB as BatchPutRequest, aC as BatchResult, aD as BatchWriteRequest, aE as CONTRACT_RANGE_FANOUT_CONCURRENCY, aF as CdcMode, aG as Change, aH as ChangeBatch, aI as ChangeEventName, aJ as ClockMode, aK as CollectionEffect, aL as CollectionOptions, aM as Column, aN as ColumnMap, aO as CommandContractMethodSpec, aP as CommandInputShape, aQ as CommandMethod, aR as CommandPlan, aS as CommandResolutionTarget, aT as CommandResultKind, aU as CommandSelectShape, aV as CompiledFragment, aW as ComposeSpec, aX as CondSlot, aY as ConditionCheckInput, aZ as Connection, a_ as ContractCallSignature, a$ as ContractCardinality, b0 as ContractCommandParams, b1 as ContractCommandResult, b2 as ContractComposeNode, b3 as ContractFromRef, b4 as ContractInputArity, b5 as ContractItem, b6 as ContractKeyFieldRef, b7 as ContractKeyInput, b8 as ContractKeyRef, b9 as ContractKeySpec, ba as ContractKind, bb as ContractMethodOp, bc as ContractParamRef, bd as ContractQueryParams, be as ContractResolution, bf as CounterAggregate, bg as CounterEffect, bh as CtxBase, bi as DEFAULT_MAX_ATTEMPTS, bj as DEFAULT_RETRY_POLICY, bk as DeleteOptions, bl as DeriveEffect, bm as DerivedEdgeWrite, bn as DerivedUpdate, bo as DescriptorBinding, bp as ENTITY_WRITES_MARKER, bq as EdgeEffect, br as EffectPath, bs as EmbeddedMetadata, bt as EmitEffect, bu as EntityWritesDefinition, bv as EntityWritesShape, bw as ExecutableCommandContract, bx as ExecutableQueryContract, by as FilterInput, bz as FilterSpec, bA as FragmentInput, bB as GsiDefinitionMarker, bC as GsiOptions, bD as IdempotencyEffect, bE as InProcessWriteDescriptor, bF as InputArity, bG as KeyDefinitionMarker, bH as KeySegment, bI as KeySlot, bJ as KeyStructure, bK as KeyedResult, bL as LIFECYCLE_CONTRACT_MARKER, bM as LifecycleContract, bN as LifecycleEffects, bO as LiteralParam, bP as MaintainItem, bQ as MaintainTrigger, bR as MaintenanceGraph, bS as ManifestEntity, bT as ManifestField, bU as ManifestFieldType, bV as ManifestGsi, bW as ManifestKey, bX as ManifestRelation, bY as ManifestTable, bZ as MembershipEffect, b_ as ModelRef, b$ as MutateMode, c0 as MutateOptions, c1 as MutateParallelResult, c2 as MutateTransactionResult, c3 as MutationBody, c4 as MutationDescriptorMap, c5 as MutationFragment, c6 as MutationInputProxy, c7 as MutationInputRef, c8 as MutationIntent, c9 as NumberParam, ca as OperationKind, cb as OperationSpec, cc as ParallelOpResult, cd as ParamKind, ce as ParamSpec, cf as ParamStructure, cg as PersistCtx, ch as PersistOrigin, ci as PlannedCommandMethod, cj as ProjectionMap, ck as ProjectionTransformOp, cl as PutOptions, cm as QueryContractMethodSpec, cn as QueryEnvelopeResult, co as QueryKeyOf, cp as QueryMethod, cq as QueryResult, cr as RangeConditionSpec, cs as ReadEnvelope, ct as ReadOpCtx, cu as ReadOpKind, cv as ReadOperationType, cw as ReadRouteDescriptor, cx as ReadRouteOptions, cy as ReadRouteResult, cz as RecordedCompose, cA as RelationBuilder, cB as RelationConsistency, cC as RelationLimitOptions, cD as RelationPattern, cE as RelationProjection, cF as RelationReadOptions, cG as RelationSelect, cH as RelationSpec, cI as RelationUpdateMode, cJ as RelationWriteOptions, cK as RequiresEffect, cL as Resolution, cM as RetryInfo, cN as RetryOperationKind, cO as SPEC_VERSION, cP as SegmentSpec, cQ as SegmentedKey, cR as SelectBuilder, cS as SelectOf, cT as SnapshotEffect, cU as StartingPosition, cV as StreamViewType, cW as StringParam, cX as TransactionContext, cY as TransactionItemType, cZ as UniqueEffect, c_ as Updatable, c$ as UpdateOptions, d0 as ViewSourceSlice, d1 as WhenSpec, d2 as WriteCtx, d3 as WriteDescriptor, d4 as WriteEnvelope, d5 as WriteInput, d6 as WriteKind, d7 as WriteLifecyclePhase, d8 as WriteMiddleware, d9 as WriteOperationType, da as WriteRecorder, db as WriteResultProjection, dc as attachModelClass, dd as buildDeleteInput, de as buildMaintenanceGraph, df as buildPutInput, dg as buildUpdateInput, dh as collectViewDefinitions, di as compileFragment, dj as compileMutationPlan, dk as compileSingleFragmentPlan, dl as cond, dm as contractOfMethodSpec, dn as definePlan, dp as entityWrites, dq as executeBatchGet, dr as executeBatchWrite, ds as executeCommandMethod, dt as executeDelete, du as executeKeyedBatchGet, dv as executePut, dw as executeQueryMethod, dx as executeRangeFanout, dy as executeTransaction, dz as executeUpdate, dA as from, dB as getEntityWrites, dC as gsi, dD as identity, dE as isColumn, dF as isCommandModelContract, dG as isCommandPlan, dH as isContractComposeNode, dI as isContractFromRef, dJ as isContractKeyFieldRef, dK as isContractKeyRef, dL as isContractParamRef, dM as isEntityWritesDefinition, dN as isKeySegment, dO as isLifecycleContract, dP as isMaintainTrigger, dQ as isMutationFragment, dR as isMutationInputRef, dS as isParam, dT as isPlannedCommandMethod, dU as isQueryModelContract, dV as isRetryableError, dW as isRetryableTransactionCancellation, dX as k, dY as key, dZ as lifecyclePhaseForIntent, d_ as maintainTrigger, d$ as mintContractKeyFieldRef, e0 as mintContractParamRef, e1 as mutation, e2 as param, e3 as preview, e4 as publicCommandModel, e5 as publicQueryModel, e6 as query, e7 as resolveLifecycle, e8 as wholeKeysSentinel } from './types-BWOrWcbd.js';
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, q as ModelKind, F as FieldOptions, r as DynamoType, s as ProjectionTransform, t as MaintainEvent, u as MembershipPredicate, v as MaintainConsistency, w as MaintainUpdateMode, x as MembershipPredicateOp, y as RelationOptions, A as AggregateOptions, z as AggregateValue, H as SelectBuilderSpec, J as RawCondition, L as TransactionSpec, N as Manifest, O as RetryOverride, Q as ExecutionPlan, V as FieldMetadata, X 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, Y as CdcEmulatorOptions, Z as ChangeHandler, _ as Unsubscribe, $ as FaultSpec, a0 as ConcurrentRecomputeRef, C as ChangeEvent, a1 as EventLog, a2 as ReplayOptions, a3 as ShardId, a4 as ViewDefinition, a5 as RelationMetadata, a6 as TransactionItemSpec, a7 as MaintainEffect, M as ModelStatic, f as DDBModel, a8 as Param, a9 as ParamDescriptor, aa as DefinitionMap, ab as OperationDefinition, ac as WriteDefinitionOptions, ad as PartialQueryKeyOf, ae as StrictSelectSpec, af as ReadDefinitionOptions, ag as EntityInput, ah as UniqueQueryKeyOf, ai as EntityRef, aj as ConditionInput, ak as QueryModelContract, al as QueryMethodSpec, am as CommandModelContract, an as CommandMethodSpec, ao as ContractSpec, ap as QuerySpec, aq as CommandSpec, ar as ContextSpec, as as OperationsDocument, at as AnyOperationDefinition, au as BridgeBundle, av as ConditionSpec } from './types-B9rJ1z3H.js';
2
+ export { aw as AggregateMetadata, ax as BatchDeleteRequest, ay as BatchGetOptions, az as BatchGetRequest, aA as BatchGetResult, aB as BatchPutRequest, aC as BatchResult, aD as BatchWriteRequest, aE as CONTRACT_RANGE_FANOUT_CONCURRENCY, aF as CdcMode, aG as CdcModelRegistry, aH as CdcSubscribeHandlers, aI as Change, aJ as ChangeBatch, aK as ChangeEventName, aL as ClockMode, aM as CollectionEffect, aN as CollectionOptions, aO as Column, aP as ColumnMap, aQ as CommandContractMethodSpec, aR as CommandInputShape, aS as CommandMethod, aT as CommandPlan, aU as CommandResolutionTarget, aV as CommandResultKind, aW as CommandSelectShape, aX as CompiledFragment, aY as ComposeSpec, aZ as CondSlot, a_ as ConditionCheckInput, a$ as Connection, b0 as ContractCallSignature, b1 as ContractCardinality, b2 as ContractCommandParams, b3 as ContractCommandResult, b4 as ContractComposeNode, b5 as ContractFromRef, b6 as ContractInputArity, b7 as ContractItem, b8 as ContractKeyFieldRef, b9 as ContractKeyInput, ba as ContractKeyRef, bb as ContractKeySpec, bc as ContractKind, bd as ContractMethodOp, be as ContractParamRef, bf as ContractQueryParams, bg as ContractResolution, bh as CounterAggregate, bi as CounterEffect, bj as CtxBase, bk as DEFAULT_MAX_ATTEMPTS, bl as DEFAULT_RETRY_POLICY, bm as DeleteOptions, bn as DeriveEffect, bo as DerivedEdgeWrite, bp as DerivedUpdate, bq as DescriptorBinding, br as ENTITY_WRITES_MARKER, bs as EdgeEffect, bt as EffectPath, bu as EmbeddedMetadata, bv as EmitEffect, bw as EntityWritesDefinition, bx as EntityWritesShape, by as ExecutableCommandContract, bz as ExecutableQueryContract, bA as FilterInput, bB as FilterSpec, bC as FragmentInput, bD as GsiDefinitionMarker, bE as GsiOptions, bF as IdempotencyEffect, bG as InProcessWriteDescriptor, bH as InputArity, bI as KeyDefinitionMarker, bJ as KeySegment, bK as KeySlot, bL as KeyStructure, bM as KeyedResult, bN as LIFECYCLE_CONTRACT_MARKER, bO as LifecycleContract, bP as LifecycleEffects, bQ as LiteralParam, bR as MaintainItem, bS as MaintainTrigger, bT as MaintenanceGraph, bU as ManifestEntity, bV as ManifestField, bW as ManifestFieldType, bX as ManifestGsi, bY as ManifestKey, bZ as ManifestRelation, b_ as ManifestTable, b$ as MembershipEffect, c0 as ModelRef, c1 as MutateMode, c2 as MutateOptions, c3 as MutateParallelResult, c4 as MutateTransactionResult, c5 as MutationBody, c6 as MutationDescriptorMap, c7 as MutationFragment, c8 as MutationInputProxy, c9 as MutationInputRef, ca as MutationIntent, cb as NumberParam, cc as OperationKind, cd as OperationSpec, ce as ParallelOpResult, cf as ParamKind, cg as ParamSpec, ch as ParamStructure, ci as PersistCtx, cj as PersistOrigin, ck as PlannedCommandMethod, cl as ProjectionMap, cm as ProjectionTransformOp, cn as PutOptions, co as QueryContractMethodSpec, cp as QueryEnvelopeResult, cq as QueryKeyOf, cr as QueryMethod, cs as QueryResult, ct as RangeConditionSpec, cu as ReadEnvelope, cv as ReadOpCtx, cw as ReadOpKind, cx as ReadOperationType, cy as ReadRouteDescriptor, cz as ReadRouteOptions, cA as ReadRouteResult, cB as RecordedCompose, cC as RelationBuilder, cD as RelationConsistency, cE as RelationLimitOptions, cF as RelationPattern, cG as RelationProjection, cH as RelationReadOptions, cI as RelationSelect, cJ as RelationSpec, cK as RelationUpdateMode, cL as RelationWriteOptions, cM as RequiresEffect, cN as Resolution, cO as RetryInfo, cP as RetryOperationKind, cQ as SPEC_VERSION, cR as SegmentSpec, cS as SegmentedKey, cT as SelectBuilder, cU as SelectOf, cV as SnapshotEffect, cW as StartingPosition, cX as StreamViewType, cY as StringParam, cZ as SubscribeHandler, c_ as SubscribeHandlers, c$ as TransactionContext, d0 as TransactionItemType, d1 as UniqueEffect, d2 as Updatable, d3 as UpdateOptions, d4 as ViewSourceSlice, d5 as WhenSpec, d6 as WriteCtx, d7 as WriteDescriptor, d8 as WriteEnvelope, d9 as WriteInput, da as WriteKind, db as WriteLifecyclePhase, dc as WriteMiddleware, dd as WriteOperationType, de as WriteRecorder, df as WriteResultProjection, dg as attachModelClass, dh as buildDeleteInput, di as buildMaintenanceGraph, dj as buildPutInput, dk as buildSubscribeHandler, dl as buildUpdateInput, dm as collectViewDefinitions, dn as compileFragment, dp as compileMutationPlan, dq as compileSingleFragmentPlan, dr as cond, ds as contractOfMethodSpec, dt as definePlan, du as entityWrites, dv as executeBatchGet, dw as executeBatchWrite, dx as executeCommandMethod, dy as executeDelete, dz as executeKeyedBatchGet, dA as executePut, dB as executeQueryMethod, dC as executeRangeFanout, dD as executeTransaction, dE as executeUpdate, dF as from, dG as getEntityWrites, dH as gsi, dI as identity, dJ as isColumn, dK as isCommandModelContract, dL as isCommandPlan, dM as isContractComposeNode, dN as isContractFromRef, dO as isContractKeyFieldRef, dP as isContractKeyRef, dQ as isContractParamRef, dR as isEntityWritesDefinition, dS as isKeySegment, dT as isLifecycleContract, dU as isMaintainTrigger, dV as isMutationFragment, dW as isMutationInputRef, dX as isParam, dY as isPlannedCommandMethod, dZ as isQueryModelContract, d_ as isRetryableError, d$ as isRetryableTransactionCancellation, e0 as k, e1 as key, e2 as lifecyclePhaseForIntent, e3 as maintainTrigger, e4 as mintContractKeyFieldRef, e5 as mintContractParamRef, e6 as mutation, e7 as param, e8 as preview, e9 as publicCommandModel, ea as publicQueryModel, eb as query, ec as resolveLifecycle, ed as wholeKeysSentinel } from './types-B9rJ1z3H.js';
3
3
  import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
4
4
  import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
5
5
 
@@ -356,6 +356,19 @@ declare class MetadataRegistry {
356
356
  static get(target: Function): EntityMetadata;
357
357
  static has(target: Function): boolean;
358
358
  static getAll(): Map<Function, EntityMetadata>;
359
+ /**
360
+ * Snapshot of the entities that are **already finalized**, WITHOUT triggering
361
+ * finalize on any pending entity (unlike {@link getAll}). This is the safe view
362
+ * for a cross-entity lint rule that runs *inside* `finalize`: eagerly
363
+ * finalizing the rest of the registry from within a finalize pass would
364
+ * re-enter (and duplicate) the in-progress entity's finalize. A whole-registry
365
+ * rule instead reasons over the already-finalized peers plus the entity
366
+ * currently being checked; any conflicting pair is caught when the later of the
367
+ * two finalizes (both are present by then).
368
+ *
369
+ * @internal — for cross-entity linter rules.
370
+ */
371
+ static getFinalized(): Map<Function, EntityMetadata>;
359
372
  static get linter(): Linter;
360
373
  static set linter(linter: Linter);
361
374
  /** Resets linter to the default built-in rule set. */
@@ -484,6 +497,48 @@ interface FieldDecorator<T> extends FieldDecoratorFn<T> {
484
497
  * `literals` set.
485
498
  */
486
499
  declare function literal<const L extends string>(...values: readonly [L, ...L[]]): FieldDecoratorFn<L>;
500
+ /**
501
+ * `@ttl` — the **DynamoDB Time-To-Live** field decorator (issue #172, Epic #167 —
502
+ * CFn generator C4). It marks the model's TTL attribute: the Number field holding
503
+ * the **epoch-seconds** expiry timestamp DynamoDB reads to auto-delete the item.
504
+ *
505
+ * ## Standalone, number-pinned (not composed with `@number`)
506
+ *
507
+ * `@ttl` is a **standalone** semantic decorator — it records the field's storage
508
+ * type (`dynamoType: 'N'`) itself, exactly as `@datetime` records `'S'` + a format
509
+ * and `@literal` records `'S'` + a literal set. It is NOT composed with `@number`
510
+ * (a `@number @ttl` stack). Two reasons:
511
+ *
512
+ * 1. **A valid TTL attribute is always a Number** (epoch seconds) — there is no
513
+ * string/boolean TTL — so the storage type is not a free choice the author
514
+ * should have to (re)state. Folding `'N'` into `@ttl` removes the redundant
515
+ * second decorator and the ordering/consistency question a two-decorator stack
516
+ * would raise (which wins if they disagreed?).
517
+ * 2. It matches the module idiom: every semantic decorator here is self-contained
518
+ * and pins exactly one storage type; none composes with another.
519
+ *
520
+ * ## Loud-reject (the most-feared silent-drop class in this repo)
521
+ *
522
+ * - **Non-number field → compile error.** The decorator is pinned to `number`
523
+ * (its `context` is `ClassFieldDecoratorContext<unknown, number | undefined>`),
524
+ * so `@ttl expiresAt!: string` fails to type-check — the SAME cross-type
525
+ * mechanism that makes `@number age!: string` an error. A TTL on a non-Number
526
+ * attribute can never be declared (DynamoDB would silently never expire it).
527
+ * - **More than one `@ttl` per (physical) table → throws.** DynamoDB allows
528
+ * exactly one TTL attribute per table. A second `@ttl` on the same model throws
529
+ * at `@model` registration; two `@ttl` fields on DIFFERENT entities sharing one
530
+ * physical table throw at manifest build (where all table siblings are known).
531
+ *
532
+ * ## Runtime behaviour
533
+ *
534
+ * A `@ttl` field is a plain stored Number at runtime — no special serialization,
535
+ * hydration, or key handling (it is not a key attribute). The decorator only
536
+ * records metadata (`dynamoType: 'N'`, `ttl: true`); the TTL *effect* is a table
537
+ * property DynamoDB applies, emitted into the generated CloudFormation
538
+ * `TimeToLiveSpecification` (never into `AttributeDefinitions`, which holds key
539
+ * attributes only). So it needs no runtime-serialization conformance change.
540
+ */
541
+ declare const ttl: FieldDecoratorFn<number>;
487
542
  declare const string: FieldDecorator<string>;
488
543
  declare const number: FieldDecorator<number>;
489
544
  declare const boolean: FieldDecorator<boolean>;
@@ -868,6 +923,51 @@ declare function count(): AggregateValue;
868
923
  */
869
924
  declare function max(field: string): AggregateValue;
870
925
 
926
+ /**
927
+ * `@cdcProjected()` — mark a source model **CDC-parseable** (issue #153).
928
+ *
929
+ * ## What it is
930
+ *
931
+ * External projection means projecting a source model's changes onto an external
932
+ * sink (BigQuery / OpenSearch / …) over CDC (DynamoDB Streams). graphddb owns only
933
+ * the **parse → typed record** contract; the sink write / dedup / delivery live in
934
+ * the consumer's CDC infrastructure, OUTSIDE the boundary (see
935
+ * `docs/cdc-projection.md`). `@cdcProjected()` is the model-level opt-in that
936
+ * enables that contract on a model:
937
+ *
938
+ * - `Model.fromChange(event)` (the pure `(event) => [old, new]` typed mapper) is
939
+ * gated on it — calling it on an un-annotated model throws (and is a compile
940
+ * error via the type surface);
941
+ * - `DDBModel.subscribe(handlers)` routes CDC events only to `@cdcProjected` models;
942
+ * - the codegen reads the flag to emit the `CdcModelRegistry` module augmentation
943
+ * that types `subscribe`'s handlers by model name.
944
+ *
945
+ * ## No runtime side effect
946
+ *
947
+ * The decorator carries NO runtime — it does not subscribe, write, capture, or hook
948
+ * anything. It only flips a capability bit
949
+ * ({@link import('../metadata/types.js').EntityMetadata.cdcProjected}) on the model's
950
+ * metadata. Like `@maintainedFrom`, it is a CLASS-LEVEL decorator that runs BEFORE
951
+ * the topmost `@model` (TC39 bottom-up class-decorator ordering), so it pushes into
952
+ * the module-level collector and `@model` drains it. Stacking it above or below
953
+ * other class decorators carries no meaning.
954
+ *
955
+ * @example
956
+ * ```ts
957
+ * @model({ table: 'Orders', prefix: 'ORDER' })
958
+ * @cdcProjected()
959
+ * class OrderModel extends DDBModel {
960
+ * static readonly keys = key<{ orderId: string }>((c) => ({
961
+ * pk: k`ORDER#${c.orderId}`, sk: k`META`,
962
+ * }));
963
+ * @string orderId!: string;
964
+ * @string status!: string;
965
+ * @datetime updatedAt!: Date;
966
+ * }
967
+ * ```
968
+ */
969
+ declare function cdcProjected(): (_target: Function, _context: ClassDecoratorContext) => void;
970
+
871
971
  declare class TableMapping {
872
972
  private static mapping;
873
973
  static set(mapping: Record<string, string>): void;
@@ -1516,6 +1616,46 @@ declare function createMaintenanceDrain(opts?: MaintenanceDrainOptions): Mainten
1516
1616
  */
1517
1617
  declare function createMaintenanceDrainHandler(opts?: MaintenanceDrainOptions): ChangeHandler;
1518
1618
 
1619
+ /**
1620
+ * `fromChange` — the pure `(event) => [old, new]` typed mapper (issue #153).
1621
+ *
1622
+ * This is graphddb's HALF of the CDC-projection boundary (see
1623
+ * `docs/cdc-projection.md`): it parses a raw {@link ChangeEvent}'s `oldImage` /
1624
+ * `newImage` into typed model instances and does nothing downstream of that (no
1625
+ * sink write, no dedup, no subscription). `Model.fromChange(event)` on `DDBModel`
1626
+ * delegates here.
1627
+ *
1628
+ * The two responsibilities packed into one call are **routing** and **parse**:
1629
+ *
1630
+ * - Routing — an event that is not for `modelClass` yields `[null, null]`. A valid
1631
+ * event for the class always has at least one non-null image, so `[null, null]`
1632
+ * is an unambiguous "not for this model" signal and no separate `owns()` guard is
1633
+ * needed. The match is by `event.model` (the resolved model name the write path /
1634
+ * emulator stamps) when present, falling back to the model's PK prefix
1635
+ * (`keys.pk` begins with `<prefix>`) when the event carries no `model`.
1636
+ * - Parse — each present image is hydrated via the existing {@link hydrate}
1637
+ * (raw item → typed value, INCLUDING ISO 8601 → `Date` for `@datetime` and
1638
+ * embedded reconstruction), returning ALL fields (no projection — narrowing does
1639
+ * not reduce network cost since the image is already on the stream). The hydrated
1640
+ * plain record is then loaded onto a fresh model instance so the result is a
1641
+ * genuine `InstanceType` (like the read path's `{ hydrate }` factory option).
1642
+ *
1643
+ * The image side present per event kind mirrors DynamoDB Streams:
1644
+ *
1645
+ * - INSERT → `[null, new ]`
1646
+ * - MODIFY → `[old, new ]`
1647
+ * - REMOVE → `[old, null]`
1648
+ */
1649
+
1650
+ /**
1651
+ * Parse a {@link ChangeEvent} into the `[oldRecord, newRecord]` tuple for the given
1652
+ * model. Returns `[null, null]` when the event is not for this model (routing). The
1653
+ * caller (`DDBModel.fromChange`) supplies the resolved metadata + class; this
1654
+ * function is the runtime core and is deliberately model-name-string driven so
1655
+ * `DDBModel.subscribe` can reuse it when routing a batch.
1656
+ */
1657
+ declare function parseChange<T extends object>(event: ChangeEvent, metadata: EntityMetadata, modelName: string, modelClass: new () => T): [T | null, T | null];
1658
+
1519
1659
  /**
1520
1660
  * Per-key cursor envelope for batched `range` (`list`) contract methods (issue
1521
1661
  * #62, CQRS single-service runtime; spec `docs/cqrs-contract.md`,
@@ -1608,6 +1748,13 @@ declare function decodePerKeyCursor(cursor: string, expectedKey: Record<string,
1608
1748
  * unaffected. query-boundary is excluded because it flags non-unique GSIs which
1609
1749
  * are valid for list() operations; boundary enforcement is handled at runtime by
1610
1750
  * the planner's boundary-check.
1751
+ *
1752
+ * Also includes cfn-schema-consistency (issue #169): a whole-table validator
1753
+ * that rejects entities sharing a physical table with an ambiguous base
1754
+ * KeySchema, inconsistently-shared GSI index names, or more than 20 unioned
1755
+ * GSIs — the CFn deploy-consistency user-error class, caught statically at
1756
+ * finalize. It is additive: a single entity on its own table with ≤ 20 GSIs is
1757
+ * never affected.
1611
1758
  */
1612
1759
  declare function createDefaultLinter(): Linter;
1613
1760
 
@@ -3003,4 +3150,4 @@ declare function assertBundleSerializable(bundle: BridgeBundle): void;
3003
3150
  */
3004
3151
  declare function buildBridgeBundle(queries?: DefinitionMap, commands?: DefinitionMap, registry?: typeof MetadataRegistry, transactions?: Record<string, TransactionDefinition>, contractInputs?: ContractInputs): BridgeBundle;
3005
3152
 
3006
- 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, type DriftReport, 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, type HasManyVersionedCallback, type HasManyVersionedOptions, type HasOneVersionedCallback, type HasOneVersionedOptions, Item, KeyDefinition, type LintResult, type LintRule, Linter, type ListInput, type ListOptions, MAINT_OUTBOX_PK_PREFIX, MAX_TRANSACT_ITEMS, MaintainConsistency, MaintainEffect, MaintainEvent, MaintainUpdateMode, type MaintainedFromCallback, type MaintainedFromOptions, MaintenanceDrain, type MaintenanceDrainOptions, type MaintenanceRebuildOptions, MaintenanceRebuilder, Manifest, MembershipPredicate, MembershipPredicateOp, MetadataRegistry, Middleware, type ModelOptions, ModelStatic, OLD_VALUE_NAMESPACE, OperationDefinition, OperationsDocument, Param, ParamDescriptor, type Parameterize, PartialQueryKeyOf, type PerKeyCursorEnvelope, type PlanInput, PrimaryKeyOf, type ProjectionResult, ProjectionTransform, type ProjectionValue, PutInput, QueryMethodSpec, QueryModelContract, type QueryOptions$1 as QueryOptions, QuerySpec, RawCondition, ReadExecOptions, ReadParams, ReadRequestCtx, ReadRequestKind, type RebuildResult, RelationMetadata, RelationOptions, type RelationTraversalOptions, ReplayOptions, RequestContext, ResolvedKey, RetryOverride, RetryPolicy, RetryingExecutor, SelectableOf, type SelfProxy, type SelfRef, ShardId, type SourceProxy, type SourceRef, 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 VersionedHistoryOptions, type VersionedLatestOptions, ViewDefinition, 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, createMaintenanceDrain, createMaintenanceDrainHandler, createMaintenanceRebuilder, 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, maintainedFrom, map, max, missingGsiRule, model, noScanRule, number, numberSet, plan, queryBoundaryRule, relationDepthRule, requireLimitRule, resolveKey, resolveRelations, serializeContractKey, serializeFieldValue, string, stringSet, validateDepth, validateGsiAmbiguity, when, whenMember };
3153
+ 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, type DriftReport, 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, type HasManyVersionedCallback, type HasManyVersionedOptions, type HasOneVersionedCallback, type HasOneVersionedOptions, Item, KeyDefinition, type LintResult, type LintRule, Linter, type ListInput, type ListOptions, MAINT_OUTBOX_PK_PREFIX, MAX_TRANSACT_ITEMS, MaintainConsistency, MaintainEffect, MaintainEvent, MaintainUpdateMode, type MaintainedFromCallback, type MaintainedFromOptions, MaintenanceDrain, type MaintenanceDrainOptions, type MaintenanceRebuildOptions, MaintenanceRebuilder, Manifest, MembershipPredicate, MembershipPredicateOp, MetadataRegistry, Middleware, type ModelOptions, ModelStatic, OLD_VALUE_NAMESPACE, OperationDefinition, OperationsDocument, Param, ParamDescriptor, type Parameterize, PartialQueryKeyOf, type PerKeyCursorEnvelope, type PlanInput, PrimaryKeyOf, type ProjectionResult, ProjectionTransform, type ProjectionValue, PutInput, QueryMethodSpec, QueryModelContract, type QueryOptions$1 as QueryOptions, QuerySpec, RawCondition, ReadExecOptions, ReadParams, ReadRequestCtx, ReadRequestKind, type RebuildResult, RelationMetadata, RelationOptions, type RelationTraversalOptions, ReplayOptions, RequestContext, ResolvedKey, RetryOverride, RetryPolicy, RetryingExecutor, SelectableOf, type SelfProxy, type SelfRef, ShardId, type SourceProxy, type SourceRef, 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 VersionedHistoryOptions, type VersionedLatestOptions, ViewDefinition, 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, cdcProjected, collectContractBoundaryViolations, collectContractN1Violations, compileFilterExpression, count, createCdcEmulator, createDefaultLinter, createMaintenanceDrain, createMaintenanceDrainHandler, createMaintenanceRebuilder, 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, maintainedFrom, map, max, missingGsiRule, model, noScanRule, number, numberSet, parseChange, plan, queryBoundaryRule, relationDepthRule, requireLimitRule, resolveKey, resolveRelations, serializeContractKey, serializeFieldValue, string, stringSet, ttl, validateDepth, validateGsiAmbiguity, when, whenMember };
package/dist/index.js CHANGED
@@ -51,7 +51,6 @@ import {
51
51
  from,
52
52
  getEdgeWrites,
53
53
  getImplicitKeyFields,
54
- hydrate,
55
54
  isCommandModelContract,
56
55
  isCommandPlan,
57
56
  isContractComposeNode,
@@ -64,7 +63,6 @@ import {
64
63
  isMutationInputRef,
65
64
  isPlannedCommandMethod,
66
65
  isQueryModelContract,
67
- isSelectBuilder,
68
66
  isTransactionRef,
69
67
  mapWithConcurrency,
70
68
  mintContractKeyFieldRef,
@@ -79,7 +77,7 @@ import {
79
77
  validateDepth,
80
78
  when,
81
79
  wholeKeysSentinel
82
- } from "./chunk-G5RWWBAL.js";
80
+ } from "./chunk-FI63YKK5.js";
83
81
  import {
84
82
  CdcEmulator,
85
83
  MAINT_OUTBOX_PK_PREFIX,
@@ -91,7 +89,7 @@ import {
91
89
  orderAndTrimCollection,
92
90
  pathField,
93
91
  projectFrom
94
- } from "./chunk-BROCT574.js";
92
+ } from "./chunk-EMJHTUA4.js";
95
93
  import {
96
94
  BATCH_GET_MAX_KEYS,
97
95
  BATCH_WRITE_MAX_ITEMS,
@@ -112,6 +110,7 @@ import {
112
110
  buildDeleteInput,
113
111
  buildMaintenanceGraph,
114
112
  buildPutInput,
113
+ buildSubscribeHandler,
115
114
  buildUpdateExpression,
116
115
  buildUpdateInput,
117
116
  collapseSameKeyItems,
@@ -129,6 +128,7 @@ import {
129
128
  getEntityWrites,
130
129
  gsi,
131
130
  gsiAmbiguityRule,
131
+ hydrate,
132
132
  identity,
133
133
  isColumn,
134
134
  isEntityWritesDefinition,
@@ -139,6 +139,7 @@ import {
139
139
  isRawCondition,
140
140
  isRetryableError,
141
141
  isRetryableTransactionCancellation,
142
+ isSelectBuilder,
142
143
  k,
143
144
  key,
144
145
  lifecyclePhaseForIntent,
@@ -146,6 +147,7 @@ import {
146
147
  missingGsiRule,
147
148
  noScanRule,
148
149
  param,
150
+ parseChange,
149
151
  preview,
150
152
  relationDepthRule,
151
153
  requireLimitRule,
@@ -154,7 +156,7 @@ import {
154
156
  resolveModelClass,
155
157
  segmentFieldNames,
156
158
  serializeFieldValue
157
- } from "./chunk-CPTV3H2U.js";
159
+ } from "./chunk-B3GWIWT6.js";
158
160
 
159
161
  // src/metadata/prefix.ts
160
162
  function derivePrefix(customPrefix, className) {
@@ -206,6 +208,7 @@ var pendingEmbedded = [];
206
208
  var pendingRelations = [];
207
209
  var pendingAggregates = [];
208
210
  var pendingMaintainedFrom = [];
211
+ var pendingCdcProjected = false;
209
212
  function collectField(field2) {
210
213
  pendingFields.push(field2);
211
214
  }
@@ -221,6 +224,9 @@ function collectAggregate(aggregate2) {
221
224
  function collectMaintainedFrom(decl) {
222
225
  pendingMaintainedFrom.push(decl);
223
226
  }
227
+ function collectCdcProjected() {
228
+ pendingCdcProjected = true;
229
+ }
224
230
  function drainFields() {
225
231
  const result = pendingFields;
226
232
  pendingFields = [];
@@ -246,6 +252,11 @@ function drainMaintainedFrom() {
246
252
  pendingMaintainedFrom = [];
247
253
  return result;
248
254
  }
255
+ function drainCdcProjected() {
256
+ const result = pendingCdcProjected;
257
+ pendingCdcProjected = false;
258
+ return result;
259
+ }
249
260
 
250
261
  // src/decorators/model.ts
251
262
  function model(options) {
@@ -255,6 +266,7 @@ function model(options) {
255
266
  const relations = drainRelations();
256
267
  const aggregates = drainAggregates();
257
268
  const maintainedFrom2 = drainMaintainedFrom();
269
+ const cdcProjected2 = drainCdcProjected();
258
270
  const prefix = derivePrefix(options.prefix, context.name);
259
271
  const kind = options.kind ?? "entity";
260
272
  if (kind === "entity" && maintainedFrom2.length > 0) {
@@ -267,6 +279,13 @@ function model(options) {
267
279
  `@model on '${String(context.name)}': \`kind: '${kind}'\` declares a maintained view but no \`@maintainedFrom(...)\` source is stacked. A view with no source is maintained by nothing \u2014 add at least one \`@maintainedFrom\` decorator.`
268
280
  );
269
281
  }
282
+ const ttlFields = fields.filter((f) => f.ttl === true);
283
+ if (ttlFields.length > 1) {
284
+ throw new Error(
285
+ `@model on '${String(context.name)}': ${ttlFields.length} \`@ttl\` fields (${ttlFields.map((f) => `'${f.propertyName}'`).join(", ")}) are declared, but DynamoDB allows exactly one TTL attribute per table. Mark a single field \`@ttl\`.`
286
+ );
287
+ }
288
+ const ttlAttribute = ttlFields.length === 1 ? ttlFields[0].propertyName : void 0;
270
289
  MetadataRegistry.register(target, {
271
290
  tableName: options.table,
272
291
  prefix,
@@ -278,7 +297,9 @@ function model(options) {
278
297
  embeddedFields,
279
298
  kind,
280
299
  ...options.description !== void 0 ? { description: options.description } : {},
281
- maintainedFrom: maintainedFrom2
300
+ ...cdcProjected2 ? { cdcProjected: cdcProjected2 } : {},
301
+ maintainedFrom: maintainedFrom2,
302
+ ...ttlAttribute !== void 0 ? { ttlAttribute } : {}
282
303
  });
283
304
  };
284
305
  }
@@ -328,6 +349,13 @@ function literal(...values) {
328
349
  });
329
350
  };
330
351
  }
352
+ var ttl = (_value, context) => {
353
+ collectField({
354
+ propertyName: String(context.name),
355
+ dynamoType: "N",
356
+ ttl: true
357
+ });
358
+ };
331
359
  var string = createFieldDecorator("S");
332
360
  var number = createFieldDecorator("N");
333
361
  var boolean = createFieldDecorator("BOOL");
@@ -659,6 +687,13 @@ function maintainedFrom(source, callback) {
659
687
  };
660
688
  }
661
689
 
690
+ // src/decorators/cdc-projected.ts
691
+ function cdcProjected() {
692
+ return function(_target, _context) {
693
+ collectCdcProjected();
694
+ };
695
+ }
696
+
662
697
  // src/operations/declarative-transaction.ts
663
698
  var PLACEHOLDER_RE = /\{[^{}]+\}/g;
664
699
  function resolveTemplate(template, params, element) {
@@ -1848,10 +1883,12 @@ export {
1848
1883
  buildProjection,
1849
1884
  buildPutInput,
1850
1885
  buildQuerySpec,
1886
+ buildSubscribeHandler,
1851
1887
  buildTransactionSpec,
1852
1888
  buildTransactions,
1853
1889
  buildUpdateExpression,
1854
1890
  buildUpdateInput,
1891
+ cdcProjected,
1855
1892
  collectContractBoundaryViolations,
1856
1893
  collectContractN1Violations,
1857
1894
  collectViewDefinitions,
@@ -1958,6 +1995,7 @@ export {
1958
1995
  number,
1959
1996
  numberSet,
1960
1997
  param,
1998
+ parseChange,
1961
1999
  plan,
1962
2000
  preview,
1963
2001
  publicCommandModel,
@@ -1973,6 +2011,7 @@ export {
1973
2011
  serializeFieldValue,
1974
2012
  string,
1975
2013
  stringSet,
2014
+ ttl,
1976
2015
  validateDepth,
1977
2016
  validateGsiAmbiguity,
1978
2017
  when,
@@ -1,4 +1,4 @@
1
- import { E as Executor, D as DynamoDBOperation, 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, M as ModelStatic, f as DDBModel, C as ChangeEvent } from '../types-BWOrWcbd.js';
1
+ import { E as Executor, D as DynamoDBOperation, 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, M as ModelStatic, f as DDBModel, C as ChangeEvent } from '../types-B9rJ1z3H.js';
2
2
  import '@aws-sdk/client-dynamodb';
3
3
 
4
4
  /**
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createCdcEmulator
3
- } from "../chunk-BROCT574.js";
3
+ } from "../chunk-EMJHTUA4.js";
4
4
  import {
5
5
  ClientManager,
6
6
  MetadataRegistry,
7
7
  TableMapping,
8
8
  resolveModelClass
9
- } from "../chunk-CPTV3H2U.js";
9
+ } from "../chunk-B3GWIWT6.js";
10
10
 
11
11
  // src/memory/memory-store.ts
12
12
  function deepClone(value) {