@model-ts/dynamodb 4.0.0 → 4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @model-ts/dynamodb
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3cf37a0: Add sandbox rollback option
8
+
3
9
  ## 4.0.0
4
10
 
5
11
  ### Major Changes
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const t = tslib_1.__importStar(require("io-ts"));
5
+ const core_1 = require("@model-ts/core");
6
+ const sandbox_1 = require("../sandbox");
7
+ const client_1 = require("../client");
8
+ const provider_1 = require("../provider");
9
+ const client = new client_1.Client({ tableName: "table" });
10
+ const provider = provider_1.getProvider(client);
11
+ const SIMPLE_CODEC = t.type({
12
+ foo: t.string,
13
+ bar: t.number,
14
+ });
15
+ class Simple extends core_1.model("Simple", SIMPLE_CODEC, provider) {
16
+ get PK() {
17
+ return `PK#${this.foo}`;
18
+ }
19
+ get SK() {
20
+ return `SK#${this.bar}`;
21
+ }
22
+ }
23
+ describe("rollback", () => {
24
+ let sandbox;
25
+ beforeAll(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
26
+ sandbox = yield sandbox_1.createSandbox(client);
27
+ yield sandbox.seed(new Simple({ foo: "seeded1", bar: 1 }), new Simple({ foo: "seeded2", bar: 2 }));
28
+ }));
29
+ afterAll(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
30
+ yield sandbox.destroy();
31
+ }));
32
+ test("rolls back newly added items", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
33
+ sandbox.startTracking();
34
+ yield new Simple({ foo: "new-item", bar: 99 }).put();
35
+ expect(yield sandbox.get("PK#new-item", "SK#99")).not.toBeNull();
36
+ yield sandbox.rollback();
37
+ expect(yield sandbox.get("PK#new-item", "SK#99")).toBeNull();
38
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).not.toBeNull();
39
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).not.toBeNull();
40
+ }));
41
+ test("rolls back updated items", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
42
+ sandbox.startTracking();
43
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "modified" });
44
+ const modified = yield sandbox.get("PK#seeded1", "SK#1");
45
+ expect(modified.foo).toBe("modified");
46
+ yield sandbox.rollback();
47
+ const restored = yield sandbox.get("PK#seeded1", "SK#1");
48
+ expect(restored.foo).toBe("seeded1");
49
+ }));
50
+ test("rolls back deleted items", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
51
+ sandbox.startTracking();
52
+ yield Simple.delete({ PK: "PK#seeded1", SK: "SK#1" });
53
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).toBeNull();
54
+ yield sandbox.rollback();
55
+ const restored = yield sandbox.get("PK#seeded1", "SK#1");
56
+ expect(restored).not.toBeNull();
57
+ expect(restored.foo).toBe("seeded1");
58
+ }));
59
+ test("rolls back soft-deleted items", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
60
+ sandbox.startTracking();
61
+ const item = new Simple({ foo: "seeded1", bar: 1 });
62
+ // @ts-ignore - _docVersion needed for softDelete encoding
63
+ item._docVersion = 0;
64
+ yield client.softDelete(item);
65
+ // Original should be gone, deleted version should exist
66
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).toBeNull();
67
+ expect(yield sandbox.get("$$DELETED$$PK#seeded1", "$$DELETED$$SK#1")).not.toBeNull();
68
+ yield sandbox.rollback();
69
+ // Original should be restored, deleted version should be gone
70
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).not.toBeNull();
71
+ expect(yield sandbox.get("$$DELETED$$PK#seeded1", "$$DELETED$$SK#1")).toBeNull();
72
+ }));
73
+ test("rolls back mixed operations", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
74
+ sandbox.startTracking();
75
+ // Add a new item
76
+ yield new Simple({ foo: "brand-new", bar: 50 }).put();
77
+ // Update an existing item
78
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "changed" });
79
+ // Delete an existing item
80
+ yield Simple.delete({ PK: "PK#seeded2", SK: "SK#2" });
81
+ // Verify all changes took effect
82
+ expect(yield sandbox.get("PK#brand-new", "SK#50")).not.toBeNull();
83
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("changed");
84
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).toBeNull();
85
+ yield sandbox.rollback();
86
+ // New item should be gone
87
+ expect(yield sandbox.get("PK#brand-new", "SK#50")).toBeNull();
88
+ // Updated item should be restored
89
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1");
90
+ // Deleted item should be back
91
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).not.toBeNull();
92
+ }));
93
+ test("supports multiple tracking/rollback cycles", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
94
+ // Cycle 1
95
+ sandbox.startTracking();
96
+ yield new Simple({ foo: "cycle1", bar: 10 }).put();
97
+ yield sandbox.rollback();
98
+ expect(yield sandbox.get("PK#cycle1", "SK#10")).toBeNull();
99
+ // Cycle 2
100
+ sandbox.startTracking();
101
+ yield new Simple({ foo: "cycle2", bar: 20 }).put();
102
+ yield sandbox.rollback();
103
+ expect(yield sandbox.get("PK#cycle2", "SK#20")).toBeNull();
104
+ // Cycle 3 - modify seeded data
105
+ sandbox.startTracking();
106
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "cycle3-mod" });
107
+ yield sandbox.rollback();
108
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1");
109
+ // Seeded data is intact throughout
110
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).not.toBeNull();
111
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).not.toBeNull();
112
+ }));
113
+ test("does not track writes before startTracking", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
114
+ // Write without tracking
115
+ yield new Simple({ foo: "untracked", bar: 77 }).put();
116
+ // Now start tracking and immediately rollback
117
+ sandbox.startTracking();
118
+ yield sandbox.rollback();
119
+ // The untracked write should still be there
120
+ expect(yield sandbox.get("PK#untracked", "SK#77")).not.toBeNull();
121
+ // Clean up manually for subsequent tests
122
+ sandbox.startTracking();
123
+ yield Simple.delete({ PK: "PK#untracked", SK: "SK#77" });
124
+ yield sandbox.rollback();
125
+ }));
126
+ test("tracks the same key modified multiple times", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
127
+ sandbox.startTracking();
128
+ // Update the same item twice
129
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "first-update" });
130
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "second-update" });
131
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("second-update");
132
+ yield sandbox.rollback();
133
+ // Should restore to original, not to the intermediate state
134
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1");
135
+ }));
136
+ });
137
+ describe("rollback with beforeEach/afterEach pattern", () => {
138
+ let sandbox;
139
+ beforeAll(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
140
+ sandbox = yield sandbox_1.createSandbox(client);
141
+ yield sandbox.seed(new Simple({ foo: "a", bar: 1 }), new Simple({ foo: "b", bar: 2 }));
142
+ }));
143
+ beforeEach(() => {
144
+ sandbox.startTracking();
145
+ });
146
+ afterEach(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
147
+ yield sandbox.rollback();
148
+ }));
149
+ afterAll(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
150
+ yield sandbox.destroy();
151
+ }));
152
+ test("test A: add an item", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
153
+ yield new Simple({ foo: "from-test-a", bar: 100 }).put();
154
+ expect(yield sandbox.get("PK#from-test-a", "SK#100")).not.toBeNull();
155
+ }));
156
+ test("test B: item from test A does not exist", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
157
+ expect(yield sandbox.get("PK#from-test-a", "SK#100")).toBeNull();
158
+ }));
159
+ test("test C: modify seeded data", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
160
+ yield Simple.updateRaw({ PK: "PK#a", SK: "SK#1" }, { foo: "modified-a" });
161
+ expect((yield sandbox.get("PK#a", "SK#1")).foo).toBe("modified-a");
162
+ }));
163
+ test("test D: seeded data is back to original", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
164
+ expect((yield sandbox.get("PK#a", "SK#1")).foo).toBe("a");
165
+ }));
166
+ test("test E: delete seeded data", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
167
+ yield Simple.delete({ PK: "PK#b", SK: "SK#2" });
168
+ expect(yield sandbox.get("PK#b", "SK#2")).toBeNull();
169
+ }));
170
+ test("test F: deleted seeded data is back", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
171
+ expect(yield sandbox.get("PK#b", "SK#2")).not.toBeNull();
172
+ expect((yield sandbox.get("PK#b", "SK#2")).foo).toBe("b");
173
+ }));
174
+ });
175
+ describe("existing sandbox semantics still work", () => {
176
+ let sandbox;
177
+ beforeEach(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
178
+ sandbox = yield sandbox_1.createSandbox(client);
179
+ }));
180
+ afterEach(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
181
+ yield sandbox.destroy();
182
+ }));
183
+ test("create and destroy per test still works", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
184
+ yield sandbox.seed(new Simple({ foo: "per-test", bar: 1 }));
185
+ const item = yield sandbox.get("PK#per-test", "SK#1");
186
+ expect(item).not.toBeNull();
187
+ expect(item.foo).toBe("per-test");
188
+ }));
189
+ test("snapshot and diff still work", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
190
+ const before = yield sandbox.snapshot();
191
+ yield new Simple({ foo: "diffed", bar: 1 }).put();
192
+ const diffResult = yield sandbox.diff(before);
193
+ expect(diffResult).toContain("PK#diffed");
194
+ }));
195
+ });
196
+ //# sourceMappingURL=rollback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.test.js","sourceRoot":"","sources":["../../../src/__test__/rollback.test.ts"],"names":[],"mappings":"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"}
@@ -16,5 +16,7 @@ export interface Sandbox {
16
16
  diff: (before: {
17
17
  [key: string]: any;
18
18
  }) => Promise<string>;
19
+ startTracking: () => void;
20
+ rollback: () => Promise<void>;
19
21
  }
20
22
  export declare const createSandbox: (client: Client) => Promise<Sandbox>;
@@ -97,9 +97,134 @@ const getTableContents = (tableName) => tslib_1.__awaiter(void 0, void 0, void 0
97
97
  return acc;
98
98
  });
99
99
  exports.getTableContents = getTableContents;
100
+ const WRITE_METHODS = new Set([
101
+ "put",
102
+ "update",
103
+ "delete",
104
+ "batchWrite",
105
+ "transactWrite",
106
+ ]);
107
+ function createTrackedDocClient(original, tableName) {
108
+ let isTracking = false;
109
+ const trackedKeys = new Map();
110
+ const captureKey = (pk, sk) => tslib_1.__awaiter(this, void 0, void 0, function* () {
111
+ const compositeKey = `${pk}__${sk}`;
112
+ if (trackedKeys.has(compositeKey))
113
+ return;
114
+ const { Item } = yield original
115
+ .get({ TableName: tableName, Key: { PK: pk, SK: sk } })
116
+ .promise();
117
+ trackedKeys.set(compositeKey, { pk, sk, original: Item !== null && Item !== void 0 ? Item : null });
118
+ });
119
+ const captureKeysForOperation = (method, params) => tslib_1.__awaiter(this, void 0, void 0, function* () {
120
+ var _a;
121
+ switch (method) {
122
+ case "put":
123
+ if (params.TableName === tableName && params.Item) {
124
+ yield captureKey(params.Item.PK, params.Item.SK);
125
+ }
126
+ break;
127
+ case "update":
128
+ case "delete":
129
+ if (params.TableName === tableName && params.Key) {
130
+ yield captureKey(params.Key.PK, params.Key.SK);
131
+ }
132
+ break;
133
+ case "batchWrite": {
134
+ const tableItems = ((_a = params.RequestItems) === null || _a === void 0 ? void 0 : _a[tableName]) || [];
135
+ yield Promise.all(tableItems.map((item) => {
136
+ if (item.PutRequest) {
137
+ return captureKey(item.PutRequest.Item.PK, item.PutRequest.Item.SK);
138
+ }
139
+ if (item.DeleteRequest) {
140
+ return captureKey(item.DeleteRequest.Key.PK, item.DeleteRequest.Key.SK);
141
+ }
142
+ }));
143
+ break;
144
+ }
145
+ case "transactWrite": {
146
+ const transactItems = params.TransactItems || [];
147
+ yield Promise.all(transactItems
148
+ .map((item) => {
149
+ var _a, _b, _c;
150
+ if (((_a = item.Put) === null || _a === void 0 ? void 0 : _a.TableName) === tableName) {
151
+ return captureKey(item.Put.Item.PK, item.Put.Item.SK);
152
+ }
153
+ if (((_b = item.Update) === null || _b === void 0 ? void 0 : _b.TableName) === tableName) {
154
+ return captureKey(item.Update.Key.PK, item.Update.Key.SK);
155
+ }
156
+ if (((_c = item.Delete) === null || _c === void 0 ? void 0 : _c.TableName) === tableName) {
157
+ return captureKey(item.Delete.Key.PK, item.Delete.Key.SK);
158
+ }
159
+ })
160
+ .filter(Boolean));
161
+ break;
162
+ }
163
+ }
164
+ });
165
+ const proxy = new Proxy(original, {
166
+ get(target, prop) {
167
+ const value = target[prop];
168
+ if (value === undefined)
169
+ return undefined;
170
+ if (typeof value === "function") {
171
+ if (isTracking && WRITE_METHODS.has(prop)) {
172
+ return (params) => {
173
+ const request = value.call(target, params);
174
+ const origPromise = request.promise.bind(request);
175
+ request.promise = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
176
+ yield captureKeysForOperation(prop, params);
177
+ return origPromise();
178
+ });
179
+ return request;
180
+ };
181
+ }
182
+ return value.bind(target);
183
+ }
184
+ return value;
185
+ },
186
+ });
187
+ return {
188
+ proxy: proxy,
189
+ startTracking: () => {
190
+ isTracking = true;
191
+ trackedKeys.clear();
192
+ },
193
+ rollback: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
194
+ isTracking = false;
195
+ const entries = Array.from(trackedKeys.values());
196
+ const toDelete = entries.filter((e) => e.original === null);
197
+ const toRestore = entries.filter((e) => e.original !== null);
198
+ const deleteChunks = Array_1.chunksOf(25)(toDelete);
199
+ const restoreChunks = Array_1.chunksOf(25)(toRestore);
200
+ yield Promise.all([
201
+ ...deleteChunks.map((chunk) => original
202
+ .batchWrite({
203
+ RequestItems: {
204
+ [tableName]: chunk.map(({ pk, sk }) => ({
205
+ DeleteRequest: { Key: { PK: pk, SK: sk } },
206
+ })),
207
+ },
208
+ })
209
+ .promise()),
210
+ ...restoreChunks.map((chunk) => original
211
+ .batchWrite({
212
+ RequestItems: {
213
+ [tableName]: chunk.map(({ original: item }) => ({
214
+ PutRequest: { Item: item },
215
+ })),
216
+ },
217
+ })
218
+ .promise()),
219
+ ]);
220
+ trackedKeys.clear();
221
+ }),
222
+ };
223
+ }
100
224
  const createSandbox = (client) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
101
225
  const tableName = yield exports.createTable();
102
- client.setDocumentClient(docClient);
226
+ const tracked = createTrackedDocClient(docClient, tableName);
227
+ client.setDocumentClient(tracked.proxy);
103
228
  client.setTableName(tableName);
104
229
  return {
105
230
  destroy: () => exports.destroyTable(tableName),
@@ -132,6 +257,8 @@ const createSandbox = (client) => tslib_1.__awaiter(void 0, void 0, void 0, func
132
257
  const snapshot = yield exports.getTableContents(tableName);
133
258
  return diff_1.formatSnapshotDiff(before, snapshot);
134
259
  }),
260
+ startTracking: tracked.startTracking,
261
+ rollback: tracked.rollback,
135
262
  };
136
263
  });
137
264
  exports.createSandbox = createSandbox;
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":";;;;AAAA,4DAA2B;AAC3B,2CAA0C;AAC1C,gFAA+C;AAC/C,iCAA2C;AAE3C,+BAAiC;AAEjC,MAAM,GAAG,GAAG,IAAI,kBAAQ,CAAC;IACvB,WAAW,EAAE,KAAK;IAClB,eAAe,EAAE,KAAK;IACtB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;IACpC,MAAM,EAAE,OAAO;CAChB,CAAC,CAAA;AAEF,MAAM,SAAS,GAAG,IAAI,kBAAQ,CAAC,cAAc,CAAC;IAC5C,WAAW,EAAE,KAAK;IAClB,eAAe,EAAE,KAAK;IACtB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;IACpC,MAAM,EAAE,OAAO;CAChB,CAAC,CAAA;AAEK,MAAM,WAAW,GAAG,GAAS,EAAE;IACpC,MAAM,SAAS,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAExD,MAAM,GAAG;SACN,WAAW,CAAC;QACX,SAAS,EAAE,SAAS;QACpB,oBAAoB,EAAE;YACpB,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;YAC3C,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;YAC3C,GAAG,eAAS,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC5B,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;gBACjD,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;aAClD,CAAC;SACH;QACD,SAAS,EAAE;YACT,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE;YACxC,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;SAC1C;QACD,sBAAsB,EAAE;YACtB;gBACE,SAAS,EAAE,MAAM;gBACjB,SAAS,EAAE;oBACT,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE;oBACxC,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;iBAC1C;gBACD,UAAU,EAAE;oBACV,cAAc,EAAE,KAAK;iBACtB;aACF;YACD,GAAG,eAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACzB,SAAS,EAAE,GAAG;gBACd,SAAS,EAAE;oBACT,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE;oBAC9C,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;iBAChD;gBACD,UAAU,EAAE;oBACV,cAAc,EAAE,KAAK;iBACtB;aACF,CAAC,CAAC;SACJ;QACD,WAAW,EAAE,iBAAiB;KAC/B,CAAC;SACD,OAAO,EAAE;SACT,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE;QAChB,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,CAAC,CAAC,CAAA;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;IAEJ,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA,CAAA;AAjDY,QAAA,WAAW,eAiDvB;AAEM,MAAM,YAAY,GAAG,CAAO,SAAiB,EAAE,EAAE;IACtD,OAAO,GAAG;SACP,WAAW,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;SACrC,OAAO,EAAE;SACT,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;SACd,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,CAAC,CAAC,CAAA;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;AACN,CAAC,CAAA,CAAA;AATY,QAAA,YAAY,gBASxB;AAEM,MAAM,gBAAgB,GAAG,CAC9B,SAAiB,EACgB,EAAE;IACnC,MAAM,IAAI,GAAG,CAAO,iBAAuB,EAAkB,EAAE;QAC7D,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,gBAAgB,EAAE,GAAG,MAAM,SAAS;aACrD,IAAI,CAAC;YACJ,SAAS,EAAE,SAAS;YACpB,iBAAiB;SAClB,CAAC;aACD,OAAO,EAAE,CAAA;QAEZ,IAAI,gBAAgB;YAAE,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;QAC1E,OAAO,KAAK,CAAA;IACd,CAAC,CAAA,CAAA;IAED,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,CAAA;IAE1B,MAAM,GAAG,GAA2B,EAAE,CAAA;IAEtC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;IAE/D,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA,CAAA;AAtBY,QAAA,gBAAgB,oBAsB5B;AAYD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,eAAe;CAChB,CAAC,CAAA;AAEF,SAAS,sBAAsB,CAC7B,QAAiC,EACjC,SAAiB;IAEjB,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAwB,CAAA;IAEnD,MAAM,UAAU,GAAG,CAAO,EAAU,EAAE,EAAU,EAAE,EAAE;QAClD,MAAM,YAAY,GAAG,GAAG,EAAE,KAAK,EAAE,EAAE,CAAA;QACnC,IAAI,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC;YAAE,OAAM;QAEzC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,QAAQ;aAC5B,GAAG,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;aACtD,OAAO,EAAE,CAAA;QAEZ,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC,CAAA,CAAA;IAED,MAAM,uBAAuB,GAAG,CAAO,MAAc,EAAE,MAAW,EAAE,EAAE;;QACpE,QAAQ,MAAM,EAAE;YACd,KAAK,KAAK;gBACR,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE;oBACjD,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;iBACjD;gBACD,MAAK;YACP,KAAK,QAAQ,CAAC;YACd,KAAK,QAAQ;gBACX,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,EAAE;oBAChD,MAAM,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;iBAC/C;gBACD,MAAK;YACP,KAAK,YAAY,CAAC,CAAC;gBACjB,MAAM,UAAU,GAAG,CAAA,MAAA,MAAM,CAAC,YAAY,0CAAG,SAAS,CAAC,KAAI,EAAE,CAAA;gBACzD,MAAM,OAAO,CAAC,GAAG,CACf,UAAU,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;oBAC3B,IAAI,IAAI,CAAC,UAAU,EAAE;wBACnB,OAAO,UAAU,CACf,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CACxB,CAAA;qBACF;oBACD,IAAI,IAAI,CAAC,aAAa,EAAE;wBACtB,OAAO,UAAU,CACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EACzB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAC1B,CAAA;qBACF;gBACH,CAAC,CAAC,CACH,CAAA;gBACD,MAAK;aACN;YACD,KAAK,eAAe,CAAC,CAAC;gBACpB,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAA;gBAChD,MAAM,OAAO,CAAC,GAAG,CACf,aAAa;qBACV,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;;oBACjB,IAAI,CAAA,MAAA,IAAI,CAAC,GAAG,0CAAE,SAAS,MAAK,SAAS,EAAE;wBACrC,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;qBACtD;oBACD,IAAI,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,SAAS,MAAK,SAAS,EAAE;wBACxC,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;qBAC1D;oBACD,IAAI,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,SAAS,MAAK,SAAS,EAAE;wBACxC,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;qBAC1D;gBACH,CAAC,CAAC;qBACD,MAAM,CAAC,OAAO,CAAC,CACnB,CAAA;gBACD,MAAK;aACN;SACF;IACH,CAAC,CAAA,CAAA;IAED,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE;QAChC,GAAG,CAAC,MAAM,EAAE,IAAI;YACd,MAAM,KAAK,GAAI,MAAc,CAAC,IAAI,CAAC,CAAA;YACnC,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAA;YAEzC,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE;gBAC/B,IAAI,UAAU,IAAI,aAAa,CAAC,GAAG,CAAC,IAAc,CAAC,EAAE;oBACnD,OAAO,CAAC,MAAW,EAAE,EAAE;wBACrB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;wBAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;wBACjD,OAAO,CAAC,OAAO,GAAG,GAAS,EAAE;4BAC3B,MAAM,uBAAuB,CAAC,IAAc,EAAE,MAAM,CAAC,CAAA;4BACrD,OAAO,WAAW,EAAE,CAAA;wBACtB,CAAC,CAAA,CAAA;wBACD,OAAO,OAAO,CAAA;oBAChB,CAAC,CAAA;iBACF;gBACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;aAC1B;YAED,OAAO,KAAK,CAAA;QACd,CAAC;KACF,CAAC,CAAA;IAEF,OAAO;QACL,KAAK,EAAE,KAAgC;QACvC,aAAa,EAAE,GAAG,EAAE;YAClB,UAAU,GAAG,IAAI,CAAA;YACjB,WAAW,CAAC,KAAK,EAAE,CAAA;QACrB,CAAC;QACD,QAAQ,EAAE,GAAS,EAAE;YACnB,UAAU,GAAG,KAAK,CAAA;YAElB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAA;YAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAA;YAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAA;YAE5D,MAAM,YAAY,GAAG,gBAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;YAC3C,MAAM,aAAa,GAAG,gBAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;YAE7C,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChB,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC5B,QAAQ;qBACL,UAAU,CAAC;oBACV,YAAY,EAAE;wBACZ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;4BACtC,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;yBAC3C,CAAC,CAAC;qBACJ;iBACF,CAAC;qBACD,OAAO,EAAE,CACb;gBACD,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7B,QAAQ;qBACL,UAAU,CAAC;oBACV,YAAY,EAAE;wBACZ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;4BAC9C,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;yBAC3B,CAAC,CAAC;qBACJ;iBACF,CAAC;qBACD,OAAO,EAAE,CACb;aACF,CAAC,CAAA;YAEF,WAAW,CAAC,KAAK,EAAE,CAAA;QACrB,CAAC,CAAA;KACF,CAAA;AACH,CAAC;AAgBM,MAAM,aAAa,GAAG,CAAO,MAAc,EAAoB,EAAE;IACtE,MAAM,SAAS,GAAG,MAAM,mBAAW,EAAE,CAAA;IAErC,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IAC5D,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;IAE9B,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAY,CAAC,SAAS,CAAC;QACtC,QAAQ,EAAE,GAAG,EAAE,CAAC,wBAAgB,CAAC,SAAS,CAAC;QAC3C,IAAI,EAAE,CAAO,GAAG,IAAmC,EAAE,EAAE;YACrD,MAAM,MAAM,GAAG,gBAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;YAEjC,MAAM,OAAO,CAAC,GAAG,CACf,MAAM,CAAC,GAAG,CAAC,CAAO,KAAK,EAAE,EAAE;gBACzB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;;oBAC5B,OAAA,OAAO,CAAA,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,MAAM,0CAAE,gBAAgB,CAAA,KAAK,UAAU;wBAC/C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;wBAC9B,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,UAAU;4BAChC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;4BACZ,CAAC,CAAC,CAAC,CAAA;iBAAA,CACN,CAAA;gBAED,OAAO,MAAM,CAAC,cAAc;qBACzB,UAAU,CAAC;oBACV,YAAY,EAAE;wBACZ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;qBAC7D;iBACF,CAAC;qBACD,OAAO,EAAE,CAAA;YACd,CAAC,CAAA,CAAC,CACH,CAAA;QACH,CAAC,CAAA;QACD,GAAG,EAAE,CAAC,EAAU,EAAE,EAAU,EAAE,EAAE,CAC9B,MAAM,CAAC,cAAc;aAClB,GAAG,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;aACtD,OAAO,EAAE;aACT,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,IAAI,CAAC;QACrC,IAAI,EAAE,CAAO,MAAM,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,MAAM,wBAAgB,CAAC,SAAS,CAAC,CAAA;YAElD,OAAO,yBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC7C,CAAC,CAAA;QACD,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAA;AACH,CAAC,CAAA,CAAA;AA9CY,QAAA,aAAa,iBA8CzB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,194 @@
1
+ import { __awaiter } from "tslib";
2
+ import * as t from "io-ts";
3
+ import { model } from "@model-ts/core";
4
+ import { createSandbox } from "../sandbox";
5
+ import { Client } from "../client";
6
+ import { getProvider } from "../provider";
7
+ const client = new Client({ tableName: "table" });
8
+ const provider = getProvider(client);
9
+ const SIMPLE_CODEC = t.type({
10
+ foo: t.string,
11
+ bar: t.number,
12
+ });
13
+ class Simple extends model("Simple", SIMPLE_CODEC, provider) {
14
+ get PK() {
15
+ return `PK#${this.foo}`;
16
+ }
17
+ get SK() {
18
+ return `SK#${this.bar}`;
19
+ }
20
+ }
21
+ describe("rollback", () => {
22
+ let sandbox;
23
+ beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
24
+ sandbox = yield createSandbox(client);
25
+ yield sandbox.seed(new Simple({ foo: "seeded1", bar: 1 }), new Simple({ foo: "seeded2", bar: 2 }));
26
+ }));
27
+ afterAll(() => __awaiter(void 0, void 0, void 0, function* () {
28
+ yield sandbox.destroy();
29
+ }));
30
+ test("rolls back newly added items", () => __awaiter(void 0, void 0, void 0, function* () {
31
+ sandbox.startTracking();
32
+ yield new Simple({ foo: "new-item", bar: 99 }).put();
33
+ expect(yield sandbox.get("PK#new-item", "SK#99")).not.toBeNull();
34
+ yield sandbox.rollback();
35
+ expect(yield sandbox.get("PK#new-item", "SK#99")).toBeNull();
36
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).not.toBeNull();
37
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).not.toBeNull();
38
+ }));
39
+ test("rolls back updated items", () => __awaiter(void 0, void 0, void 0, function* () {
40
+ sandbox.startTracking();
41
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "modified" });
42
+ const modified = yield sandbox.get("PK#seeded1", "SK#1");
43
+ expect(modified.foo).toBe("modified");
44
+ yield sandbox.rollback();
45
+ const restored = yield sandbox.get("PK#seeded1", "SK#1");
46
+ expect(restored.foo).toBe("seeded1");
47
+ }));
48
+ test("rolls back deleted items", () => __awaiter(void 0, void 0, void 0, function* () {
49
+ sandbox.startTracking();
50
+ yield Simple.delete({ PK: "PK#seeded1", SK: "SK#1" });
51
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).toBeNull();
52
+ yield sandbox.rollback();
53
+ const restored = yield sandbox.get("PK#seeded1", "SK#1");
54
+ expect(restored).not.toBeNull();
55
+ expect(restored.foo).toBe("seeded1");
56
+ }));
57
+ test("rolls back soft-deleted items", () => __awaiter(void 0, void 0, void 0, function* () {
58
+ sandbox.startTracking();
59
+ const item = new Simple({ foo: "seeded1", bar: 1 });
60
+ // @ts-ignore - _docVersion needed for softDelete encoding
61
+ item._docVersion = 0;
62
+ yield client.softDelete(item);
63
+ // Original should be gone, deleted version should exist
64
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).toBeNull();
65
+ expect(yield sandbox.get("$$DELETED$$PK#seeded1", "$$DELETED$$SK#1")).not.toBeNull();
66
+ yield sandbox.rollback();
67
+ // Original should be restored, deleted version should be gone
68
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).not.toBeNull();
69
+ expect(yield sandbox.get("$$DELETED$$PK#seeded1", "$$DELETED$$SK#1")).toBeNull();
70
+ }));
71
+ test("rolls back mixed operations", () => __awaiter(void 0, void 0, void 0, function* () {
72
+ sandbox.startTracking();
73
+ // Add a new item
74
+ yield new Simple({ foo: "brand-new", bar: 50 }).put();
75
+ // Update an existing item
76
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "changed" });
77
+ // Delete an existing item
78
+ yield Simple.delete({ PK: "PK#seeded2", SK: "SK#2" });
79
+ // Verify all changes took effect
80
+ expect(yield sandbox.get("PK#brand-new", "SK#50")).not.toBeNull();
81
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("changed");
82
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).toBeNull();
83
+ yield sandbox.rollback();
84
+ // New item should be gone
85
+ expect(yield sandbox.get("PK#brand-new", "SK#50")).toBeNull();
86
+ // Updated item should be restored
87
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1");
88
+ // Deleted item should be back
89
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).not.toBeNull();
90
+ }));
91
+ test("supports multiple tracking/rollback cycles", () => __awaiter(void 0, void 0, void 0, function* () {
92
+ // Cycle 1
93
+ sandbox.startTracking();
94
+ yield new Simple({ foo: "cycle1", bar: 10 }).put();
95
+ yield sandbox.rollback();
96
+ expect(yield sandbox.get("PK#cycle1", "SK#10")).toBeNull();
97
+ // Cycle 2
98
+ sandbox.startTracking();
99
+ yield new Simple({ foo: "cycle2", bar: 20 }).put();
100
+ yield sandbox.rollback();
101
+ expect(yield sandbox.get("PK#cycle2", "SK#20")).toBeNull();
102
+ // Cycle 3 - modify seeded data
103
+ sandbox.startTracking();
104
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "cycle3-mod" });
105
+ yield sandbox.rollback();
106
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1");
107
+ // Seeded data is intact throughout
108
+ expect(yield sandbox.get("PK#seeded1", "SK#1")).not.toBeNull();
109
+ expect(yield sandbox.get("PK#seeded2", "SK#2")).not.toBeNull();
110
+ }));
111
+ test("does not track writes before startTracking", () => __awaiter(void 0, void 0, void 0, function* () {
112
+ // Write without tracking
113
+ yield new Simple({ foo: "untracked", bar: 77 }).put();
114
+ // Now start tracking and immediately rollback
115
+ sandbox.startTracking();
116
+ yield sandbox.rollback();
117
+ // The untracked write should still be there
118
+ expect(yield sandbox.get("PK#untracked", "SK#77")).not.toBeNull();
119
+ // Clean up manually for subsequent tests
120
+ sandbox.startTracking();
121
+ yield Simple.delete({ PK: "PK#untracked", SK: "SK#77" });
122
+ yield sandbox.rollback();
123
+ }));
124
+ test("tracks the same key modified multiple times", () => __awaiter(void 0, void 0, void 0, function* () {
125
+ sandbox.startTracking();
126
+ // Update the same item twice
127
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "first-update" });
128
+ yield Simple.updateRaw({ PK: "PK#seeded1", SK: "SK#1" }, { foo: "second-update" });
129
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("second-update");
130
+ yield sandbox.rollback();
131
+ // Should restore to original, not to the intermediate state
132
+ expect((yield sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1");
133
+ }));
134
+ });
135
+ describe("rollback with beforeEach/afterEach pattern", () => {
136
+ let sandbox;
137
+ beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
138
+ sandbox = yield createSandbox(client);
139
+ yield sandbox.seed(new Simple({ foo: "a", bar: 1 }), new Simple({ foo: "b", bar: 2 }));
140
+ }));
141
+ beforeEach(() => {
142
+ sandbox.startTracking();
143
+ });
144
+ afterEach(() => __awaiter(void 0, void 0, void 0, function* () {
145
+ yield sandbox.rollback();
146
+ }));
147
+ afterAll(() => __awaiter(void 0, void 0, void 0, function* () {
148
+ yield sandbox.destroy();
149
+ }));
150
+ test("test A: add an item", () => __awaiter(void 0, void 0, void 0, function* () {
151
+ yield new Simple({ foo: "from-test-a", bar: 100 }).put();
152
+ expect(yield sandbox.get("PK#from-test-a", "SK#100")).not.toBeNull();
153
+ }));
154
+ test("test B: item from test A does not exist", () => __awaiter(void 0, void 0, void 0, function* () {
155
+ expect(yield sandbox.get("PK#from-test-a", "SK#100")).toBeNull();
156
+ }));
157
+ test("test C: modify seeded data", () => __awaiter(void 0, void 0, void 0, function* () {
158
+ yield Simple.updateRaw({ PK: "PK#a", SK: "SK#1" }, { foo: "modified-a" });
159
+ expect((yield sandbox.get("PK#a", "SK#1")).foo).toBe("modified-a");
160
+ }));
161
+ test("test D: seeded data is back to original", () => __awaiter(void 0, void 0, void 0, function* () {
162
+ expect((yield sandbox.get("PK#a", "SK#1")).foo).toBe("a");
163
+ }));
164
+ test("test E: delete seeded data", () => __awaiter(void 0, void 0, void 0, function* () {
165
+ yield Simple.delete({ PK: "PK#b", SK: "SK#2" });
166
+ expect(yield sandbox.get("PK#b", "SK#2")).toBeNull();
167
+ }));
168
+ test("test F: deleted seeded data is back", () => __awaiter(void 0, void 0, void 0, function* () {
169
+ expect(yield sandbox.get("PK#b", "SK#2")).not.toBeNull();
170
+ expect((yield sandbox.get("PK#b", "SK#2")).foo).toBe("b");
171
+ }));
172
+ });
173
+ describe("existing sandbox semantics still work", () => {
174
+ let sandbox;
175
+ beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
176
+ sandbox = yield createSandbox(client);
177
+ }));
178
+ afterEach(() => __awaiter(void 0, void 0, void 0, function* () {
179
+ yield sandbox.destroy();
180
+ }));
181
+ test("create and destroy per test still works", () => __awaiter(void 0, void 0, void 0, function* () {
182
+ yield sandbox.seed(new Simple({ foo: "per-test", bar: 1 }));
183
+ const item = yield sandbox.get("PK#per-test", "SK#1");
184
+ expect(item).not.toBeNull();
185
+ expect(item.foo).toBe("per-test");
186
+ }));
187
+ test("snapshot and diff still work", () => __awaiter(void 0, void 0, void 0, function* () {
188
+ const before = yield sandbox.snapshot();
189
+ yield new Simple({ foo: "diffed", bar: 1 }).put();
190
+ const diffResult = yield sandbox.diff(before);
191
+ expect(diffResult).toContain("PK#diffed");
192
+ }));
193
+ });
194
+ //# sourceMappingURL=rollback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.test.js","sourceRoot":"","sources":["../../../src/__test__/rollback.test.ts"],"names":[],"mappings":"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"}
@@ -16,5 +16,7 @@ export interface Sandbox {
16
16
  diff: (before: {
17
17
  [key: string]: any;
18
18
  }) => Promise<string>;
19
+ startTracking: () => void;
20
+ rollback: () => Promise<void>;
19
21
  }
20
22
  export declare const createSandbox: (client: Client) => Promise<Sandbox>;
@@ -91,9 +91,134 @@ export const getTableContents = (tableName) => __awaiter(void 0, void 0, void 0,
91
91
  items.forEach((item) => (acc[`${item.PK}__${item.SK}`] = item));
92
92
  return acc;
93
93
  });
94
+ const WRITE_METHODS = new Set([
95
+ "put",
96
+ "update",
97
+ "delete",
98
+ "batchWrite",
99
+ "transactWrite",
100
+ ]);
101
+ function createTrackedDocClient(original, tableName) {
102
+ let isTracking = false;
103
+ const trackedKeys = new Map();
104
+ const captureKey = (pk, sk) => __awaiter(this, void 0, void 0, function* () {
105
+ const compositeKey = `${pk}__${sk}`;
106
+ if (trackedKeys.has(compositeKey))
107
+ return;
108
+ const { Item } = yield original
109
+ .get({ TableName: tableName, Key: { PK: pk, SK: sk } })
110
+ .promise();
111
+ trackedKeys.set(compositeKey, { pk, sk, original: Item !== null && Item !== void 0 ? Item : null });
112
+ });
113
+ const captureKeysForOperation = (method, params) => __awaiter(this, void 0, void 0, function* () {
114
+ var _a;
115
+ switch (method) {
116
+ case "put":
117
+ if (params.TableName === tableName && params.Item) {
118
+ yield captureKey(params.Item.PK, params.Item.SK);
119
+ }
120
+ break;
121
+ case "update":
122
+ case "delete":
123
+ if (params.TableName === tableName && params.Key) {
124
+ yield captureKey(params.Key.PK, params.Key.SK);
125
+ }
126
+ break;
127
+ case "batchWrite": {
128
+ const tableItems = ((_a = params.RequestItems) === null || _a === void 0 ? void 0 : _a[tableName]) || [];
129
+ yield Promise.all(tableItems.map((item) => {
130
+ if (item.PutRequest) {
131
+ return captureKey(item.PutRequest.Item.PK, item.PutRequest.Item.SK);
132
+ }
133
+ if (item.DeleteRequest) {
134
+ return captureKey(item.DeleteRequest.Key.PK, item.DeleteRequest.Key.SK);
135
+ }
136
+ }));
137
+ break;
138
+ }
139
+ case "transactWrite": {
140
+ const transactItems = params.TransactItems || [];
141
+ yield Promise.all(transactItems
142
+ .map((item) => {
143
+ var _a, _b, _c;
144
+ if (((_a = item.Put) === null || _a === void 0 ? void 0 : _a.TableName) === tableName) {
145
+ return captureKey(item.Put.Item.PK, item.Put.Item.SK);
146
+ }
147
+ if (((_b = item.Update) === null || _b === void 0 ? void 0 : _b.TableName) === tableName) {
148
+ return captureKey(item.Update.Key.PK, item.Update.Key.SK);
149
+ }
150
+ if (((_c = item.Delete) === null || _c === void 0 ? void 0 : _c.TableName) === tableName) {
151
+ return captureKey(item.Delete.Key.PK, item.Delete.Key.SK);
152
+ }
153
+ })
154
+ .filter(Boolean));
155
+ break;
156
+ }
157
+ }
158
+ });
159
+ const proxy = new Proxy(original, {
160
+ get(target, prop) {
161
+ const value = target[prop];
162
+ if (value === undefined)
163
+ return undefined;
164
+ if (typeof value === "function") {
165
+ if (isTracking && WRITE_METHODS.has(prop)) {
166
+ return (params) => {
167
+ const request = value.call(target, params);
168
+ const origPromise = request.promise.bind(request);
169
+ request.promise = () => __awaiter(this, void 0, void 0, function* () {
170
+ yield captureKeysForOperation(prop, params);
171
+ return origPromise();
172
+ });
173
+ return request;
174
+ };
175
+ }
176
+ return value.bind(target);
177
+ }
178
+ return value;
179
+ },
180
+ });
181
+ return {
182
+ proxy: proxy,
183
+ startTracking: () => {
184
+ isTracking = true;
185
+ trackedKeys.clear();
186
+ },
187
+ rollback: () => __awaiter(this, void 0, void 0, function* () {
188
+ isTracking = false;
189
+ const entries = Array.from(trackedKeys.values());
190
+ const toDelete = entries.filter((e) => e.original === null);
191
+ const toRestore = entries.filter((e) => e.original !== null);
192
+ const deleteChunks = chunksOf(25)(toDelete);
193
+ const restoreChunks = chunksOf(25)(toRestore);
194
+ yield Promise.all([
195
+ ...deleteChunks.map((chunk) => original
196
+ .batchWrite({
197
+ RequestItems: {
198
+ [tableName]: chunk.map(({ pk, sk }) => ({
199
+ DeleteRequest: { Key: { PK: pk, SK: sk } },
200
+ })),
201
+ },
202
+ })
203
+ .promise()),
204
+ ...restoreChunks.map((chunk) => original
205
+ .batchWrite({
206
+ RequestItems: {
207
+ [tableName]: chunk.map(({ original: item }) => ({
208
+ PutRequest: { Item: item },
209
+ })),
210
+ },
211
+ })
212
+ .promise()),
213
+ ]);
214
+ trackedKeys.clear();
215
+ }),
216
+ };
217
+ }
94
218
  export const createSandbox = (client) => __awaiter(void 0, void 0, void 0, function* () {
95
219
  const tableName = yield createTable();
96
- client.setDocumentClient(docClient);
220
+ const tracked = createTrackedDocClient(docClient, tableName);
221
+ client.setDocumentClient(tracked.proxy);
97
222
  client.setTableName(tableName);
98
223
  return {
99
224
  destroy: () => destroyTable(tableName),
@@ -126,6 +251,8 @@ export const createSandbox = (client) => __awaiter(void 0, void 0, void 0, funct
126
251
  const snapshot = yield getTableContents(tableName);
127
252
  return formatSnapshotDiff(before, snapshot);
128
253
  }),
254
+ startTracking: tracked.startTracking,
255
+ rollback: tracked.rollback,
129
256
  };
130
257
  });
131
258
  //# sourceMappingURL=sandbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@model-ts/dynamodb",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "author": "Fabian Finke <finkef@icloud.com>",
@@ -0,0 +1,279 @@
1
+ import * as t from "io-ts"
2
+ import { model } from "@model-ts/core"
3
+ import { Sandbox, createSandbox } from "../sandbox"
4
+ import { Client } from "../client"
5
+ import { getProvider } from "../provider"
6
+
7
+ const client = new Client({ tableName: "table" })
8
+ const provider = getProvider(client)
9
+
10
+ const SIMPLE_CODEC = t.type({
11
+ foo: t.string,
12
+ bar: t.number,
13
+ })
14
+
15
+ class Simple extends model("Simple", SIMPLE_CODEC, provider) {
16
+ get PK() {
17
+ return `PK#${this.foo}`
18
+ }
19
+
20
+ get SK() {
21
+ return `SK#${this.bar}`
22
+ }
23
+ }
24
+
25
+ describe("rollback", () => {
26
+ let sandbox: Sandbox
27
+
28
+ beforeAll(async () => {
29
+ sandbox = await createSandbox(client)
30
+ await sandbox.seed(
31
+ new Simple({ foo: "seeded1", bar: 1 }),
32
+ new Simple({ foo: "seeded2", bar: 2 })
33
+ )
34
+ })
35
+
36
+ afterAll(async () => {
37
+ await sandbox.destroy()
38
+ })
39
+
40
+ test("rolls back newly added items", async () => {
41
+ sandbox.startTracking()
42
+
43
+ await new Simple({ foo: "new-item", bar: 99 }).put()
44
+ expect(await sandbox.get("PK#new-item", "SK#99")).not.toBeNull()
45
+
46
+ await sandbox.rollback()
47
+
48
+ expect(await sandbox.get("PK#new-item", "SK#99")).toBeNull()
49
+ expect(await sandbox.get("PK#seeded1", "SK#1")).not.toBeNull()
50
+ expect(await sandbox.get("PK#seeded2", "SK#2")).not.toBeNull()
51
+ })
52
+
53
+ test("rolls back updated items", async () => {
54
+ sandbox.startTracking()
55
+
56
+ await Simple.updateRaw(
57
+ { PK: "PK#seeded1", SK: "SK#1" },
58
+ { foo: "modified" }
59
+ )
60
+
61
+ const modified = await sandbox.get("PK#seeded1", "SK#1")
62
+ expect(modified.foo).toBe("modified")
63
+
64
+ await sandbox.rollback()
65
+
66
+ const restored = await sandbox.get("PK#seeded1", "SK#1")
67
+ expect(restored.foo).toBe("seeded1")
68
+ })
69
+
70
+ test("rolls back deleted items", async () => {
71
+ sandbox.startTracking()
72
+
73
+ await Simple.delete({ PK: "PK#seeded1", SK: "SK#1" })
74
+ expect(await sandbox.get("PK#seeded1", "SK#1")).toBeNull()
75
+
76
+ await sandbox.rollback()
77
+
78
+ const restored = await sandbox.get("PK#seeded1", "SK#1")
79
+ expect(restored).not.toBeNull()
80
+ expect(restored.foo).toBe("seeded1")
81
+ })
82
+
83
+ test("rolls back soft-deleted items", async () => {
84
+ sandbox.startTracking()
85
+
86
+ const item = new Simple({ foo: "seeded1", bar: 1 })
87
+ // @ts-ignore - _docVersion needed for softDelete encoding
88
+ item._docVersion = 0
89
+ await client.softDelete(item)
90
+
91
+ // Original should be gone, deleted version should exist
92
+ expect(await sandbox.get("PK#seeded1", "SK#1")).toBeNull()
93
+ expect(
94
+ await sandbox.get("$$DELETED$$PK#seeded1", "$$DELETED$$SK#1")
95
+ ).not.toBeNull()
96
+
97
+ await sandbox.rollback()
98
+
99
+ // Original should be restored, deleted version should be gone
100
+ expect(await sandbox.get("PK#seeded1", "SK#1")).not.toBeNull()
101
+ expect(
102
+ await sandbox.get("$$DELETED$$PK#seeded1", "$$DELETED$$SK#1")
103
+ ).toBeNull()
104
+ })
105
+
106
+ test("rolls back mixed operations", async () => {
107
+ sandbox.startTracking()
108
+
109
+ // Add a new item
110
+ await new Simple({ foo: "brand-new", bar: 50 }).put()
111
+
112
+ // Update an existing item
113
+ await Simple.updateRaw(
114
+ { PK: "PK#seeded1", SK: "SK#1" },
115
+ { foo: "changed" }
116
+ )
117
+
118
+ // Delete an existing item
119
+ await Simple.delete({ PK: "PK#seeded2", SK: "SK#2" })
120
+
121
+ // Verify all changes took effect
122
+ expect(await sandbox.get("PK#brand-new", "SK#50")).not.toBeNull()
123
+ expect((await sandbox.get("PK#seeded1", "SK#1")).foo).toBe("changed")
124
+ expect(await sandbox.get("PK#seeded2", "SK#2")).toBeNull()
125
+
126
+ await sandbox.rollback()
127
+
128
+ // New item should be gone
129
+ expect(await sandbox.get("PK#brand-new", "SK#50")).toBeNull()
130
+ // Updated item should be restored
131
+ expect((await sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1")
132
+ // Deleted item should be back
133
+ expect(await sandbox.get("PK#seeded2", "SK#2")).not.toBeNull()
134
+ })
135
+
136
+ test("supports multiple tracking/rollback cycles", async () => {
137
+ // Cycle 1
138
+ sandbox.startTracking()
139
+ await new Simple({ foo: "cycle1", bar: 10 }).put()
140
+ await sandbox.rollback()
141
+ expect(await sandbox.get("PK#cycle1", "SK#10")).toBeNull()
142
+
143
+ // Cycle 2
144
+ sandbox.startTracking()
145
+ await new Simple({ foo: "cycle2", bar: 20 }).put()
146
+ await sandbox.rollback()
147
+ expect(await sandbox.get("PK#cycle2", "SK#20")).toBeNull()
148
+
149
+ // Cycle 3 - modify seeded data
150
+ sandbox.startTracking()
151
+ await Simple.updateRaw(
152
+ { PK: "PK#seeded1", SK: "SK#1" },
153
+ { foo: "cycle3-mod" }
154
+ )
155
+ await sandbox.rollback()
156
+ expect((await sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1")
157
+
158
+ // Seeded data is intact throughout
159
+ expect(await sandbox.get("PK#seeded1", "SK#1")).not.toBeNull()
160
+ expect(await sandbox.get("PK#seeded2", "SK#2")).not.toBeNull()
161
+ })
162
+
163
+ test("does not track writes before startTracking", async () => {
164
+ // Write without tracking
165
+ await new Simple({ foo: "untracked", bar: 77 }).put()
166
+
167
+ // Now start tracking and immediately rollback
168
+ sandbox.startTracking()
169
+ await sandbox.rollback()
170
+
171
+ // The untracked write should still be there
172
+ expect(await sandbox.get("PK#untracked", "SK#77")).not.toBeNull()
173
+
174
+ // Clean up manually for subsequent tests
175
+ sandbox.startTracking()
176
+ await Simple.delete({ PK: "PK#untracked", SK: "SK#77" })
177
+ await sandbox.rollback()
178
+ })
179
+
180
+ test("tracks the same key modified multiple times", async () => {
181
+ sandbox.startTracking()
182
+
183
+ // Update the same item twice
184
+ await Simple.updateRaw(
185
+ { PK: "PK#seeded1", SK: "SK#1" },
186
+ { foo: "first-update" }
187
+ )
188
+ await Simple.updateRaw(
189
+ { PK: "PK#seeded1", SK: "SK#1" },
190
+ { foo: "second-update" }
191
+ )
192
+
193
+ expect((await sandbox.get("PK#seeded1", "SK#1")).foo).toBe("second-update")
194
+
195
+ await sandbox.rollback()
196
+
197
+ // Should restore to original, not to the intermediate state
198
+ expect((await sandbox.get("PK#seeded1", "SK#1")).foo).toBe("seeded1")
199
+ })
200
+ })
201
+
202
+ describe("rollback with beforeEach/afterEach pattern", () => {
203
+ let sandbox: Sandbox
204
+
205
+ beforeAll(async () => {
206
+ sandbox = await createSandbox(client)
207
+ await sandbox.seed(
208
+ new Simple({ foo: "a", bar: 1 }),
209
+ new Simple({ foo: "b", bar: 2 })
210
+ )
211
+ })
212
+
213
+ beforeEach(() => {
214
+ sandbox.startTracking()
215
+ })
216
+
217
+ afterEach(async () => {
218
+ await sandbox.rollback()
219
+ })
220
+
221
+ afterAll(async () => {
222
+ await sandbox.destroy()
223
+ })
224
+
225
+ test("test A: add an item", async () => {
226
+ await new Simple({ foo: "from-test-a", bar: 100 }).put()
227
+ expect(await sandbox.get("PK#from-test-a", "SK#100")).not.toBeNull()
228
+ })
229
+
230
+ test("test B: item from test A does not exist", async () => {
231
+ expect(await sandbox.get("PK#from-test-a", "SK#100")).toBeNull()
232
+ })
233
+
234
+ test("test C: modify seeded data", async () => {
235
+ await Simple.updateRaw({ PK: "PK#a", SK: "SK#1" }, { foo: "modified-a" })
236
+ expect((await sandbox.get("PK#a", "SK#1")).foo).toBe("modified-a")
237
+ })
238
+
239
+ test("test D: seeded data is back to original", async () => {
240
+ expect((await sandbox.get("PK#a", "SK#1")).foo).toBe("a")
241
+ })
242
+
243
+ test("test E: delete seeded data", async () => {
244
+ await Simple.delete({ PK: "PK#b", SK: "SK#2" })
245
+ expect(await sandbox.get("PK#b", "SK#2")).toBeNull()
246
+ })
247
+
248
+ test("test F: deleted seeded data is back", async () => {
249
+ expect(await sandbox.get("PK#b", "SK#2")).not.toBeNull()
250
+ expect((await sandbox.get("PK#b", "SK#2")).foo).toBe("b")
251
+ })
252
+ })
253
+
254
+ describe("existing sandbox semantics still work", () => {
255
+ let sandbox: Sandbox
256
+
257
+ beforeEach(async () => {
258
+ sandbox = await createSandbox(client)
259
+ })
260
+
261
+ afterEach(async () => {
262
+ await sandbox.destroy()
263
+ })
264
+
265
+ test("create and destroy per test still works", async () => {
266
+ await sandbox.seed(new Simple({ foo: "per-test", bar: 1 }))
267
+
268
+ const item = await sandbox.get("PK#per-test", "SK#1")
269
+ expect(item).not.toBeNull()
270
+ expect(item.foo).toBe("per-test")
271
+ })
272
+
273
+ test("snapshot and diff still work", async () => {
274
+ const before = await sandbox.snapshot()
275
+ await new Simple({ foo: "diffed", bar: 1 }).put()
276
+ const diffResult = await sandbox.diff(before)
277
+ expect(diffResult).toContain("PK#diffed")
278
+ })
279
+ })
package/src/sandbox.ts CHANGED
@@ -105,18 +105,186 @@ export const getTableContents = async (
105
105
  return acc
106
106
  }
107
107
 
108
+ // -------------------------------------------------------------------------------------
109
+ // Tracking
110
+ // -------------------------------------------------------------------------------------
111
+
112
+ interface TrackedEntry {
113
+ pk: string
114
+ sk: string
115
+ original: any | null
116
+ }
117
+
118
+ const WRITE_METHODS = new Set([
119
+ "put",
120
+ "update",
121
+ "delete",
122
+ "batchWrite",
123
+ "transactWrite",
124
+ ])
125
+
126
+ function createTrackedDocClient(
127
+ original: DynamoDB.DocumentClient,
128
+ tableName: string
129
+ ) {
130
+ let isTracking = false
131
+ const trackedKeys = new Map<string, TrackedEntry>()
132
+
133
+ const captureKey = async (pk: string, sk: string) => {
134
+ const compositeKey = `${pk}__${sk}`
135
+ if (trackedKeys.has(compositeKey)) return
136
+
137
+ const { Item } = await original
138
+ .get({ TableName: tableName, Key: { PK: pk, SK: sk } })
139
+ .promise()
140
+
141
+ trackedKeys.set(compositeKey, { pk, sk, original: Item ?? null })
142
+ }
143
+
144
+ const captureKeysForOperation = async (method: string, params: any) => {
145
+ switch (method) {
146
+ case "put":
147
+ if (params.TableName === tableName && params.Item) {
148
+ await captureKey(params.Item.PK, params.Item.SK)
149
+ }
150
+ break
151
+ case "update":
152
+ case "delete":
153
+ if (params.TableName === tableName && params.Key) {
154
+ await captureKey(params.Key.PK, params.Key.SK)
155
+ }
156
+ break
157
+ case "batchWrite": {
158
+ const tableItems = params.RequestItems?.[tableName] || []
159
+ await Promise.all(
160
+ tableItems.map((item: any) => {
161
+ if (item.PutRequest) {
162
+ return captureKey(
163
+ item.PutRequest.Item.PK,
164
+ item.PutRequest.Item.SK
165
+ )
166
+ }
167
+ if (item.DeleteRequest) {
168
+ return captureKey(
169
+ item.DeleteRequest.Key.PK,
170
+ item.DeleteRequest.Key.SK
171
+ )
172
+ }
173
+ })
174
+ )
175
+ break
176
+ }
177
+ case "transactWrite": {
178
+ const transactItems = params.TransactItems || []
179
+ await Promise.all(
180
+ transactItems
181
+ .map((item: any) => {
182
+ if (item.Put?.TableName === tableName) {
183
+ return captureKey(item.Put.Item.PK, item.Put.Item.SK)
184
+ }
185
+ if (item.Update?.TableName === tableName) {
186
+ return captureKey(item.Update.Key.PK, item.Update.Key.SK)
187
+ }
188
+ if (item.Delete?.TableName === tableName) {
189
+ return captureKey(item.Delete.Key.PK, item.Delete.Key.SK)
190
+ }
191
+ })
192
+ .filter(Boolean)
193
+ )
194
+ break
195
+ }
196
+ }
197
+ }
198
+
199
+ const proxy = new Proxy(original, {
200
+ get(target, prop) {
201
+ const value = (target as any)[prop]
202
+ if (value === undefined) return undefined
203
+
204
+ if (typeof value === "function") {
205
+ if (isTracking && WRITE_METHODS.has(prop as string)) {
206
+ return (params: any) => {
207
+ const request = value.call(target, params)
208
+ const origPromise = request.promise.bind(request)
209
+ request.promise = async () => {
210
+ await captureKeysForOperation(prop as string, params)
211
+ return origPromise()
212
+ }
213
+ return request
214
+ }
215
+ }
216
+ return value.bind(target)
217
+ }
218
+
219
+ return value
220
+ },
221
+ })
222
+
223
+ return {
224
+ proxy: proxy as DynamoDB.DocumentClient,
225
+ startTracking: () => {
226
+ isTracking = true
227
+ trackedKeys.clear()
228
+ },
229
+ rollback: async () => {
230
+ isTracking = false
231
+
232
+ const entries = Array.from(trackedKeys.values())
233
+ const toDelete = entries.filter((e) => e.original === null)
234
+ const toRestore = entries.filter((e) => e.original !== null)
235
+
236
+ const deleteChunks = chunksOf(25)(toDelete)
237
+ const restoreChunks = chunksOf(25)(toRestore)
238
+
239
+ await Promise.all([
240
+ ...deleteChunks.map((chunk) =>
241
+ original
242
+ .batchWrite({
243
+ RequestItems: {
244
+ [tableName]: chunk.map(({ pk, sk }) => ({
245
+ DeleteRequest: { Key: { PK: pk, SK: sk } },
246
+ })),
247
+ },
248
+ })
249
+ .promise()
250
+ ),
251
+ ...restoreChunks.map((chunk) =>
252
+ original
253
+ .batchWrite({
254
+ RequestItems: {
255
+ [tableName]: chunk.map(({ original: item }) => ({
256
+ PutRequest: { Item: item },
257
+ })),
258
+ },
259
+ })
260
+ .promise()
261
+ ),
262
+ ])
263
+
264
+ trackedKeys.clear()
265
+ },
266
+ }
267
+ }
268
+
269
+ // -------------------------------------------------------------------------------------
270
+ // Sandbox
271
+ // -------------------------------------------------------------------------------------
272
+
108
273
  export interface Sandbox {
109
274
  destroy: () => Promise<void>
110
275
  snapshot: () => Promise<{ [key: string]: any }>
111
276
  seed: (...args: Array<{ [key: string]: any }>) => Promise<void>
112
277
  get: (pk: string, sk: string) => Promise<null | any>
113
278
  diff: (before: { [key: string]: any }) => Promise<string>
279
+ startTracking: () => void
280
+ rollback: () => Promise<void>
114
281
  }
115
282
 
116
283
  export const createSandbox = async (client: Client): Promise<Sandbox> => {
117
284
  const tableName = await createTable()
118
285
 
119
- client.setDocumentClient(docClient)
286
+ const tracked = createTrackedDocClient(docClient, tableName)
287
+ client.setDocumentClient(tracked.proxy)
120
288
  client.setTableName(tableName)
121
289
 
122
290
  return {
@@ -155,5 +323,7 @@ export const createSandbox = async (client: Client): Promise<Sandbox> => {
155
323
 
156
324
  return formatSnapshotDiff(before, snapshot)
157
325
  },
326
+ startTracking: tracked.startTracking,
327
+ rollback: tracked.rollback,
158
328
  }
159
329
  }