graphddb 0.1.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.
@@ -0,0 +1,182 @@
1
+ import { E as Executor, D as DynamoDBOperation, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, T as TransactWriteExecItem, M as ModelStatic, e as DDBModel, C as ChangeEvent } from '../types-CDrWiPxp.js';
2
+ import '@aws-sdk/client-dynamodb';
3
+
4
+ /**
5
+ * In-process physical store backing the GraphDDB Memory Test Adapter
6
+ * (issue #76). A table is a `Map<PK, Map<SK, Item>>`; items are kept in their
7
+ * **physical** form exactly as GraphDDB writes them (`PK` / `SK` / `GSI*PK` /
8
+ * `GSI*SK` plus attributes), with no marshalling and no hydration. Sort keys are
9
+ * compared lexicographically (byte order) at read time — numeric zero-padding is
10
+ * the model's responsibility, matching the proposal's fidelity non-goals.
11
+ *
12
+ * GSI secondary indexes are not stored separately: since GraphDDB projects ALL
13
+ * onto its GSIs, a GSI query is answered by filtering the base partition rows on
14
+ * their `{index}PK` / `{index}SK` attributes — equivalent to a maintained ALL
15
+ * projection, and trivially consistent on every write.
16
+ */
17
+ /** A physical item as stored: a plain attribute map including PK/SK/GSI keys. */
18
+ type Item = Record<string, unknown>;
19
+ /** A structured-clone snapshot of the whole store, for save/restore isolation. */
20
+ type MemorySnapshot = Record<string, Item[]>;
21
+ declare class MemoryStore {
22
+ /** table → PK → SK → item. */
23
+ private tables;
24
+ private partition;
25
+ /** Insert/overwrite one physical item. Returns the prior item if present. */
26
+ putItem(table: string, item: Item): Item | undefined;
27
+ /** Fetch one physical item by base-table key. */
28
+ getItem(table: string, pk: string, sk: string): Item | undefined;
29
+ /** Delete one item by base-table key. Returns the removed item if present. */
30
+ deleteItem(table: string, pk: string, sk: string): Item | undefined;
31
+ /**
32
+ * All items in one base-table partition, sorted ascending by SK (byte order).
33
+ * Used by the Query path (PK eq + optional SK range).
34
+ */
35
+ partitionItems(table: string, pk: string): Item[];
36
+ /**
37
+ * All items in one GSI partition (rows whose `{index}PK` equals `pk`), sorted
38
+ * ascending by the GSI sort key (`{index}SK`, byte order). Filtering the base
39
+ * rows is equivalent to a maintained ALL-projection secondary index.
40
+ */
41
+ gsiPartitionItems(table: string, indexName: string, pk: string): Item[];
42
+ /** Every physical item in one table (unsorted; inspection only). */
43
+ allItems(table: string): Item[];
44
+ /** Names of every table that currently holds at least one partition. */
45
+ tableNames(): string[];
46
+ /** Item count for one table. */
47
+ count(table: string): number;
48
+ /** Clear all tables. */
49
+ reset(): void;
50
+ /** Structured-clone the whole store (save). */
51
+ snapshot(): MemorySnapshot;
52
+ /** Replace all store contents from a snapshot (load). */
53
+ restore(snapshot: MemorySnapshot): void;
54
+ }
55
+
56
+ /**
57
+ * In-process {@link Executor} over a {@link MemoryStore} (issue #76). It
58
+ * interprets the *structured* operations GraphDDB emits — never AWS SDK
59
+ * commands and never the compiled key-condition strings — so the planner,
60
+ * key resolver, projection, hydrator and relation traversal all run unchanged
61
+ * (proposal option B). Only the FilterExpression and Update/Condition
62
+ * expressions are interpreted (the boundary where GraphDDB hands the executor a
63
+ * compiled string), via the dedicated in-memory evaluators.
64
+ *
65
+ * Implements exactly the DynamoDB subset GraphDDB uses: PK-eq Query with an
66
+ * optional SK `=` / `begins_with` range, `limit` + `ExclusiveStartKey`
67
+ * pagination, `scanIndexForward`, GSI queries (ALL projection), BatchGet,
68
+ * projection, server-side filter, conditional writes, and atomic TransactWrite.
69
+ */
70
+
71
+ declare class MemoryExecutor implements Executor {
72
+ private readonly store;
73
+ constructor(store: MemoryStore);
74
+ execute(operation: DynamoDBOperation): Promise<ExecutorResult>;
75
+ batchGet(input: BatchGetExecInput): Promise<ExecutorResult>;
76
+ private getItem;
77
+ private query;
78
+ put(input: PutInput, options?: WriteExecOptions): Promise<WriteResult>;
79
+ update(input: UpdateInput, options?: WriteExecOptions): Promise<WriteResult>;
80
+ delete(input: DeleteInput, options?: WriteExecOptions): Promise<WriteResult>;
81
+ batchWrite(tableName: string, items: BatchWriteExecItem[]): Promise<void>;
82
+ transactWrite(items: TransactWriteExecItem[]): Promise<void>;
83
+ private restoreTable;
84
+ /**
85
+ * Evaluate a transaction `ConditionCheck` (issue #81): read the keyed item and
86
+ * assert its `ConditionExpression` holds. Mutates nothing; a failed assertion
87
+ * throws {@link ConditionalCheckFailed}, which {@link transactWrite} catches to
88
+ * roll the whole transaction back — mirroring DynamoDB's atomic cancellation.
89
+ */
90
+ private conditionCheck;
91
+ private assertCondition;
92
+ }
93
+
94
+ /**
95
+ * `graphddb/testing` — the in-process test adapter entry point (issue #76).
96
+ *
97
+ * `createTestDB()` installs a {@link MemoryExecutor} as GraphDDB's I/O seam, so
98
+ * `Model.put/query/list/update/...`, the planner, hydrator and relation
99
+ * traversal all run against an in-memory store — **no DynamoDB, no Docker**.
100
+ * The returned `db.testing` is a {@link MemoryInspector} for asserting the
101
+ * **physical** layout (PK/SK/GSI as stored, no hydration), seeding fixtures,
102
+ * resetting, and snapshot/restore isolation between tests.
103
+ *
104
+ * With `{ cdc: true }`, a {@link CdcEmulator} (record mode) is attached over the
105
+ * configured models so writes flowing through the in-memory executor produce
106
+ * `ChangeEvent`s, readable via `db.testing.changes()` (Phase 3 of the proposal,
107
+ * enabled because CDC #72 exists on this branch).
108
+ */
109
+
110
+ /** A scan filter over a single table's physical rows (inspection only). */
111
+ interface ScanFilter {
112
+ /** Match the base-table `PK` exactly. */
113
+ pk?: string;
114
+ /** Match a base-table `SK` prefix. */
115
+ skPrefix?: string;
116
+ /**
117
+ * Inspect a GSI partition instead of the base table: rows are filtered on
118
+ * `{index}PK` (via {@link pk}) / `{index}SK` prefix (via {@link skPrefix}).
119
+ */
120
+ index?: string;
121
+ }
122
+ /**
123
+ * Direct, hydration-free inspection of the in-memory store (proposal
124
+ * §"inspection / dump IF"). `dump` / `scan` return **physical** items — the bytes GraphDDB
125
+ * stored, including `PK` / `SK` / `GSI*PK` / `GSI*SK` — for asserting model
126
+ * mapping. This is a test-observation path; the system-under-test still uses
127
+ * `Model.query` / `Model.list`.
128
+ */
129
+ interface MemoryInspector {
130
+ /** Every physical item, keyed by physical table name. */
131
+ dump(): Record<string, Item[]>;
132
+ /** Every physical item in one table. */
133
+ dumpTable(table: string): Item[];
134
+ /** Raw physical rows of a table, optionally filtered by PK / SK-prefix / GSI. */
135
+ scan(table: string, filter?: ScanFilter): Item[];
136
+ /** Item count for a table. */
137
+ count(table: string): number;
138
+ /** One physical item by base-table key, or `null`. */
139
+ getRaw(table: string, key: {
140
+ PK: string;
141
+ SK: string;
142
+ }): Item | null;
143
+ /** Insert physical items directly (fixtures). */
144
+ seed(table: string, items: Item[]): void;
145
+ /** Clear every table. */
146
+ reset(): void;
147
+ /** Structured-clone the whole store (save). */
148
+ snapshot(): MemorySnapshot;
149
+ /** Restore a snapshot (load). */
150
+ restore(snapshot: MemorySnapshot): void;
151
+ /** ChangeEvents captured so far (requires `cdc: true`). */
152
+ changes(): ChangeEvent[];
153
+ /** Tear down: restore the default executor and detach CDC. */
154
+ close(): void;
155
+ }
156
+ /** A model reference: a `ModelStatic` (from `DDBModel.asModel()`) or its class. */
157
+ type ModelRef = ModelStatic<DDBModel> | Function;
158
+ interface CreateTestDBOptions {
159
+ /**
160
+ * Models whose physical table name should be inspectable by their logical
161
+ * name and (when `cdc: true`) be stream-enabled. Optional: the inspector also
162
+ * reflects any table the store has written to.
163
+ */
164
+ models?: ModelRef[];
165
+ /** Enable the CDC emulator (record mode) over the configured models. */
166
+ cdc?: boolean;
167
+ }
168
+ interface TestDB {
169
+ /** The inspection / fixture / isolation interface. */
170
+ testing: MemoryInspector;
171
+ /** The backing store (advanced use). */
172
+ store: MemoryStore;
173
+ }
174
+ /**
175
+ * Create an in-memory GraphDDB for tests. Installs a {@link MemoryExecutor} on
176
+ * the {@link ClientManager} seam and returns a {@link MemoryInspector}. Call
177
+ * `db.testing.close()` (or `ClientManager.resetExecutor()`) when done to restore
178
+ * the default DynamoDB executor.
179
+ */
180
+ declare function createTestDB(options?: CreateTestDBOptions): TestDB;
181
+
182
+ export { type CreateTestDBOptions, type Item, MemoryExecutor, type MemoryInspector, type MemorySnapshot, MemoryStore, type ModelRef, type ScanFilter, type TestDB, createTestDB };