graphddb 0.3.1 → 0.4.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/README.md CHANGED
@@ -680,7 +680,7 @@ Relation traversal は、Entity 上に定義されたアクセスパスのみを
680
680
  | ドキュメント | 内容 |
681
681
  |----------|-------------|
682
682
  | [Specification](./docs/spec.md) | コア API: entity、structured keys/GSIs、query/filter、relation、batch/transaction、design rule、runtime の挙動。 |
683
- | [Design patterns](./docs/design-patterns.md) | DynamoDB の代表的な 10 設計パターン(RFC #118 §1)を graphddb の機能にマッピング: same-partition / embedded snapshot / edge / materialized view / sparse view / aggregate counter / versioned / reverse lookup / external projection。各パターンの用途・宣言方法(`pattern` / `defineView` / `defineVersioned` / `defineProjection` / `@aggregate`)・read & write 維持の挙動・Phase 別の対応状況。 |
683
+ | [Design patterns](./docs/design-patterns.md) | DynamoDB の代表的な 10 設計パターン(RFC #118 §1)を graphddb の機能にマッピング: same-partition / embedded snapshot / edge / materialized view / sparse view / aggregate counter / versioned / reverse lookup / external projection。各パターンの用途・宣言方法(`pattern` / `@model({ kind })` + `@maintainedFrom` / `@hasOne`・`@hasMany` の versioned pattern / `@aggregate`)・read & write 維持の挙動・Phase 別の対応状況。 |
684
684
  | [CQRS contract layer](./docs/cqrs-contract.md) | public な Query/Command contract、cardinality matrix、N+1 安全性、contract をまたぐ合成、context 境界。 |
685
685
  | [Mutation → command derivation](./docs/mutation-command-derivation.md) | Command IF の背後にある内部的な write-plan 合成 DSL: モデルの write セマンティクス(`entityWrites`)、fragment 合成、atomic な `TransactWriteItems` の導出。 |
686
686
  | [Class hydration](./docs/class-hydration.md) | read 結果をホスト言語のオブジェクトにロードする opt-in な `options.hydrate` ファクトリ(Phase 1: `query` トップレベル; Phase 2–3 は今後)。 |
@@ -6,9 +6,8 @@ import {
6
6
  buildDeleteInput,
7
7
  buildMaintenanceGraph,
8
8
  buildPutInput,
9
- isProjectionDefinition,
10
9
  resolveModelClass
11
- } from "./chunk-YIXXTGZ6.js";
10
+ } from "./chunk-CPTV3H2U.js";
12
11
 
13
12
  // src/cdc/prng.ts
14
13
  var SeededRandom = class {
@@ -550,10 +549,13 @@ var MaintenanceDrain = class {
550
549
  return m;
551
550
  }
552
551
  });
553
- const views = opts.views ?? [];
554
- const allClasses = [...classes, ...views.map((v) => v.viewClass)];
552
+ const explicitViews = opts.views;
553
+ const allClasses = [
554
+ ...classes,
555
+ ...(explicitViews ?? []).map((v) => v.viewClass)
556
+ ];
555
557
  const scoped = allClasses.length > 0 ? new Map(allClasses.map((c) => [c, MetadataRegistry.get(c)])) : void 0;
556
- this.graph = buildMaintenanceGraph(scoped, views);
558
+ this.graph = buildMaintenanceGraph(scoped, explicitViews);
557
559
  for (const item of this.graph.items) {
558
560
  this.ownerByName.set(item.ownerEntity, item.ownerClass);
559
561
  }
@@ -790,114 +792,6 @@ function createMaintenanceDrainHandler(opts = {}) {
790
792
  return createMaintenanceDrain(opts).handler;
791
793
  }
792
794
 
793
- // src/cdc/projection-sink.ts
794
- var EVENT_FOR_CHANGE = {
795
- INSERT: "created",
796
- MODIFY: "updated",
797
- REMOVE: "removed"
798
- };
799
- var InMemoryProjectionSink = class {
800
- /** The current sink contents, keyed by the idempotency key. */
801
- records = /* @__PURE__ */ new Map();
802
- /** Total upsert CALLS (including redelivered ones) — distinguishes calls from records. */
803
- upserts = 0;
804
- upsert(key, record) {
805
- this.records.set(key, record);
806
- this.upserts += 1;
807
- }
808
- delete(key) {
809
- this.records.delete(key);
810
- }
811
- /** The number of distinct sink records (the converged projection size). */
812
- size() {
813
- return this.records.size;
814
- }
815
- /** The total upsert calls (≥ size when redelivery occurred). */
816
- upsertCount() {
817
- return this.upserts;
818
- }
819
- /** Reset the sink (test). */
820
- reset() {
821
- this.records.clear();
822
- this.upserts = 0;
823
- }
824
- };
825
- var ProjectionSinkDrain = class {
826
- sink;
827
- /** Source-entity CLASS name (the `event.model` the capture seam records) → projections. */
828
- bySource = /* @__PURE__ */ new Map();
829
- /** Per-(shard,seq) de-dup within one handler invocation (at-least-once). */
830
- applied = /* @__PURE__ */ new Set();
831
- constructor(opts) {
832
- this.sink = opts.sink;
833
- for (const proj of opts.projections) {
834
- if (!isProjectionDefinition(proj)) {
835
- throw new Error(
836
- "ProjectionSinkDrain: a non-projection definition was supplied. Build projections with defineProjection(...)."
837
- );
838
- }
839
- const sourceName = proj.sourceClass.name;
840
- const bucket = this.bySource.get(sourceName);
841
- if (bucket) bucket.push(proj);
842
- else this.bySource.set(sourceName, [proj]);
843
- }
844
- }
845
- /** The CDC {@link ChangeHandler} to subscribe to an emulator / Streams source. */
846
- handler = async (batch) => {
847
- const failures = [];
848
- for (const event of batch.records) {
849
- try {
850
- await this.applyOne(event);
851
- } catch (e) {
852
- failures.push(event.sequenceNumber);
853
- if (process.env.GRAPHDDB_PROJECTION_DEBUG) {
854
- console.error("PROJECTION SINK ERROR", event.keys.pk, e);
855
- }
856
- }
857
- }
858
- return failures.length > 0 ? { batchItemFailures: failures } : {};
859
- };
860
- /** Project one source event into the sink for every matching projection. */
861
- async applyOne(event) {
862
- const sourceName = event.model;
863
- if (sourceName === void 0) return;
864
- const projections = this.bySource.get(sourceName);
865
- if (projections === void 0 || projections.length === 0) return;
866
- const lifecycleEvent = EVENT_FOR_CHANGE[event.eventName];
867
- const image = event.eventName === "REMOVE" ? event.oldImage : event.newImage;
868
- if (image === void 0) return;
869
- const eventId = `${event.shardId}#${event.sequenceNumber}`;
870
- if (this.applied.has(eventId)) return;
871
- for (const proj of projections) {
872
- if (!proj.on.includes(lifecycleEvent)) continue;
873
- const key = image[proj.idempotencyKey];
874
- if (key === void 0 || key === null) {
875
- throw new Error(
876
- `defineProjection '${proj.name}': source event carries no idempotency key attribute '${proj.idempotencyKey}'. Every projected source row must carry it (it folds at-least-once delivery to one sink upsert).`
877
- );
878
- }
879
- const keyStr = String(key);
880
- if (lifecycleEvent === "removed") {
881
- await this.sink.delete?.(keyStr);
882
- continue;
883
- }
884
- const record = Object.keys(proj.project).length === 0 ? image : projectFrom(proj.project, image);
885
- await this.sink.upsert(keyStr, record);
886
- }
887
- this.applied.add(eventId);
888
- }
889
- /** Clear the per-delivery de-dup set (test reset). */
890
- reset() {
891
- this.applied = /* @__PURE__ */ new Set();
892
- }
893
- };
894
- function createProjectionSinkDrain(opts) {
895
- return new ProjectionSinkDrain(opts);
896
- }
897
- function createProjectionSinkHandler(opts) {
898
- return createProjectionSinkDrain(opts).handler;
899
- }
900
-
901
795
  export {
902
796
  CdcEmulator,
903
797
  createCdcEmulator,
@@ -908,9 +802,5 @@ export {
908
802
  MAINT_OUTBOX_PK_PREFIX,
909
803
  MaintenanceDrain,
910
804
  createMaintenanceDrain,
911
- createMaintenanceDrainHandler,
912
- InMemoryProjectionSink,
913
- ProjectionSinkDrain,
914
- createProjectionSinkDrain,
915
- createProjectionSinkHandler
805
+ createMaintenanceDrainHandler
916
806
  };