@proteinjs/db 1.54.2 → 1.54.3
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 +11 -0
- package/dist/src/Record.d.ts +16 -0
- package/dist/src/Record.d.ts.map +1 -1
- package/dist/src/Record.js +52 -2
- package/dist/src/Record.js.map +1 -1
- package/dist/test/LegacyCellHydration.test.d.ts +2 -0
- package/dist/test/LegacyCellHydration.test.d.ts.map +1 -0
- package/dist/test/LegacyCellHydration.test.js +321 -0
- package/dist/test/LegacyCellHydration.test.js.map +1 -0
- package/dist/test/reusable/ColumnTypesTests.d.ts.map +1 -1
- package/dist/test/reusable/ColumnTypesTests.js +55 -0
- package/dist/test/reusable/ColumnTypesTests.js.map +1 -1
- package/package.json +2 -2
- package/src/Record.ts +57 -5
- package/test/LegacyCellHydration.test.ts +234 -0
- package/test/reusable/ColumnTypesTests.ts +47 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.54.3](https://github.com/proteinjs/db/compare/@proteinjs/db@1.54.2...@proteinjs/db@1.54.3) (2026-10-16)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **db:** a stored cell a column cannot deserialize never takes the row, the result set or the process with it ([e920974](https://github.com/proteinjs/db/commit/e9209748a054fd30b51f19251fffd6bf2c6da725))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## [1.54.2](https://github.com/proteinjs/db/compare/@proteinjs/db@1.54.1...@proteinjs/db@1.54.2) (2026-10-16)
|
|
7
18
|
|
|
8
19
|
|
package/dist/src/Record.d.ts
CHANGED
|
@@ -24,6 +24,13 @@ export type RecordEncryptionContext = {
|
|
|
24
24
|
keyOwner: string;
|
|
25
25
|
};
|
|
26
26
|
export declare class RecordSerializer<T extends Record> {
|
|
27
|
+
/**
|
|
28
|
+
* The table-and-column pairs whose stored cells have failed to deserialize in this process
|
|
29
|
+
* (`omitCellNotDeserialized`): each is warned once. A legacy cell is read again by every query
|
|
30
|
+
* that touches its row — a background sweep reads some rows every few seconds — and the warning
|
|
31
|
+
* is a schema fact, not a per-read event.
|
|
32
|
+
*/
|
|
33
|
+
private static legacyCellsWarned;
|
|
27
34
|
private logger;
|
|
28
35
|
private table;
|
|
29
36
|
private encryptionContext?;
|
|
@@ -48,6 +55,15 @@ export declare class RecordSerializer<T extends Record> {
|
|
|
48
55
|
*/
|
|
49
56
|
private defineFieldReadOnFirstRead;
|
|
50
57
|
private hydrationPlan;
|
|
58
|
+
/**
|
|
59
|
+
* A stored cell the column cannot deserialize — a value written past the serializer, the way a
|
|
60
|
+
* hand-run statement or an older writer leaves it — never takes the row, the result set or the
|
|
61
|
+
* process with it. The field is omitted from the record (the law the per-row hydration held:
|
|
62
|
+
* `try { deserialize } catch { omit }`; what a reader of an optional field already takes as
|
|
63
|
+
* absent), and one warning per table and column per process names the table, the column and the
|
|
64
|
+
* first row seen — never the stored value, which the parser's own message quotes.
|
|
65
|
+
*/
|
|
66
|
+
private omitCellNotDeserialized;
|
|
51
67
|
private isPromise;
|
|
52
68
|
}
|
|
53
69
|
export declare class FieldSerializer<T extends Record> {
|
package/dist/src/Record.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Record.d.ts","sourceRoot":"","sources":["../../src/Record.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,MAAM,MAAM,CAErE;AAoBD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,MAAM,CAAC,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,MAAM,CAAC,CAAC,CAElD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAE7D;6FAC6F;AAC7F,MAAM,MAAM,uBAAuB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAiB3D,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM;IAC5C,OAAO,CAAC,MAAM,CAA+C;IAC7D,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,iBAAiB,CAAC,CAA0B;IACpD,OAAO,CAAC,IAAI,CAAC,CAAgB;gBAEjB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,uBAAuB;IAKlE,SAAS,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCvD;;;;;;OAMG;IACH,cAAc,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAezE,4EAA4E;IACtE,WAAW,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjE,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"Record.d.ts","sourceRoot":"","sources":["../../src/Record.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,MAAM,MAAM,CAErE;AAoBD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,MAAM,CAAC,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,MAAM,CAAC,CAAC,CAElD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAE7D;6FAC6F;AAC7F,MAAM,MAAM,uBAAuB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAiB3D,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM;IAC5C;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAqB;IACrD,OAAO,CAAC,MAAM,CAA+C;IAC7D,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,iBAAiB,CAAC,CAA0B;IACpD,OAAO,CAAC,IAAI,CAAC,CAAgB;gBAEjB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,uBAAuB;IAKlE,SAAS,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCvD;;;;;;OAMG;IACH,cAAc,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAezE,4EAA4E;IACtE,WAAW,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjE,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,eAAe;IA+DvB;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IAgClC,OAAO,CAAC,aAAa;IAyBrB;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,SAAS;CAGlB;AAED,qBAAa,eAAe,CAAC,CAAC,SAAS,MAAM;IAC/B,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7B,SAAS,CAAC,iBAAiB,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG;;;;IAepD,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,oBAAoB,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;;;;CA2BpG"}
|
package/dist/src/Record.js
CHANGED
|
@@ -229,6 +229,7 @@ var RecordSerializer = /** @class */ (function () {
|
|
|
229
229
|
return this.hydratePrepared(plan, prepared);
|
|
230
230
|
};
|
|
231
231
|
RecordSerializer.prototype.hydratePrepared = function (plan, prepared) {
|
|
232
|
+
var _this = this;
|
|
232
233
|
var record = {};
|
|
233
234
|
var settling;
|
|
234
235
|
var omittedFields;
|
|
@@ -249,11 +250,21 @@ var RecordSerializer = /** @class */ (function () {
|
|
|
249
250
|
this_1.defineFieldReadOnFirstRead(record, propertyName, column, storedValue);
|
|
250
251
|
return "continue";
|
|
251
252
|
}
|
|
252
|
-
var fieldValue =
|
|
253
|
+
var fieldValue = void 0;
|
|
254
|
+
try {
|
|
255
|
+
fieldValue = column.deserialize(storedValue, prepared);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
this_1.omitCellNotDeserialized(columnName, prepared, error);
|
|
259
|
+
return "continue";
|
|
260
|
+
}
|
|
253
261
|
if (this_1.isPromise(fieldValue)) {
|
|
254
262
|
record[propertyName] = undefined; // seats the property in column order; the value lands when it settles
|
|
255
263
|
(settling !== null && settling !== void 0 ? settling : (settling = [])).push(fieldValue.then(function (value) {
|
|
256
264
|
record[propertyName] = value;
|
|
265
|
+
}, function (error) {
|
|
266
|
+
delete record[propertyName];
|
|
267
|
+
_this.omitCellNotDeserialized(columnName, prepared, error);
|
|
257
268
|
}));
|
|
258
269
|
return "continue";
|
|
259
270
|
}
|
|
@@ -277,15 +288,23 @@ var RecordSerializer = /** @class */ (function () {
|
|
|
277
288
|
* (`Column.deserializeOnFirstRead`); a write replaces it like any other field.
|
|
278
289
|
*/
|
|
279
290
|
RecordSerializer.prototype.defineFieldReadOnFirstRead = function (record, propertyName, column, storedValue) {
|
|
291
|
+
var _this = this;
|
|
280
292
|
var value;
|
|
281
293
|
var read = false;
|
|
294
|
+
var omit = function (error) { return _this.omitCellNotDeserialized(column.name, record, error); };
|
|
282
295
|
Object.defineProperty(record, propertyName, {
|
|
283
296
|
enumerable: true,
|
|
284
297
|
configurable: true,
|
|
285
298
|
get: function () {
|
|
286
299
|
if (!read) {
|
|
287
|
-
value = column.deserialize(storedValue, undefined);
|
|
288
300
|
read = true;
|
|
301
|
+
try {
|
|
302
|
+
value = column.deserialize(storedValue, undefined);
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
delete record[propertyName];
|
|
306
|
+
omit(error);
|
|
307
|
+
}
|
|
289
308
|
}
|
|
290
309
|
return value;
|
|
291
310
|
},
|
|
@@ -316,9 +335,40 @@ var RecordSerializer = /** @class */ (function () {
|
|
|
316
335
|
this.plan = { hooks: new EncryptionRecordHooks(), slotsByColumnName: slotsByColumnName };
|
|
317
336
|
return this.plan;
|
|
318
337
|
};
|
|
338
|
+
/**
|
|
339
|
+
* A stored cell the column cannot deserialize — a value written past the serializer, the way a
|
|
340
|
+
* hand-run statement or an older writer leaves it — never takes the row, the result set or the
|
|
341
|
+
* process with it. The field is omitted from the record (the law the per-row hydration held:
|
|
342
|
+
* `try { deserialize } catch { omit }`; what a reader of an optional field already takes as
|
|
343
|
+
* absent), and one warning per table and column per process names the table, the column and the
|
|
344
|
+
* first row seen — never the stored value, which the parser's own message quotes.
|
|
345
|
+
*/
|
|
346
|
+
RecordSerializer.prototype.omitCellNotDeserialized = function (columnName, row, error) {
|
|
347
|
+
var cell = "".concat(this.table.name, ".").concat(columnName);
|
|
348
|
+
if (RecordSerializer.legacyCellsWarned.has(cell)) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
RecordSerializer.legacyCellsWarned.add(cell);
|
|
352
|
+
this.logger.warn({
|
|
353
|
+
message: "A stored cell could not be deserialized; the field is omitted from the record",
|
|
354
|
+
obj: {
|
|
355
|
+
table: this.table.name,
|
|
356
|
+
column: columnName,
|
|
357
|
+
id: row['id'],
|
|
358
|
+
error: error instanceof Error ? error.name : typeof error,
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
};
|
|
319
362
|
RecordSerializer.prototype.isPromise = function (value) {
|
|
320
363
|
return typeof (value === null || value === void 0 ? void 0 : value.then) === 'function';
|
|
321
364
|
};
|
|
365
|
+
/**
|
|
366
|
+
* The table-and-column pairs whose stored cells have failed to deserialize in this process
|
|
367
|
+
* (`omitCellNotDeserialized`): each is warned once. A legacy cell is read again by every query
|
|
368
|
+
* that touches its row — a background sweep reads some rows every few seconds — and the warning
|
|
369
|
+
* is a schema fact, not a per-read event.
|
|
370
|
+
*/
|
|
371
|
+
RecordSerializer.legacyCellsWarned = new Set();
|
|
322
372
|
return RecordSerializer;
|
|
323
373
|
}());
|
|
324
374
|
exports.RecordSerializer = RecordSerializer;
|
package/dist/src/Record.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Record.js","sourceRoot":"","sources":["../../src/Record.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA2C;AAC3C,qCAAuD;AAEvD,uCAAsC;AAStC,SAAgB,cAAc,CAAC,MAAc;IAC3C,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,CAAC;AACzE,CAAC;AAFD,wCAEC;AAED,IAAM,aAAa,GAAoB;IACrC,EAAE,EAAE,IAAI,oBAAU,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;IAClD,OAAO,EAAE,IAAI,wBAAc,CAAC,SAAS,EAAE;QACrC,YAAY,EAAE;YAAY,sBAAA,IAAA,eAAM,GAAE,EAAA;iBAAA;KACnC,CAAC;IACF,OAAO,EAAE,IAAI,wBAAc,CAAC,SAAS,EAAE;QACrC,YAAY,EAAE;YAAY,sBAAA,IAAA,eAAM,GAAE,EAAA;iBAAA;QAClC,WAAW,EAAE;YAAY,sBAAA,IAAA,eAAM,GAAE,EAAA;iBAAA;KAClC,CAAC;CACH,CAAC;AAEF;IAAgC,qCAAK;IACnC,2BAAY,SAAiB,EAAE,SAAiB;QAAhD,YACE,kBAAM,gBAAS,SAAS,gCAAsB,SAAS,CAAE,CAAC,SAE3D;QADC,KAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;;IAClC,CAAC;IACH,wBAAC;AAAD,CAAC,AALD,CAAgC,KAAK,GAKpC;AAED;;;;;;;GAOG;AACH,SAAgB,iBAAiB,CAC/B,OAAuC;IAEvC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC;AAJD,8CAIC;AAuBD;
|
|
1
|
+
{"version":3,"file":"Record.js","sourceRoot":"","sources":["../../src/Record.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA2C;AAC3C,qCAAuD;AAEvD,uCAAsC;AAStC,SAAgB,cAAc,CAAC,MAAc;IAC3C,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,CAAC;AACzE,CAAC;AAFD,wCAEC;AAED,IAAM,aAAa,GAAoB;IACrC,EAAE,EAAE,IAAI,oBAAU,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;IAClD,OAAO,EAAE,IAAI,wBAAc,CAAC,SAAS,EAAE;QACrC,YAAY,EAAE;YAAY,sBAAA,IAAA,eAAM,GAAE,EAAA;iBAAA;KACnC,CAAC;IACF,OAAO,EAAE,IAAI,wBAAc,CAAC,SAAS,EAAE;QACrC,YAAY,EAAE;YAAY,sBAAA,IAAA,eAAM,GAAE,EAAA;iBAAA;QAClC,WAAW,EAAE;YAAY,sBAAA,IAAA,eAAM,GAAE,EAAA;iBAAA;KAClC,CAAC;CACH,CAAC;AAEF;IAAgC,qCAAK;IACnC,2BAAY,SAAiB,EAAE,SAAiB;QAAhD,YACE,kBAAM,gBAAS,SAAS,gCAAsB,SAAS,CAAE,CAAC,SAE3D;QADC,KAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;;IAClC,CAAC;IACH,wBAAC;AAAD,CAAC,AALD,CAAgC,KAAK,GAKpC;AAED;;;;;;;GAOG;AACH,SAAgB,iBAAiB,CAC/B,OAAuC;IAEvC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC;AAJD,8CAIC;AAuBD;IAaE,0BAAY,KAAe,EAAE,iBAA2C;QALhE,WAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAM3D,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IAC7C,CAAC;IAEK,oCAAS,GAAf,UAAgB,MAAW;;;;;;wBACnB,UAAU,GAAQ,EAAE,CAAC;wBACrB,eAAe,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBAClD,aAAa,GAAa,EAAE,CAAC;6BACH,MAAM;;;;;;;;;;;wBACpC,IAAI,OAAO,MAAM,CAAC,iBAAiB,CAAC,KAAK,UAAU,EAAE;4BACnD,wBAAS;yBACV;wBAEkB,qBAAM,MAAM,CAAC,iBAAiB,CAAC,EAAA;;wBAA5C,UAAU,GAAG,SAA+B;wBAClD,IAAI,UAAU,KAAK,SAAS,EAAE;4BACtB,wBAAwB,GAAG,qEAA8D,IAAI,CAAC,KAAK,CAAC,IAAI,cAAI,iBAAiB,CAAE,CAAC;4BACtI,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;yBAC3C;;;;wBAE8C,qBAAM,eAAe,CAAC,SAAS,CAAC,iBAAiB,EAAE,UAAU,CAAC,EAAA;;wBAArG,KAAuC,SAA8D,EAAnG,UAAU,gBAAA,EAAE,oBAAoB,0BAAA;wBACxC,UAAU,CAAC,UAAU,CAAC,GAAG,oBAAoB,CAAC;;;;wBAE9C,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;;;;;;wBAI1C,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;4BAC5B,qEAAqE;4BACrE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0CAA0C,EAAE,GAAG,EAAE,EAAE,aAAa,eAAA,EAAE,EAAE,CAAC,CAAC;yBACnG;wBAMiC,sFAAa,oCAAoC,QAAC;;wBAA5E,qBAAqB,GAAK,CAAA,SAAkD,CAAA,sBAAvD;wBAC7B,qBAAM,IAAI,qBAAqB,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,EAAA;;wBAA7F,SAA6F,CAAC;wBAC9F,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;OAMG;IACH,yCAAc,GAAd,UAAe,iBAAqC;QAClD,IAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,IAAM,OAAO,GAAuB,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACxE,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACjD,IAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;gBAC1B,OAAO,GAAG,IAAI,CAAC;aAChB;YACD,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;SACrB;QAED,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,OAAe,CAAC;IAC3D,CAAC;IAED,4EAA4E;IACtE,sCAAW,GAAjB,UAAkB,gBAAkC;;;;4BAC3C,qBAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC,EAAA;4BAAjE,sBAAO,SAA0D,EAAC;;;;KACnE;IAEO,kCAAO,GAAf,UAAgB,IAAmB,EAAE,gBAAkC;QAAvE,iBAUC;QATC,uFAAuF;QACvF,wFAAwF;QACxF,kDAAkD;QAClD,IAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;YAC5B,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAC,GAAG,IAAK,OAAA,KAAI,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,EAA/B,CAA+B,CAAC,CAAC;SAChE;QAED,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAEO,0CAAe,GAAvB,UAAwB,IAAmB,EAAE,QAA0B;QAAvE,iBA6DC;QA5DC,IAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,IAAI,QAAqC,CAAC;QAC1C,IAAI,aAAmC,CAAC;gCAC7B,UAAU;YACnB,IAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,CAAC,IAAI,EAAE;gBACT,uEAAuE;gBACvE,CAAC,aAAa,aAAb,aAAa,cAAb,aAAa,IAAb,aAAa,GAAK,EAAE,EAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;;aAEzC;YAEO,IAAA,YAAY,GAAa,IAAI,aAAjB,EAAE,MAAM,GAAK,IAAI,OAAT,CAAU;YACtC,IAAM,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;gBACvB,MAAM,CAAC,YAAY,CAAC,GAAG,WAAW,CAAC;;aAEpC;YAED,IAAI,MAAM,CAAC,sBAAsB,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,SAAS,EAAE;gBACtF,OAAK,0BAA0B,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;;aAE5E;YAED,IAAI,UAAU,SAAS,CAAC;YACxB,IAAI;gBACF,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;aACxD;YAAC,OAAO,KAAK,EAAE;gBACd,OAAK,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;;aAE3D;YAED,IAAI,OAAK,SAAS,CAAC,UAAU,CAAC,EAAE;gBAC9B,MAAM,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,CAAC,sEAAsE;gBACxG,CAAC,QAAQ,aAAR,QAAQ,cAAR,QAAQ,IAAR,QAAQ,GAAK,EAAE,EAAC,CAAC,IAAI,CACpB,UAAU,CAAC,IAAI,CACb,UAAC,KAAK;oBACJ,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC;gBAC/B,CAAC,EACD,UAAC,KAAK;oBACJ,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC;oBAC5B,KAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC5D,CAAC,CACF,CACF,CAAC;;aAEH;YAED,MAAM,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC;;;QA5CpC,KAAK,IAAM,UAAU,IAAI,QAAQ;oBAAtB,UAAU;SA6CpB;QAED,IAAI,aAAa,EAAE;YACjB,wDAAwD;YACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,4CAA4C,EAAE,GAAG,EAAE,EAAE,aAAa,eAAA,EAAE,EAAE,CAAC,CAAC;SACtG;QAED,IAAI,QAAQ,EAAE;YACZ,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,cAAM,OAAA,MAAW,EAAX,CAAW,CAAC,CAAC;SACtD;QAED,OAAO,MAAW,CAAC;IACrB,CAAC;IAED;;;OAGG;IACK,qDAA0B,GAAlC,UACE,MAAW,EACX,YAAoB,EACpB,MAAwB,EACxB,WAAoB;QAJtB,iBA8BC;QAxBC,IAAI,KAAc,CAAC;QACnB,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,IAAM,IAAI,GAAG,UAAC,KAAc,IAAK,OAAA,KAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAxD,CAAwD,CAAC;QAC1F,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE;YAC1C,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;YAClB,GAAG;gBACD,IAAI,CAAC,IAAI,EAAE;oBACT,IAAI,GAAG,IAAI,CAAC;oBACZ,IAAI;wBACF,KAAK,GAAG,MAAM,CAAC,WAAY,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;qBACrD;oBAAC,OAAO,KAAK,EAAE;wBACd,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC;wBAC5B,IAAI,CAAC,KAAK,CAAC,CAAC;qBACb;iBACF;gBAED,OAAO,KAAK,CAAC;YACf,CAAC;YACD,GAAG,YAAC,IAAa;gBACf,KAAK,GAAG,IAAI,CAAC;gBACb,IAAI,GAAG,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAEO,wCAAa,GAArB;QACE,IAAI,IAAI,CAAC,IAAI,EAAE;YACb,OAAO,IAAI,CAAC,IAAI,CAAC;SAClB;QAED,2FAA2F;QAC3F,+DAA+D;QAC/D,8DAA8D;QACtD,IAAA,qBAAqB,GAC3B,OAAO,CAAC,oCAAoC,CAAwD,sBADzE,CAC0E;QACvG,IAAM,iBAAiB,GAAuC,EAAE,CAAC;QACjE,IAAM,OAAO,GAAiD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACjF,sFAAsF;QACtF,8DAA8D;QAC9D,KAAK,IAAM,YAAY,IAAI,OAAO,EAAE;YAClC,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,cAAA,EAAE,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;SACjG;QACD,KAAK,IAAM,YAAY,IAAI,OAAO,EAAE;YAClC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,YAAY,cAAA,EAAE,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;SACnF;QAED,IAAI,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,qBAAqB,EAAE,EAAE,iBAAiB,mBAAA,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACK,kDAAuB,GAA/B,UAAgC,UAAkB,EAAE,GAAqB,EAAE,KAAc;QACvF,IAAM,IAAI,GAAG,UAAG,IAAI,CAAC,KAAK,CAAC,IAAI,cAAI,UAAU,CAAE,CAAC;QAChD,IAAI,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAChD,OAAO;SACR;QAED,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACf,OAAO,EAAE,+EAA+E;YACxF,GAAG,EAAE;gBACH,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;gBACtB,MAAM,EAAE,UAAU;gBAClB,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC;gBACb,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK;aAC1D;SACF,CAAC,CAAC;IACL,CAAC;IAEO,oCAAS,GAAjB,UAAqB,KAAqB;QACxC,OAAO,OAAO,CAAC,KAA+C,aAA/C,KAAK,uBAAL,KAAK,CAA4C,IAAI,CAAA,KAAK,UAAU,CAAC;IACtF,CAAC;IApPD;;;;;OAKG;IACY,kCAAiB,GAAG,IAAI,GAAG,EAAU,AAApB,CAAqB;IA+OvD,uBAAC;CAAA,AAtPD,IAsPC;AAtPY,4CAAgB;AAwP7B;IACE,yBAAoB,KAAe;QAAf,UAAK,GAAL,KAAK,CAAU;IAAG,CAAC;IAEjC,mCAAS,GAAf,UAAgB,iBAAyB,EAAE,UAAe;;;;;;wBAClD,OAAO,GAAyC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;wBACnE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;wBAC1C,IAAI,CAAC,MAAM,EAAE;4BACX,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;yBACjE;wBAEG,oBAAoB,GAAG,UAAU,CAAC;6BAClC,MAAM,CAAC,SAAS,EAAhB,wBAAgB;wBACK,qBAAM,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAA;;wBAAzD,oBAAoB,GAAG,SAAkC,CAAC;;4BAG5D,sBAAO,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,oBAAoB,sBAAA,EAAE,EAAC;;;;KAC1D;IAEK,qCAAW,GAAjB,UAAkB,UAAkB,EAAE,oBAAyB,EAAE,gBAAkC;;;;;;wBAC3F,OAAO,GAAyC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;wBACrE,iBAAiB,GAAG,UAAU,CAAC;wBAC/B,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;wBACjC,IAAI,CAAC,MAAM,EAAE;4BACX,KAAW,kBAAkB,IAAI,OAAO,EAAE;gCAClC,WAAW,GAAI,IAAI,CAAC,KAAK,CAAC,OAAe,CAAC,kBAAkB,CAAC,CAAC;gCACpE,IAAI,WAAW,IAAI,UAAU,IAAI,WAAW,CAAC,IAAI,EAAE;oCACjD,iBAAiB,GAAG,kBAAkB,CAAC;oCACvC,MAAM,GAAG,WAAW,CAAC;oCACrB,MAAM;iCACP;6BACF;yBACF;wBAED,IAAI,CAAC,MAAM,EAAE;4BACX,8FAA8F;4BAC9F,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;yBACjE;wBAEG,UAAU,GAAG,oBAAoB,CAAC;6BAClC,MAAM,CAAC,WAAW,EAAlB,wBAAkB;wBACP,qBAAM,MAAM,CAAC,WAAW,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,EAAA;;wBAA7E,UAAU,GAAG,SAAgE,CAAC;;4BAGhF,sBAAO,EAAE,iBAAiB,mBAAA,EAAE,UAAU,YAAA,EAAE,EAAC;;;;KAC1C;IACH,sBAAC;AAAD,CAAC,AA7CD,IA6CC;AA7CY,0CAAe"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LegacyCellHydration.test.d.ts","sourceRoot":"","sources":["../../test/LegacyCellHydration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
var __assign = (this && this.__assign) || function () {
|
|
18
|
+
__assign = Object.assign || function(t) {
|
|
19
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
+
s = arguments[i];
|
|
21
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
+
t[p] = s[p];
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
};
|
|
26
|
+
return __assign.apply(this, arguments);
|
|
27
|
+
};
|
|
28
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
29
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
30
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
31
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
32
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
33
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
34
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
38
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
39
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
40
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
41
|
+
function step(op) {
|
|
42
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
43
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
44
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
45
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
46
|
+
switch (op[0]) {
|
|
47
|
+
case 0: case 1: t = op; break;
|
|
48
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
49
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
50
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
51
|
+
default:
|
|
52
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
53
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
54
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
55
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
56
|
+
if (t[2]) _.ops.pop();
|
|
57
|
+
_.trys.pop(); continue;
|
|
58
|
+
}
|
|
59
|
+
op = body.call(thisArg, _);
|
|
60
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
61
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
+
var reflection_1 = require("@proteinjs/reflection");
|
|
66
|
+
var Db_1 = require("../src/Db");
|
|
67
|
+
var TableWatcherRunner_1 = require("../src/TableWatcherRunner");
|
|
68
|
+
var Table_1 = require("../src/Table");
|
|
69
|
+
var Record_1 = require("../src/Record");
|
|
70
|
+
var Columns_1 = require("../src/Columns");
|
|
71
|
+
var DocTable = /** @class */ (function (_super) {
|
|
72
|
+
__extends(DocTable, _super);
|
|
73
|
+
function DocTable() {
|
|
74
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
75
|
+
_this.name = 'legacy_cell_doc';
|
|
76
|
+
_this.columns = (0, Record_1.withRecordColumns)({
|
|
77
|
+
title: new Columns_1.StringColumn('title'),
|
|
78
|
+
tags: new Columns_1.ArrayColumn('tag_list'),
|
|
79
|
+
settings: new Columns_1.ObjectColumn('settings'),
|
|
80
|
+
after: new Columns_1.StringColumn('after'),
|
|
81
|
+
});
|
|
82
|
+
return _this;
|
|
83
|
+
}
|
|
84
|
+
return DocTable;
|
|
85
|
+
}(Table_1.Table));
|
|
86
|
+
var docTable = new DocTable();
|
|
87
|
+
var TestTransactionContextFactory = /** @class */ (function () {
|
|
88
|
+
function TestTransactionContextFactory() {
|
|
89
|
+
this.context = {};
|
|
90
|
+
}
|
|
91
|
+
TestTransactionContextFactory.prototype.getTransactionContext = function () {
|
|
92
|
+
return this.context;
|
|
93
|
+
};
|
|
94
|
+
TestTransactionContextFactory.prototype.runInContext = function (context, fn) {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
96
|
+
var previous;
|
|
97
|
+
return __generator(this, function (_a) {
|
|
98
|
+
switch (_a.label) {
|
|
99
|
+
case 0:
|
|
100
|
+
previous = this.context;
|
|
101
|
+
this.context = context;
|
|
102
|
+
_a.label = 1;
|
|
103
|
+
case 1:
|
|
104
|
+
_a.trys.push([1, , 3, 4]);
|
|
105
|
+
return [4 /*yield*/, fn()];
|
|
106
|
+
case 2: return [2 /*return*/, _a.sent()];
|
|
107
|
+
case 3:
|
|
108
|
+
this.context = previous;
|
|
109
|
+
return [7 /*endfinally*/];
|
|
110
|
+
case 4: return [2 /*return*/];
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
return TestTransactionContextFactory;
|
|
116
|
+
}());
|
|
117
|
+
/** A driver that answers every query with the rows it was handed — the stored cells as the database holds them. */
|
|
118
|
+
var RowsDriver = /** @class */ (function () {
|
|
119
|
+
function RowsDriver(rows) {
|
|
120
|
+
this.rows = rows;
|
|
121
|
+
}
|
|
122
|
+
RowsDriver.prototype.getDbName = function () {
|
|
123
|
+
return 'test';
|
|
124
|
+
};
|
|
125
|
+
RowsDriver.prototype.createDbIfNotExists = function () {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
127
|
+
return [2 /*return*/];
|
|
128
|
+
}); });
|
|
129
|
+
};
|
|
130
|
+
RowsDriver.prototype.createDb = function () {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
132
|
+
return [2 /*return*/];
|
|
133
|
+
}); });
|
|
134
|
+
};
|
|
135
|
+
RowsDriver.prototype.dropDb = function () {
|
|
136
|
+
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
137
|
+
return [2 /*return*/];
|
|
138
|
+
}); });
|
|
139
|
+
};
|
|
140
|
+
RowsDriver.prototype.getTableManager = function () {
|
|
141
|
+
throw new Error('not used by these tests');
|
|
142
|
+
};
|
|
143
|
+
RowsDriver.prototype.runQuery = function () {
|
|
144
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
145
|
+
return __generator(this, function (_a) {
|
|
146
|
+
return [2 /*return*/, this.rows];
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
RowsDriver.prototype.runDml = function () {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
152
|
+
return __generator(this, function (_a) {
|
|
153
|
+
return [2 /*return*/, 0];
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
RowsDriver.prototype.runTransaction = function (fn) {
|
|
158
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
159
|
+
return __generator(this, function (_a) {
|
|
160
|
+
switch (_a.label) {
|
|
161
|
+
case 0: return [4 /*yield*/, fn({ id: 'transaction' })];
|
|
162
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
RowsDriver.prototype.getOperationDeadlineMs = function () {
|
|
168
|
+
return 1000;
|
|
169
|
+
};
|
|
170
|
+
return RowsDriver;
|
|
171
|
+
}());
|
|
172
|
+
var dbOver = function (table, rows) {
|
|
173
|
+
return new Db_1.Db(new RowsDriver(rows), function () { return table; }, new TestTransactionContextFactory(), true);
|
|
174
|
+
};
|
|
175
|
+
var storedRow = function (id, cells) { return (__assign({ id: id, created: new Date(1700000000000), updated: new Date(1700000000000), title: "title ".concat(id), tag_list: '["a","b"]', settings: '{"theme":"dark"}', after: "after ".concat(id) }, cells)); };
|
|
176
|
+
/** The stored value no warning may ever carry — distinctive, so a leak is unmistakable. */
|
|
177
|
+
var LEGACY_WORD = 'legacyword7';
|
|
178
|
+
var objectCache = function () { return reflection_1.SourceRepository.get().objectCache; };
|
|
179
|
+
var originalWatchers;
|
|
180
|
+
beforeEach(function () {
|
|
181
|
+
var _a;
|
|
182
|
+
(_a = Record_1.RecordSerializer.legacyCellsWarned) === null || _a === void 0 ? void 0 : _a.clear();
|
|
183
|
+
});
|
|
184
|
+
// No reflection graph in a unit test: the watcher registry is empty by declaration.
|
|
185
|
+
beforeAll(function () {
|
|
186
|
+
originalWatchers = objectCache()['@proteinjs/db/TableWatcher'];
|
|
187
|
+
objectCache()['@proteinjs/db/TableWatcher'] = [];
|
|
188
|
+
TableWatcherRunner_1.TableWatcherRunner.tableWatcherMap = undefined;
|
|
189
|
+
});
|
|
190
|
+
afterAll(function () {
|
|
191
|
+
if (originalWatchers) {
|
|
192
|
+
objectCache()['@proteinjs/db/TableWatcher'] = originalWatchers;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
delete objectCache()['@proteinjs/db/TableWatcher'];
|
|
196
|
+
}
|
|
197
|
+
TableWatcherRunner_1.TableWatcherRunner.tableWatcherMap = undefined;
|
|
198
|
+
});
|
|
199
|
+
/** Every warning a serializer logs, as the logger received it. */
|
|
200
|
+
var warningsOf = function (serializer) {
|
|
201
|
+
var calls = [];
|
|
202
|
+
var logger = serializer.logger;
|
|
203
|
+
logger.warn = function () {
|
|
204
|
+
var args = [];
|
|
205
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
206
|
+
args[_i] = arguments[_i];
|
|
207
|
+
}
|
|
208
|
+
calls.push(args);
|
|
209
|
+
};
|
|
210
|
+
return calls;
|
|
211
|
+
};
|
|
212
|
+
describe('a stored cell a column cannot deserialize', function () {
|
|
213
|
+
it('a query over a row holding a legacy value resolves: the field is omitted, every other field lands', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
214
|
+
var rows, records;
|
|
215
|
+
return __generator(this, function (_a) {
|
|
216
|
+
switch (_a.label) {
|
|
217
|
+
case 0:
|
|
218
|
+
rows = [storedRow('r1', {}), storedRow('r2', { tag_list: LEGACY_WORD }), storedRow('r3', {})];
|
|
219
|
+
return [4 /*yield*/, dbOver(docTable, rows).query(docTable, {})];
|
|
220
|
+
case 1:
|
|
221
|
+
records = _a.sent();
|
|
222
|
+
expect(records.map(function (record) { return record.id; })).toEqual(['r1', 'r2', 'r3']);
|
|
223
|
+
expect(records[0].tags).toEqual(['a', 'b']);
|
|
224
|
+
expect(records[2].tags).toEqual(['a', 'b']);
|
|
225
|
+
expect(records[1]).not.toHaveProperty('tags');
|
|
226
|
+
expect(records[1]).toMatchObject({
|
|
227
|
+
id: 'r2',
|
|
228
|
+
title: 'title r2',
|
|
229
|
+
settings: { theme: 'dark' },
|
|
230
|
+
after: 'after r2',
|
|
231
|
+
});
|
|
232
|
+
return [2 /*return*/];
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}); });
|
|
236
|
+
it('a get of the row answers the record, not a rejection', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
237
|
+
var rows, record;
|
|
238
|
+
return __generator(this, function (_a) {
|
|
239
|
+
switch (_a.label) {
|
|
240
|
+
case 0:
|
|
241
|
+
rows = [storedRow('r2', { settings: LEGACY_WORD })];
|
|
242
|
+
return [4 /*yield*/, dbOver(docTable, rows).get(docTable, { id: 'r2' })];
|
|
243
|
+
case 1:
|
|
244
|
+
record = _a.sent();
|
|
245
|
+
expect(record).toMatchObject({ id: 'r2', title: 'title r2', tags: ['a', 'b'], after: 'after r2' });
|
|
246
|
+
expect(record).not.toHaveProperty('settings');
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}); });
|
|
251
|
+
it('warns once per table and column per process, naming the table, the column and the first row — never the value', function () {
|
|
252
|
+
var serializer = new Record_1.RecordSerializer(docTable);
|
|
253
|
+
var warnings = warningsOf(serializer);
|
|
254
|
+
var rows = [
|
|
255
|
+
storedRow('r1', { tag_list: LEGACY_WORD }),
|
|
256
|
+
storedRow('r2', { tag_list: LEGACY_WORD }),
|
|
257
|
+
storedRow('r3', { settings: LEGACY_WORD }),
|
|
258
|
+
];
|
|
259
|
+
var records = serializer.deserializeAll(rows);
|
|
260
|
+
expect(Array.isArray(records)).toBe(true);
|
|
261
|
+
expect(records.map(function (record) { return record.id; })).toEqual(['r1', 'r2', 'r3']);
|
|
262
|
+
expect(warnings).toHaveLength(2);
|
|
263
|
+
expect(warnings[0][0]).toMatchObject({
|
|
264
|
+
obj: { table: 'legacy_cell_doc', column: 'tag_list', id: 'r1', error: 'SyntaxError' },
|
|
265
|
+
});
|
|
266
|
+
expect(warnings[1][0]).toMatchObject({
|
|
267
|
+
obj: { table: 'legacy_cell_doc', column: 'settings', id: 'r3', error: 'SyntaxError' },
|
|
268
|
+
});
|
|
269
|
+
expect(JSON.stringify(warnings)).not.toContain(LEGACY_WORD);
|
|
270
|
+
});
|
|
271
|
+
it('a column whose deserialize answers with a rejecting promise is omitted the same way', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
272
|
+
var LaterColumn, LaterTable, laterTable, serializer, warnings, rows, records;
|
|
273
|
+
return __generator(this, function (_a) {
|
|
274
|
+
switch (_a.label) {
|
|
275
|
+
case 0:
|
|
276
|
+
LaterColumn = /** @class */ (function () {
|
|
277
|
+
function LaterColumn(name) {
|
|
278
|
+
this.name = name;
|
|
279
|
+
}
|
|
280
|
+
LaterColumn.prototype.deserialize = function (storedValue) {
|
|
281
|
+
return storedValue === -1 ? Promise.reject(new RangeError('unreadable')) : Promise.resolve(storedValue);
|
|
282
|
+
};
|
|
283
|
+
return LaterColumn;
|
|
284
|
+
}());
|
|
285
|
+
LaterTable = /** @class */ (function (_super) {
|
|
286
|
+
__extends(LaterTable, _super);
|
|
287
|
+
function LaterTable() {
|
|
288
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
289
|
+
_this.name = 'legacy_cell_later';
|
|
290
|
+
_this.columns = (0, Record_1.withRecordColumns)({
|
|
291
|
+
title: new Columns_1.StringColumn('title'),
|
|
292
|
+
later: new LaterColumn('later'),
|
|
293
|
+
after: new Columns_1.StringColumn('after'),
|
|
294
|
+
});
|
|
295
|
+
return _this;
|
|
296
|
+
}
|
|
297
|
+
return LaterTable;
|
|
298
|
+
}(Table_1.Table));
|
|
299
|
+
laterTable = new LaterTable();
|
|
300
|
+
serializer = new Record_1.RecordSerializer(laterTable);
|
|
301
|
+
warnings = warningsOf(serializer);
|
|
302
|
+
rows = [
|
|
303
|
+
{ id: 'l1', title: 'one', later: 1, after: 'x' },
|
|
304
|
+
{ id: 'l2', title: 'two', later: -1, after: 'y' },
|
|
305
|
+
];
|
|
306
|
+
return [4 /*yield*/, serializer.deserializeAll(rows)];
|
|
307
|
+
case 1:
|
|
308
|
+
records = _a.sent();
|
|
309
|
+
expect(records[0]).toMatchObject({ id: 'l1', title: 'one', later: 1, after: 'x' });
|
|
310
|
+
expect(records[1]).toMatchObject({ id: 'l2', title: 'two', after: 'y' });
|
|
311
|
+
expect(records[1]).not.toHaveProperty('later');
|
|
312
|
+
expect(warnings).toHaveLength(1);
|
|
313
|
+
expect(warnings[0][0]).toMatchObject({
|
|
314
|
+
obj: { table: 'legacy_cell_later', column: 'later', id: 'l2', error: 'RangeError' },
|
|
315
|
+
});
|
|
316
|
+
return [2 /*return*/];
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
}); });
|
|
320
|
+
});
|
|
321
|
+
//# sourceMappingURL=LegacyCellHydration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LegacyCellHydration.test.js","sourceRoot":"","sources":["../../test/LegacyCellHydration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnTypesTests.d.ts","sourceRoot":"","sources":["../../../test/reusable/ColumnTypesTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,QAAQ,EAAU,KAAK,EAAE,gCAAgC,
|
|
1
|
+
{"version":3,"file":"ColumnTypesTests.d.ts","sourceRoot":"","sources":["../../../test/reusable/ColumnTypesTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,QAAQ,EAAU,KAAK,EAAE,gCAAgC,EAAuB,MAAM,eAAe,CAAC;AAMnH,eAAO,MAAM,eAAe,WAClB,QAAQ,6BACW,gCAAgC,qBACxC,MAAM,GAAG,CAAC,KAAK,QAAQ,IAAI,CAAC,eAsHhD,CAAC"}
|
|
@@ -38,6 +38,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.columnTypeTests = void 0;
|
|
40
40
|
var db_1 = require("@proteinjs/db");
|
|
41
|
+
var db_query_1 = require("@proteinjs/db-query");
|
|
42
|
+
var StatementConfigFactory_1 = require("../../src/StatementConfigFactory");
|
|
41
43
|
var DbTestEnvironment_1 = require("../util/DbTestEnvironment");
|
|
42
44
|
var columnTypesTestTables_1 = require("../util/tables/columnTypesTestTables");
|
|
43
45
|
var columnTypeTests = function (driver, transactionContextFactory, dropTable) {
|
|
@@ -137,6 +139,59 @@ var columnTypeTests = function (driver, transactionContextFactory, dropTable) {
|
|
|
137
139
|
}
|
|
138
140
|
});
|
|
139
141
|
}); });
|
|
142
|
+
test('A legacy cell the column cannot deserialize never takes the row with it', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
143
|
+
var testTable, legacy, intact, statementConfigFactory, legacyRow, fetched, all, other;
|
|
144
|
+
return __generator(this, function (_a) {
|
|
145
|
+
switch (_a.label) {
|
|
146
|
+
case 0:
|
|
147
|
+
testTable = columnTypesTestTables_1.columnTypesTestTables.Test;
|
|
148
|
+
return [4 /*yield*/, db.insert(testTable, {
|
|
149
|
+
stringColumn: 'legacy',
|
|
150
|
+
objectColumn: { theme: 'dark' },
|
|
151
|
+
arrayColumn: ['a', 'b'],
|
|
152
|
+
})];
|
|
153
|
+
case 1:
|
|
154
|
+
legacy = _a.sent();
|
|
155
|
+
return [4 /*yield*/, db.insert(testTable, {
|
|
156
|
+
stringColumn: 'intact',
|
|
157
|
+
objectColumn: { theme: 'light' },
|
|
158
|
+
arrayColumn: ['c'],
|
|
159
|
+
})];
|
|
160
|
+
case 2:
|
|
161
|
+
intact = _a.sent();
|
|
162
|
+
statementConfigFactory = new StatementConfigFactory_1.StatementConfigFactory(driver.getDbName());
|
|
163
|
+
legacyRow = new db_1.QueryBuilderFactory()
|
|
164
|
+
.getQueryBuilder(testTable)
|
|
165
|
+
.condition({ field: 'id', operator: '=', value: legacy.id });
|
|
166
|
+
return [4 /*yield*/, driver.runDml(function (config) {
|
|
167
|
+
return new db_query_1.StatementFactory().update(testTable.name, { object_column: 'legacyword', array_column: 'legacyword' }, legacyRow, statementConfigFactory.getStatementConfig(config));
|
|
168
|
+
})];
|
|
169
|
+
case 3:
|
|
170
|
+
_a.sent();
|
|
171
|
+
return [4 /*yield*/, db.get(testTable, { id: legacy.id })];
|
|
172
|
+
case 4:
|
|
173
|
+
fetched = _a.sent();
|
|
174
|
+
expect(fetched).toMatchObject({ id: legacy.id, stringColumn: 'legacy' });
|
|
175
|
+
expect(fetched).not.toHaveProperty('objectColumn');
|
|
176
|
+
expect(fetched).not.toHaveProperty('arrayColumn');
|
|
177
|
+
return [4 /*yield*/, db.query(testTable, {})];
|
|
178
|
+
case 5:
|
|
179
|
+
all = _a.sent();
|
|
180
|
+
expect(all.map(function (record) { return record.id; }).sort()).toEqual([legacy.id, intact.id].sort());
|
|
181
|
+
other = all.find(function (record) { return record.id === intact.id; });
|
|
182
|
+
expect(other).toMatchObject({ stringColumn: 'intact', objectColumn: { theme: 'light' }, arrayColumn: ['c'] });
|
|
183
|
+
// Clean up
|
|
184
|
+
return [4 /*yield*/, db.delete(testTable, { id: legacy.id })];
|
|
185
|
+
case 6:
|
|
186
|
+
// Clean up
|
|
187
|
+
_a.sent();
|
|
188
|
+
return [4 /*yield*/, db.delete(testTable, { id: intact.id })];
|
|
189
|
+
case 7:
|
|
190
|
+
_a.sent();
|
|
191
|
+
return [2 /*return*/];
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}); });
|
|
140
195
|
};
|
|
141
196
|
};
|
|
142
197
|
exports.columnTypeTests = columnTypeTests;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnTypesTests.js","sourceRoot":"","sources":["../../../test/reusable/ColumnTypesTests.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"ColumnTypesTests.js","sourceRoot":"","sources":["../../../test/reusable/ColumnTypesTests.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oCAAmH;AACnH,gDAAuD;AACvD,2EAA0E;AAC1E,+DAA8D;AAC9D,8EAAyF;AAElF,IAAM,eAAe,GAAG,UAC7B,MAAgB,EAChB,yBAA2D,EAC3D,SAA+C;IAE/C,OAAO;QACL,IAAM,EAAE,GAAG,IAAI,OAAE,CAAC,MAAM,EAAE,SAAS,EAAE,yBAAyB,CAAC,CAAC;QAChE,IAAM,OAAO,GAAG,IAAI,qCAAiB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAEzD,SAAS,CAAC;;wBAAY,qBAAM,OAAO,CAAC,SAAS,EAAE,EAAA;wBAAzB,sBAAA,SAAyB,EAAA;;iBAAA,EAAE,MAAM,CAAC,CAAC;QACzD,QAAQ,CAAC;;wBAAY,qBAAM,OAAO,CAAC,QAAQ,EAAE,EAAA;wBAAxB,sBAAA,SAAwB,EAAA;;iBAAA,EAAE,MAAM,CAAC,CAAC;QAEvD,IAAI,CAAC,oCAAoC,EAAE;;;;;wBACnC,UAAU,GAAmC;4BACjD,aAAa,EAAE,IAAI;4BACnB,YAAY,EAAE,IAAI;4BAClB,WAAW,EAAE,IAAI;4BACjB,aAAa,EAAE,IAAI;4BACnB,aAAa,EAAE,IAAI;4BACnB,UAAU,EAAE,IAAI;4BAChB,cAAc,EAAE,IAAI;4BACpB,YAAY,EAAE,IAAI;4BAClB,UAAU,EAAE,IAAI;4BAChB,cAAc,EAAE,IAAI;4BACpB,YAAY,EAAE,IAAI;4BAClB,WAAW,EAAE,IAAI;4BACjB,oBAAoB,EAAE,IAAI;4BAC1B,eAAe,EAAE,IAAI;yBACtB,CAAC;wBAEI,SAAS,GAAsB,6CAAqB,CAAC,IAAI,CAAC;wBACzC,qBAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,EAAA;;wBAAvD,cAAc,GAAG,SAAsC;wBACvC,qBAAM,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC,EAAA;;wBAAlE,aAAa,GAAG,SAAkD;wBAExE,MAAM,CAAC,aAAa,CAAC,CAAC,UAAU,EAAE,CAAC;wBACnC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC/C,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC9C,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC7C,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC/C,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC/C,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC5C,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAChD,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC9C,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC5C,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAChD,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC9C,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;wBAC7C,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE,CAAC;wBACjD,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;wBAEtE,WAAW;wBACX,qBAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC,EAAA;;wBADpD,WAAW;wBACX,SAAoD,CAAC;;;;aACtD,CAAC,CAAC;QAEH,IAAI,CAAC,yCAAyC,EAAE;;;;;wBACxC,UAAU,GAAmC;4BACjD,aAAa,EAAE,SAAS;4BACxB,YAAY,EAAE,SAAS;4BACvB,WAAW,EAAE,SAAS;4BACtB,aAAa,EAAE,SAAS;4BACxB,aAAa,EAAE,SAAS;4BACxB,UAAU,EAAE,SAAS;4BACrB,cAAc,EAAE,SAAS;4BACzB,YAAY,EAAE,SAAS;4BACvB,UAAU,EAAE,SAAS;4BACrB,cAAc,EAAE,SAAS;4BACzB,YAAY,EAAE,SAAS;4BACvB,WAAW,EAAE,SAAS;4BACtB,oBAAoB,EAAE,SAAS;4BAC/B,eAAe,EAAE,SAAS;yBAC3B,CAAC;wBAEI,SAAS,GAAsB,6CAAqB,CAAC,IAAI,CAAC;wBAEhE,qBAAM,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAA;;wBAAhE,SAAgE,CAAC;;;;aAClE,CAAC,CAAC;QAEH,IAAI,CAAC,yEAAyE,EAAE;;;;;wBAKxE,SAAS,GAAsB,6CAAqB,CAAC,IAAI,CAAC;wBACjD,qBAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;gCACxC,YAAY,EAAE,QAAQ;gCACtB,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;gCAC/B,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;6BACxB,CAAC,EAAA;;wBAJI,MAAM,GAAG,SAIb;wBACa,qBAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;gCACxC,YAAY,EAAE,QAAQ;gCACtB,YAAY,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;gCAChC,WAAW,EAAE,CAAC,GAAG,CAAC;6BACnB,CAAC,EAAA;;wBAJI,MAAM,GAAG,SAIb;wBACI,sBAAsB,GAAG,IAAI,+CAAsB,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;wBACxE,SAAS,GAAG,IAAI,wBAAmB,EAAE;6BACxC,eAAe,CAAC,SAAS,CAAC;6BAC1B,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC/D,qBAAM,MAAM,CAAC,MAAM,CAAC,UAAC,MAAM;gCACzB,OAAA,IAAI,2BAAgB,EAAc,CAAC,MAAM,CACvC,SAAS,CAAC,IAAI,EACd,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAyB,EAClF,SAAS,EACT,sBAAsB,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAClD;4BALD,CAKC,CACF,EAAA;;wBAPD,SAOC,CAAC;wBAEc,qBAAM,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAA;;wBAApD,OAAO,GAAG,SAA0C;wBAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;wBACzE,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;wBACnD,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;wBAEtC,qBAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC,EAAA;;wBAAnC,GAAG,GAAG,SAA6B;wBACzC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,UAAC,MAAM,IAAK,OAAA,MAAM,CAAC,EAAE,EAAT,CAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;wBAC/E,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,UAAC,MAAM,IAAK,OAAA,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAvB,CAAuB,CAAC,CAAC;wBAC5D,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBAE9G,WAAW;wBACX,qBAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAA;;wBAD7C,WAAW;wBACX,SAA6C,CAAC;wBAC9C,qBAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAA;;wBAA7C,SAA6C,CAAC;;;;aAC/C,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC,CAAC;AAzHW,QAAA,eAAe,mBAyH1B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proteinjs/db",
|
|
3
|
-
"version": "1.54.
|
|
3
|
+
"version": "1.54.3",
|
|
4
4
|
"main": "./dist/generated/index.js",
|
|
5
5
|
"types": "./dist/generated/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"ts-jest": "29.1.1",
|
|
67
67
|
"typescript": "5.2.2"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "351cc984b09d074bf0306a82750efd99ec00654a"
|
|
70
70
|
}
|
package/src/Record.ts
CHANGED
|
@@ -68,6 +68,13 @@ interface HydrationPlan {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export class RecordSerializer<T extends Record> {
|
|
71
|
+
/**
|
|
72
|
+
* The table-and-column pairs whose stored cells have failed to deserialize in this process
|
|
73
|
+
* (`omitCellNotDeserialized`): each is warned once. A legacy cell is read again by every query
|
|
74
|
+
* that touches its row — a background sweep reads some rows every few seconds — and the warning
|
|
75
|
+
* is a schema fact, not a per-read event.
|
|
76
|
+
*/
|
|
77
|
+
private static legacyCellsWarned = new Set<string>();
|
|
71
78
|
private logger = new Logger({ name: this.constructor.name });
|
|
72
79
|
private table: Table<T>;
|
|
73
80
|
private encryptionContext?: RecordEncryptionContext;
|
|
@@ -177,13 +184,26 @@ export class RecordSerializer<T extends Record> {
|
|
|
177
184
|
continue;
|
|
178
185
|
}
|
|
179
186
|
|
|
180
|
-
|
|
187
|
+
let fieldValue: unknown;
|
|
188
|
+
try {
|
|
189
|
+
fieldValue = column.deserialize(storedValue, prepared);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
this.omitCellNotDeserialized(columnName, prepared, error);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
181
195
|
if (this.isPromise(fieldValue)) {
|
|
182
196
|
record[propertyName] = undefined; // seats the property in column order; the value lands when it settles
|
|
183
197
|
(settling ??= []).push(
|
|
184
|
-
fieldValue.then(
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
fieldValue.then(
|
|
199
|
+
(value) => {
|
|
200
|
+
record[propertyName] = value;
|
|
201
|
+
},
|
|
202
|
+
(error) => {
|
|
203
|
+
delete record[propertyName];
|
|
204
|
+
this.omitCellNotDeserialized(columnName, prepared, error);
|
|
205
|
+
}
|
|
206
|
+
)
|
|
187
207
|
);
|
|
188
208
|
continue;
|
|
189
209
|
}
|
|
@@ -215,13 +235,19 @@ export class RecordSerializer<T extends Record> {
|
|
|
215
235
|
): void {
|
|
216
236
|
let value: unknown;
|
|
217
237
|
let read = false;
|
|
238
|
+
const omit = (error: unknown) => this.omitCellNotDeserialized(column.name, record, error);
|
|
218
239
|
Object.defineProperty(record, propertyName, {
|
|
219
240
|
enumerable: true,
|
|
220
241
|
configurable: true,
|
|
221
242
|
get() {
|
|
222
243
|
if (!read) {
|
|
223
|
-
value = column.deserialize!(storedValue, undefined);
|
|
224
244
|
read = true;
|
|
245
|
+
try {
|
|
246
|
+
value = column.deserialize!(storedValue, undefined);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
delete record[propertyName];
|
|
249
|
+
omit(error);
|
|
250
|
+
}
|
|
225
251
|
}
|
|
226
252
|
|
|
227
253
|
return value;
|
|
@@ -258,6 +284,32 @@ export class RecordSerializer<T extends Record> {
|
|
|
258
284
|
return this.plan;
|
|
259
285
|
}
|
|
260
286
|
|
|
287
|
+
/**
|
|
288
|
+
* A stored cell the column cannot deserialize — a value written past the serializer, the way a
|
|
289
|
+
* hand-run statement or an older writer leaves it — never takes the row, the result set or the
|
|
290
|
+
* process with it. The field is omitted from the record (the law the per-row hydration held:
|
|
291
|
+
* `try { deserialize } catch { omit }`; what a reader of an optional field already takes as
|
|
292
|
+
* absent), and one warning per table and column per process names the table, the column and the
|
|
293
|
+
* first row seen — never the stored value, which the parser's own message quotes.
|
|
294
|
+
*/
|
|
295
|
+
private omitCellNotDeserialized(columnName: string, row: SerializedRecord, error: unknown): void {
|
|
296
|
+
const cell = `${this.table.name}.${columnName}`;
|
|
297
|
+
if (RecordSerializer.legacyCellsWarned.has(cell)) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
RecordSerializer.legacyCellsWarned.add(cell);
|
|
302
|
+
this.logger.warn({
|
|
303
|
+
message: `A stored cell could not be deserialized; the field is omitted from the record`,
|
|
304
|
+
obj: {
|
|
305
|
+
table: this.table.name,
|
|
306
|
+
column: columnName,
|
|
307
|
+
id: row['id'],
|
|
308
|
+
error: error instanceof Error ? error.name : typeof error,
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
261
313
|
private isPromise<V>(value: V | Promise<V>): value is Promise<V> {
|
|
262
314
|
return typeof (value as { then?: unknown } | null | undefined)?.then === 'function';
|
|
263
315
|
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { SourceRepository } from '@proteinjs/reflection';
|
|
2
|
+
import { Db, DbDriver } from '../src/Db';
|
|
3
|
+
import { TableWatcherRunner } from '../src/TableWatcherRunner';
|
|
4
|
+
import { Column, Table } from '../src/Table';
|
|
5
|
+
import { Record, RecordSerializer, SerializedRecord, withRecordColumns } from '../src/Record';
|
|
6
|
+
import { ArrayColumn, ObjectColumn, StringColumn } from '../src/Columns';
|
|
7
|
+
import { DefaultTransactionContextFactory, TransactionContextData } from '../src/transaction/TransactionContextFactory';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A stored cell a column cannot deserialize — a legacy value written outside the serializer, say a
|
|
11
|
+
* bare word in a column that stores JSON — never takes the row, the result set or the process with
|
|
12
|
+
* it. The law the per-row hydration held (`try { deserialize } catch { omit }`) and the one-pass
|
|
13
|
+
* hydration dropped: the field is OMITTED from the record, every other field lands, the query's
|
|
14
|
+
* promise resolves, and ONE warning per table and column per process names the table, the column
|
|
15
|
+
* and the first row seen — never the stored value (the parser's own message quotes it).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface Doc extends Record {
|
|
19
|
+
title: string;
|
|
20
|
+
tags: string[];
|
|
21
|
+
settings: { theme: string };
|
|
22
|
+
after: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class DocTable extends Table<Doc> {
|
|
26
|
+
public name = 'legacy_cell_doc';
|
|
27
|
+
public columns = withRecordColumns<Doc>({
|
|
28
|
+
title: new StringColumn('title'),
|
|
29
|
+
tags: new ArrayColumn<string>('tag_list'),
|
|
30
|
+
settings: new ObjectColumn<{ theme: string }>('settings'),
|
|
31
|
+
after: new StringColumn('after'),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const docTable = new DocTable() as Table<Doc>;
|
|
36
|
+
|
|
37
|
+
class TestTransactionContextFactory implements DefaultTransactionContextFactory {
|
|
38
|
+
private context: TransactionContextData = {};
|
|
39
|
+
|
|
40
|
+
getTransactionContext(): TransactionContextData {
|
|
41
|
+
return this.context;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async runInContext<T>(context: TransactionContextData, fn: () => Promise<T>): Promise<T> {
|
|
45
|
+
const previous = this.context;
|
|
46
|
+
this.context = context;
|
|
47
|
+
try {
|
|
48
|
+
return await fn();
|
|
49
|
+
} finally {
|
|
50
|
+
this.context = previous;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** A driver that answers every query with the rows it was handed — the stored cells as the database holds them. */
|
|
56
|
+
class RowsDriver implements DbDriver {
|
|
57
|
+
constructor(private readonly rows: SerializedRecord[]) {}
|
|
58
|
+
|
|
59
|
+
getDbName(): string {
|
|
60
|
+
return 'test';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async createDbIfNotExists(): Promise<void> {}
|
|
64
|
+
|
|
65
|
+
async createDb(): Promise<void> {}
|
|
66
|
+
|
|
67
|
+
async dropDb(): Promise<void> {}
|
|
68
|
+
|
|
69
|
+
getTableManager(): never {
|
|
70
|
+
throw new Error('not used by these tests');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async runQuery(): Promise<SerializedRecord[]> {
|
|
74
|
+
return this.rows;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async runDml(): Promise<number> {
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async runTransaction<T>(fn: (transaction: unknown) => Promise<T>): Promise<T> {
|
|
82
|
+
return await fn({ id: 'transaction' });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
getOperationDeadlineMs(): number {
|
|
86
|
+
return 1000;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const dbOver = (table: Table<any>, rows: SerializedRecord[]) =>
|
|
91
|
+
new Db(new RowsDriver(rows), () => table, new TestTransactionContextFactory(), true);
|
|
92
|
+
|
|
93
|
+
const storedRow = (id: string, cells: Partial<SerializedRecord>): SerializedRecord => ({
|
|
94
|
+
id,
|
|
95
|
+
created: new Date(1_700_000_000_000),
|
|
96
|
+
updated: new Date(1_700_000_000_000),
|
|
97
|
+
title: `title ${id}`,
|
|
98
|
+
tag_list: '["a","b"]',
|
|
99
|
+
settings: '{"theme":"dark"}',
|
|
100
|
+
after: `after ${id}`,
|
|
101
|
+
...cells,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
/** The stored value no warning may ever carry — distinctive, so a leak is unmistakable. */
|
|
105
|
+
const LEGACY_WORD = 'legacyword7';
|
|
106
|
+
|
|
107
|
+
type SourceRepositoryInternals = { objectCache: { [qualifiedName: string]: unknown[] } };
|
|
108
|
+
type TableWatcherRunnerStatics = { tableWatcherMap?: unknown };
|
|
109
|
+
type SerializerInternals = { logger: { warn: (...args: unknown[]) => void; debug: (...args: unknown[]) => void } };
|
|
110
|
+
/** The process-wide once-per-table-and-column registry behind the warning (reset per test). */
|
|
111
|
+
type SerializerStatics = { legacyCellsWarned: Set<string> };
|
|
112
|
+
const objectCache = () => (SourceRepository.get() as unknown as SourceRepositoryInternals).objectCache;
|
|
113
|
+
let originalWatchers: unknown[] | undefined;
|
|
114
|
+
|
|
115
|
+
beforeEach(() => {
|
|
116
|
+
(RecordSerializer as unknown as SerializerStatics).legacyCellsWarned?.clear();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// No reflection graph in a unit test: the watcher registry is empty by declaration.
|
|
120
|
+
beforeAll(() => {
|
|
121
|
+
originalWatchers = objectCache()['@proteinjs/db/TableWatcher'];
|
|
122
|
+
objectCache()['@proteinjs/db/TableWatcher'] = [];
|
|
123
|
+
(TableWatcherRunner as unknown as TableWatcherRunnerStatics).tableWatcherMap = undefined;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
afterAll(() => {
|
|
127
|
+
if (originalWatchers) {
|
|
128
|
+
objectCache()['@proteinjs/db/TableWatcher'] = originalWatchers;
|
|
129
|
+
} else {
|
|
130
|
+
delete objectCache()['@proteinjs/db/TableWatcher'];
|
|
131
|
+
}
|
|
132
|
+
(TableWatcherRunner as unknown as TableWatcherRunnerStatics).tableWatcherMap = undefined;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
/** Every warning a serializer logs, as the logger received it. */
|
|
136
|
+
const warningsOf = (serializer: RecordSerializer<any>): unknown[][] => {
|
|
137
|
+
const calls: unknown[][] = [];
|
|
138
|
+
const logger = (serializer as unknown as SerializerInternals).logger;
|
|
139
|
+
logger.warn = (...args: unknown[]) => {
|
|
140
|
+
calls.push(args);
|
|
141
|
+
};
|
|
142
|
+
return calls;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
describe('a stored cell a column cannot deserialize', () => {
|
|
146
|
+
it('a query over a row holding a legacy value resolves: the field is omitted, every other field lands', async () => {
|
|
147
|
+
const rows = [storedRow('r1', {}), storedRow('r2', { tag_list: LEGACY_WORD }), storedRow('r3', {})];
|
|
148
|
+
|
|
149
|
+
const records = await dbOver(docTable, rows).query(docTable, {});
|
|
150
|
+
|
|
151
|
+
expect(records.map((record) => record.id)).toEqual(['r1', 'r2', 'r3']);
|
|
152
|
+
expect(records[0].tags).toEqual(['a', 'b']);
|
|
153
|
+
expect(records[2].tags).toEqual(['a', 'b']);
|
|
154
|
+
expect(records[1]).not.toHaveProperty('tags');
|
|
155
|
+
expect(records[1]).toMatchObject({
|
|
156
|
+
id: 'r2',
|
|
157
|
+
title: 'title r2',
|
|
158
|
+
settings: { theme: 'dark' },
|
|
159
|
+
after: 'after r2',
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('a get of the row answers the record, not a rejection', async () => {
|
|
164
|
+
const rows = [storedRow('r2', { settings: LEGACY_WORD })];
|
|
165
|
+
|
|
166
|
+
const record = await dbOver(docTable, rows).get(docTable, { id: 'r2' });
|
|
167
|
+
|
|
168
|
+
expect(record).toMatchObject({ id: 'r2', title: 'title r2', tags: ['a', 'b'], after: 'after r2' });
|
|
169
|
+
expect(record).not.toHaveProperty('settings');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('warns once per table and column per process, naming the table, the column and the first row — never the value', () => {
|
|
173
|
+
const serializer = new RecordSerializer<Doc>(docTable);
|
|
174
|
+
const warnings = warningsOf(serializer);
|
|
175
|
+
const rows = [
|
|
176
|
+
storedRow('r1', { tag_list: LEGACY_WORD }),
|
|
177
|
+
storedRow('r2', { tag_list: LEGACY_WORD }),
|
|
178
|
+
storedRow('r3', { settings: LEGACY_WORD }),
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
const records = serializer.deserializeAll(rows) as Doc[];
|
|
182
|
+
|
|
183
|
+
expect(Array.isArray(records)).toBe(true);
|
|
184
|
+
expect(records.map((record) => record.id)).toEqual(['r1', 'r2', 'r3']);
|
|
185
|
+
expect(warnings).toHaveLength(2);
|
|
186
|
+
expect(warnings[0][0]).toMatchObject({
|
|
187
|
+
obj: { table: 'legacy_cell_doc', column: 'tag_list', id: 'r1', error: 'SyntaxError' },
|
|
188
|
+
});
|
|
189
|
+
expect(warnings[1][0]).toMatchObject({
|
|
190
|
+
obj: { table: 'legacy_cell_doc', column: 'settings', id: 'r3', error: 'SyntaxError' },
|
|
191
|
+
});
|
|
192
|
+
expect(JSON.stringify(warnings)).not.toContain(LEGACY_WORD);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('a column whose deserialize answers with a rejecting promise is omitted the same way', async () => {
|
|
196
|
+
class LaterColumn implements Column<number, number> {
|
|
197
|
+
constructor(public name: string) {}
|
|
198
|
+
|
|
199
|
+
deserialize(storedValue: number | null): Promise<number | null> {
|
|
200
|
+
return storedValue === -1 ? Promise.reject(new RangeError('unreadable')) : Promise.resolve(storedValue);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
interface Later extends Record {
|
|
204
|
+
title: string;
|
|
205
|
+
later: number;
|
|
206
|
+
after: string;
|
|
207
|
+
}
|
|
208
|
+
class LaterTable extends Table<Later> {
|
|
209
|
+
public name = 'legacy_cell_later';
|
|
210
|
+
public columns = withRecordColumns<Later>({
|
|
211
|
+
title: new StringColumn('title'),
|
|
212
|
+
later: new LaterColumn('later'),
|
|
213
|
+
after: new StringColumn('after'),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const laterTable = new LaterTable() as Table<Later>;
|
|
217
|
+
const serializer = new RecordSerializer<Later>(laterTable);
|
|
218
|
+
const warnings = warningsOf(serializer);
|
|
219
|
+
const rows: SerializedRecord[] = [
|
|
220
|
+
{ id: 'l1', title: 'one', later: 1, after: 'x' },
|
|
221
|
+
{ id: 'l2', title: 'two', later: -1, after: 'y' },
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
const records = await serializer.deserializeAll(rows);
|
|
225
|
+
|
|
226
|
+
expect(records[0]).toMatchObject({ id: 'l1', title: 'one', later: 1, after: 'x' });
|
|
227
|
+
expect(records[1]).toMatchObject({ id: 'l2', title: 'two', after: 'y' });
|
|
228
|
+
expect(records[1]).not.toHaveProperty('later');
|
|
229
|
+
expect(warnings).toHaveLength(1);
|
|
230
|
+
expect(warnings[0][0]).toMatchObject({
|
|
231
|
+
obj: { table: 'legacy_cell_later', column: 'later', id: 'l2', error: 'RangeError' },
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { Db, DbDriver, Record, Table, DefaultTransactionContextFactory } from '@proteinjs/db';
|
|
1
|
+
import { Db, DbDriver, Record, Table, DefaultTransactionContextFactory, QueryBuilderFactory } from '@proteinjs/db';
|
|
2
|
+
import { StatementFactory } from '@proteinjs/db-query';
|
|
3
|
+
import { StatementConfigFactory } from '../../src/StatementConfigFactory';
|
|
2
4
|
import { DbTestEnvironment } from '../util/DbTestEnvironment';
|
|
3
5
|
import { columnTypesTestTables, TestRecord } from '../util/tables/columnTypesTestTables';
|
|
4
6
|
|
|
@@ -78,5 +80,49 @@ export const columnTypeTests = (
|
|
|
78
80
|
|
|
79
81
|
await expect(db.insert(testTable, testRecord)).rejects.toThrow();
|
|
80
82
|
});
|
|
83
|
+
|
|
84
|
+
test('A legacy cell the column cannot deserialize never takes the row with it', async () => {
|
|
85
|
+
// A value written past the serializer — a bare word in a column that stores JSON — the way
|
|
86
|
+
// a hand-run statement or an older writer leaves it: the update statement the db layer
|
|
87
|
+
// itself emits, handed the cells as stored text. The row still serves: that field is
|
|
88
|
+
// omitted, every other field lands, and a query over the table resolves.
|
|
89
|
+
const testTable: Table<TestRecord> = columnTypesTestTables.Test;
|
|
90
|
+
const legacy = await db.insert(testTable, {
|
|
91
|
+
stringColumn: 'legacy',
|
|
92
|
+
objectColumn: { theme: 'dark' },
|
|
93
|
+
arrayColumn: ['a', 'b'],
|
|
94
|
+
});
|
|
95
|
+
const intact = await db.insert(testTable, {
|
|
96
|
+
stringColumn: 'intact',
|
|
97
|
+
objectColumn: { theme: 'light' },
|
|
98
|
+
arrayColumn: ['c'],
|
|
99
|
+
});
|
|
100
|
+
const statementConfigFactory = new StatementConfigFactory(driver.getDbName());
|
|
101
|
+
const legacyRow = new QueryBuilderFactory()
|
|
102
|
+
.getQueryBuilder(testTable)
|
|
103
|
+
.condition({ field: 'id', operator: '=', value: legacy.id });
|
|
104
|
+
await driver.runDml((config) =>
|
|
105
|
+
new StatementFactory<TestRecord>().update(
|
|
106
|
+
testTable.name,
|
|
107
|
+
{ object_column: 'legacyword', array_column: 'legacyword' } as Partial<TestRecord>,
|
|
108
|
+
legacyRow,
|
|
109
|
+
statementConfigFactory.getStatementConfig(config)
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const fetched = await db.get(testTable, { id: legacy.id });
|
|
114
|
+
expect(fetched).toMatchObject({ id: legacy.id, stringColumn: 'legacy' });
|
|
115
|
+
expect(fetched).not.toHaveProperty('objectColumn');
|
|
116
|
+
expect(fetched).not.toHaveProperty('arrayColumn');
|
|
117
|
+
|
|
118
|
+
const all = await db.query(testTable, {});
|
|
119
|
+
expect(all.map((record) => record.id).sort()).toEqual([legacy.id, intact.id].sort());
|
|
120
|
+
const other = all.find((record) => record.id === intact.id);
|
|
121
|
+
expect(other).toMatchObject({ stringColumn: 'intact', objectColumn: { theme: 'light' }, arrayColumn: ['c'] });
|
|
122
|
+
|
|
123
|
+
// Clean up
|
|
124
|
+
await db.delete(testTable, { id: legacy.id });
|
|
125
|
+
await db.delete(testTable, { id: intact.id });
|
|
126
|
+
});
|
|
81
127
|
};
|
|
82
128
|
};
|