@antelopejs/interface-database-decorators 0.2.1 → 0.3.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/README.md +1 -0
- package/dist/common.js +7 -5
- package/dist/common.js.map +1 -1
- package/dist/model.js +21 -11
- package/dist/model.js.map +1 -1
- package/dist/modifiers/common.d.ts +49 -29
- package/dist/modifiers/common.js +57 -66
- package/dist/modifiers/common.js.map +1 -1
- package/dist/modifiers/encryption.js +32 -1
- package/dist/modifiers/encryption.js.map +1 -1
- package/dist/modifiers/hash.d.ts +29 -2
- package/dist/modifiers/hash.js +66 -7
- package/dist/modifiers/hash.js.map +1 -1
- package/dist/modifiers/internal/classes.d.ts +45 -0
- package/dist/modifiers/internal/classes.js +131 -0
- package/dist/modifiers/internal/classes.js.map +1 -0
- package/dist/modifiers/internal/records.d.ts +6 -0
- package/dist/modifiers/internal/records.js +12 -1
- package/dist/modifiers/internal/records.js.map +1 -1
- package/dist/modifiers/localization.d.ts +30 -4
- package/dist/modifiers/localization.js +8 -20
- package/dist/modifiers/localization.js.map +1 -1
- package/dist/tests/hash_upgrade.test.js +25 -2
- package/dist/tests/hash_upgrade.test.js.map +1 -1
- package/dist/tests/localized_query_keys.test.d.ts +1 -0
- package/dist/tests/localized_query_keys.test.js +63 -0
- package/dist/tests/localized_query_keys.test.js.map +1 -0
- package/dist/tests/metadata_inheritance.test.js +63 -0
- package/dist/tests/metadata_inheritance.test.js.map +1 -1
- package/dist/tests/modifiers/common.test.js +6 -0
- package/dist/tests/modifiers/common.test.js.map +1 -1
- package/dist/tests/modifiers/encryption_date_marker.test.js +22 -0
- package/dist/tests/modifiers/encryption_date_marker.test.js.map +1 -1
- package/dist/tests/modifiers/hash.test.js +10 -4
- package/dist/tests/modifiers/hash.test.js.map +1 -1
- package/dist/tests/modifiers/hash_async_set.test.d.ts +1 -0
- package/dist/tests/modifiers/hash_async_set.test.js +135 -0
- package/dist/tests/modifiers/hash_async_set.test.js.map +1 -0
- package/dist/tests/modifiers/localization.test.js +134 -0
- package/dist/tests/modifiers/localization.test.js.map +1 -1
- package/dist/tests/modifiers/symbol_fields.test.d.ts +1 -0
- package/dist/tests/modifiers/symbol_fields.test.js +62 -0
- package/dist/tests/modifiers/symbol_fields.test.js.map +1 -0
- package/dist/tests/partial_update.test.js +79 -6
- package/dist/tests/partial_update.test.js.map +1 -1
- package/docs/3.table-modifiers.md +35 -9
- package/docs/4.data-models.md +2 -0
- package/package.json +5 -5
- package/skills/database-decorators-interface/SKILL.md +6 -2
|
@@ -11,6 +11,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const chai_1 = require("chai");
|
|
13
13
|
const table_1 = require("../../table");
|
|
14
|
+
const common_1 = require("../../modifiers/common");
|
|
15
|
+
const hash_1 = require("../../modifiers/hash");
|
|
14
16
|
const localization_1 = require("../../modifiers/localization");
|
|
15
17
|
describe("Modifiers - localization", () => {
|
|
16
18
|
it("creates localization modifier", async () => {
|
|
@@ -93,6 +95,13 @@ describe("Modifiers - localization", () => {
|
|
|
93
95
|
(0, chai_1.expect)(cleared).to.deep.equal({ en: "Hello" });
|
|
94
96
|
(0, chai_1.expect)(everyLanguage).to.deep.equal({ en: "Hello" });
|
|
95
97
|
});
|
|
98
|
+
it("answers the fallback locale when no locale is given", async () => {
|
|
99
|
+
const modifier = new TestableLocalizationModifier();
|
|
100
|
+
modifier.setOptions({ fallbackLocale: "en" });
|
|
101
|
+
const locked = modifier.lock({ en: "Hello" }, "Ignored", undefined);
|
|
102
|
+
(0, chai_1.expect)(locked).to.deep.equal({ en: "Hello" });
|
|
103
|
+
(0, chai_1.expect)(modifier.unlock({ en: "Hello", undefined: "x" }, undefined)).to.equal("Hello");
|
|
104
|
+
});
|
|
96
105
|
it("handles missing locale gracefully", async () => {
|
|
97
106
|
const modifier = new TestableLocalizationModifier();
|
|
98
107
|
modifier.setOptions({});
|
|
@@ -179,6 +188,40 @@ describe("Modifiers - localization", () => {
|
|
|
179
188
|
(0, chai_1.expect)(instance.content).to.equal("French Content");
|
|
180
189
|
(0, chai_1.expect)(instance.description).to.equal("English Description");
|
|
181
190
|
});
|
|
191
|
+
it("refuses a text assigned to every locale at once", async () => {
|
|
192
|
+
class Page extends table_1.Table.with(localization_1.LocalizationModifier) {
|
|
193
|
+
}
|
|
194
|
+
__decorate([
|
|
195
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
196
|
+
(0, table_1.Field)("string"),
|
|
197
|
+
__metadata("design:type", String)
|
|
198
|
+
], Page.prototype, "title", void 0);
|
|
199
|
+
const page = (0, common_1.fromPlainData)({}, Page).localize("en");
|
|
200
|
+
page.title = "Hello";
|
|
201
|
+
(0, chai_1.expect)(() => {
|
|
202
|
+
page.localize("*").title = "Bonjour";
|
|
203
|
+
}).to.throw(TypeError);
|
|
204
|
+
const stored = (0, common_1.fromDatabase)((0, common_1.toDatabase)(page), Page);
|
|
205
|
+
(0, chai_1.expect)(stored.localize("en").title).to.equal("Hello");
|
|
206
|
+
(0, chai_1.expect)(stored.localize("0").title).to.equal("Hello");
|
|
207
|
+
});
|
|
208
|
+
it("clears every locale when no value is assigned to all of them", async () => {
|
|
209
|
+
class Page extends table_1.Table.with(localization_1.LocalizationModifier) {
|
|
210
|
+
}
|
|
211
|
+
__decorate([
|
|
212
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
213
|
+
(0, table_1.Field)("string"),
|
|
214
|
+
__metadata("design:type", String)
|
|
215
|
+
], Page.prototype, "title", void 0);
|
|
216
|
+
const unset = (0, common_1.fromPlainData)({}, Page);
|
|
217
|
+
const page = (0, common_1.fromPlainData)({}, Page).localize("en");
|
|
218
|
+
page.title = "Hello";
|
|
219
|
+
(0, common_1.lock)(unset, localization_1.LocalizationModifier, undefined, "*");
|
|
220
|
+
page.localize("*").title = undefined;
|
|
221
|
+
(0, chai_1.expect)((0, common_1.toDatabase)(unset)._internal?.data.title).to.deep.equal({});
|
|
222
|
+
(0, chai_1.expect)(page.localize("en").title).to.equal(undefined);
|
|
223
|
+
(0, chai_1.expect)((0, common_1.toDatabase)(page)._internal?.data.title).to.deep.equal({});
|
|
224
|
+
});
|
|
182
225
|
it("maintains data structure integrity", async () => {
|
|
183
226
|
const modifier = new TestableLocalizationModifier();
|
|
184
227
|
modifier.setOptions({ fallbackLocale: "en" });
|
|
@@ -198,6 +241,97 @@ describe("Modifiers - localization", () => {
|
|
|
198
241
|
});
|
|
199
242
|
});
|
|
200
243
|
});
|
|
244
|
+
describe("Modifiers - localization wildcard key", () => {
|
|
245
|
+
it("reads the listed fields under the wildcard key as texts by locale", async () => {
|
|
246
|
+
class TestTable extends table_1.Table.with(localization_1.LocalizationModifier) {
|
|
247
|
+
}
|
|
248
|
+
__decorate([
|
|
249
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
250
|
+
(0, table_1.Field)("string"),
|
|
251
|
+
__metadata("design:type", String)
|
|
252
|
+
], TestTable.prototype, "title", void 0);
|
|
253
|
+
__decorate([
|
|
254
|
+
(0, table_1.Field)("string"),
|
|
255
|
+
__metadata("design:type", String)
|
|
256
|
+
], TestTable.prototype, "code", void 0);
|
|
257
|
+
const LISTED = ["title"];
|
|
258
|
+
const instance = new TestTable();
|
|
259
|
+
instance.code = "P-1";
|
|
260
|
+
instance.localize("en").title = "Title";
|
|
261
|
+
instance.localize("fr").title = "Titre";
|
|
262
|
+
const texts = instance.localize("*", LISTED);
|
|
263
|
+
const titles = texts.title;
|
|
264
|
+
const code = texts.code;
|
|
265
|
+
(0, chai_1.expect)(titles).to.deep.equal({ en: "Title", fr: "Titre" });
|
|
266
|
+
(0, chai_1.expect)(code).to.equal("P-1");
|
|
267
|
+
});
|
|
268
|
+
it("reads one locale again after the wildcard key", async () => {
|
|
269
|
+
class TestTable extends table_1.Table.with(localization_1.LocalizationModifier) {
|
|
270
|
+
}
|
|
271
|
+
__decorate([
|
|
272
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
273
|
+
(0, table_1.Field)("string"),
|
|
274
|
+
__metadata("design:type", String)
|
|
275
|
+
], TestTable.prototype, "title", void 0);
|
|
276
|
+
__decorate([
|
|
277
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
278
|
+
(0, table_1.Field)("string"),
|
|
279
|
+
__metadata("design:type", String)
|
|
280
|
+
], TestTable.prototype, "subtitle", void 0);
|
|
281
|
+
const instance = new TestTable();
|
|
282
|
+
instance.localize("en").title = "Title";
|
|
283
|
+
const texts = instance.localize("*", ["title", "subtitle"]);
|
|
284
|
+
const subtitles = texts.subtitle;
|
|
285
|
+
const title = texts.localize("en").title;
|
|
286
|
+
(0, chai_1.expect)(subtitles).to.equal(undefined);
|
|
287
|
+
(0, chai_1.expect)(title).to.equal("Title");
|
|
288
|
+
});
|
|
289
|
+
it("keeps the methods callable under the wildcard key for a list of any keys", async () => {
|
|
290
|
+
class TestTable extends table_1.Table.with(localization_1.LocalizationModifier, hash_1.HashModifier) {
|
|
291
|
+
}
|
|
292
|
+
__decorate([
|
|
293
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
294
|
+
(0, table_1.Field)("string"),
|
|
295
|
+
__metadata("design:type", String)
|
|
296
|
+
], TestTable.prototype, "title", void 0);
|
|
297
|
+
__decorate([
|
|
298
|
+
(0, hash_1.Hashed)({ algorithm: "sha256" }),
|
|
299
|
+
(0, table_1.Field)("string"),
|
|
300
|
+
__metadata("design:type", String)
|
|
301
|
+
], TestTable.prototype, "fingerprint", void 0);
|
|
302
|
+
const anyKeys = ["title", "isHashOutdated"];
|
|
303
|
+
const instance = new TestTable();
|
|
304
|
+
instance.localize("en").title = "Title";
|
|
305
|
+
instance.fingerprint = "print";
|
|
306
|
+
const texts = instance.localize("*", anyKeys);
|
|
307
|
+
const titles = { ...texts.title };
|
|
308
|
+
const outdated = texts.isHashOutdated("fingerprint");
|
|
309
|
+
const row = texts.localize("en");
|
|
310
|
+
(0, chai_1.expect)(titles).to.deep.equal({ en: "Title" });
|
|
311
|
+
(0, chai_1.expect)(outdated).to.equal(false);
|
|
312
|
+
(0, chai_1.expect)(row.title).to.equal("Title");
|
|
313
|
+
});
|
|
314
|
+
it("reads the wildcard key as texts by locale through a generic row", async () => {
|
|
315
|
+
class TestTable extends table_1.Table.with(localization_1.LocalizationModifier) {
|
|
316
|
+
titles() {
|
|
317
|
+
return this.localize("*", ["title"]).title;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
__decorate([
|
|
321
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
322
|
+
(0, table_1.Field)("string"),
|
|
323
|
+
__metadata("design:type", String)
|
|
324
|
+
], TestTable.prototype, "title", void 0);
|
|
325
|
+
function withTitles(row) {
|
|
326
|
+
return [row, row.localize("*", ["title"]).title];
|
|
327
|
+
}
|
|
328
|
+
const instance = new TestTable();
|
|
329
|
+
instance.localize("en").title = "Title";
|
|
330
|
+
const own = instance.titles();
|
|
331
|
+
(0, chai_1.expect)(own).to.deep.equal({ en: "Title" });
|
|
332
|
+
(0, chai_1.expect)(withTitles(instance)[1]).to.deep.equal({ en: "Title" });
|
|
333
|
+
});
|
|
334
|
+
});
|
|
201
335
|
class TestableLocalizationModifier extends localization_1.LocalizationModifier {
|
|
202
336
|
setOptions(options) {
|
|
203
337
|
this.options = options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localization.test.js","sourceRoot":"","sources":["../../../src/tests/modifiers/localization.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"localization.test.js","sourceRoot":"","sources":["../../../src/tests/modifiers/localization.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const table_1 = require("../../table");
|
|
5
|
+
const common_1 = require("../../modifiers/common");
|
|
6
|
+
const field = Symbol("field");
|
|
7
|
+
class PrefixModifier extends common_1.TwoWayModifier {
|
|
8
|
+
lock(_locked, value, prefix) {
|
|
9
|
+
return `${prefix}:${value}`;
|
|
10
|
+
}
|
|
11
|
+
unlock(locked, prefix) {
|
|
12
|
+
return locked.slice(prefix.length + 1);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
class AutoModifier extends common_1.TwoWayModifier {
|
|
16
|
+
autolock = true;
|
|
17
|
+
autounlock = true;
|
|
18
|
+
lock(_locked, value) {
|
|
19
|
+
return [value];
|
|
20
|
+
}
|
|
21
|
+
unlock(locked) {
|
|
22
|
+
return locked[0];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function autoRow() {
|
|
26
|
+
class AutoRow extends table_1.Table {
|
|
27
|
+
}
|
|
28
|
+
(0, common_1.attachModifier)(AutoRow, AutoModifier, field, {});
|
|
29
|
+
return AutoRow;
|
|
30
|
+
}
|
|
31
|
+
describe("Modifiers - symbol-named fields", () => {
|
|
32
|
+
it("locks and unlocks a symbol-named field on first write", () => {
|
|
33
|
+
const row = new (autoRow())();
|
|
34
|
+
row[field] = "value";
|
|
35
|
+
(0, chai_1.expect)(row[field]).to.equal("value");
|
|
36
|
+
(0, chai_1.expect)((0, common_1.toDatabase)(row)._internal?.data[field]).to.deep.equal(["value"]);
|
|
37
|
+
});
|
|
38
|
+
it("locks a symbol-named field with lock() arguments", () => {
|
|
39
|
+
class PrefixRow extends table_1.Table {
|
|
40
|
+
}
|
|
41
|
+
(0, common_1.attachModifier)(PrefixRow, PrefixModifier, field, {});
|
|
42
|
+
const row = new PrefixRow();
|
|
43
|
+
row[field] = "value";
|
|
44
|
+
(0, common_1.lock)(row, PrefixModifier, [field], "p");
|
|
45
|
+
(0, chai_1.expect)((0, common_1.toDatabase)(row)._internal?.data[field]).to.equal("p:value");
|
|
46
|
+
(0, common_1.unlock)(row, PrefixModifier, [field], "p");
|
|
47
|
+
(0, chai_1.expect)(row[field]).to.equal("value");
|
|
48
|
+
});
|
|
49
|
+
it("keeps a symbol-named field modified in a subclass", () => {
|
|
50
|
+
class ChildRow extends autoRow() {
|
|
51
|
+
}
|
|
52
|
+
const row = new ChildRow();
|
|
53
|
+
row[field] = "value";
|
|
54
|
+
(0, chai_1.expect)(row[field]).to.equal("value");
|
|
55
|
+
});
|
|
56
|
+
it("lists a symbol-named field among the modified fields", () => {
|
|
57
|
+
(0, chai_1.expect)((0, common_1.getModifiedFields)(new (autoRow())(), AutoModifier)).to.deep.equal([
|
|
58
|
+
field,
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=symbol_fields.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol_fields.test.js","sourceRoot":"","sources":["../../../src/tests/modifiers/symbol_fields.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,9 +15,12 @@ const database_1 = require("../database");
|
|
|
15
15
|
const model_1 = require("../model");
|
|
16
16
|
const autodate_1 = require("../modifiers/autodate");
|
|
17
17
|
const encryption_1 = require("../modifiers/encryption");
|
|
18
|
+
const hash_1 = require("../modifiers/hash");
|
|
19
|
+
const records_1 = require("../modifiers/internal/records");
|
|
18
20
|
const schema_1 = require("../schema");
|
|
19
21
|
const table_1 = require("../table");
|
|
20
22
|
const SCHEMA_ID = "partial-update-schema";
|
|
23
|
+
const SECRET_KEY = "0123456789abcdef0123456789abcdef";
|
|
21
24
|
let Note = class Note extends table_1.Table.with(encryption_1.EncryptionModifier) {
|
|
22
25
|
};
|
|
23
26
|
__decorate([
|
|
@@ -30,26 +33,96 @@ __decorate([
|
|
|
30
33
|
__metadata("design:type", Date)
|
|
31
34
|
], Note.prototype, "updatedAt", void 0);
|
|
32
35
|
__decorate([
|
|
33
|
-
(0, encryption_1.Encrypted)({ secretKey:
|
|
36
|
+
(0, encryption_1.Encrypted)({ secretKey: SECRET_KEY }),
|
|
34
37
|
(0, table_1.Field)("string"),
|
|
35
38
|
__metadata("design:type", String)
|
|
36
39
|
], Note.prototype, "secret", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, encryption_1.Encrypted)({ secretKey: SECRET_KEY }),
|
|
42
|
+
(0, table_1.Field)("string"),
|
|
43
|
+
__metadata("design:type", String)
|
|
44
|
+
], Note.prototype, "other", void 0);
|
|
37
45
|
Note = __decorate([
|
|
38
46
|
(0, schema_1.RegisterTable)("partial_update_notes", SCHEMA_ID)
|
|
39
47
|
], Note);
|
|
48
|
+
let Account = class Account extends table_1.Table.with(hash_1.HashModifier) {
|
|
49
|
+
};
|
|
50
|
+
__decorate([
|
|
51
|
+
(0, table_1.Field)("string"),
|
|
52
|
+
__metadata("design:type", String)
|
|
53
|
+
], Account.prototype, "name", void 0);
|
|
54
|
+
__decorate([
|
|
55
|
+
(0, hash_1.Hashed)({ algorithm: "sha256" }),
|
|
56
|
+
(0, table_1.Field)("string"),
|
|
57
|
+
__metadata("design:type", String)
|
|
58
|
+
], Account.prototype, "pin", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, hash_1.Hashed)({ algorithm: "sha256" }),
|
|
61
|
+
(0, table_1.Field)("string"),
|
|
62
|
+
__metadata("design:type", String)
|
|
63
|
+
], Account.prototype, "token", void 0);
|
|
64
|
+
Account = __decorate([
|
|
65
|
+
(0, schema_1.RegisterTable)("partial_update_accounts", SCHEMA_ID)
|
|
66
|
+
], Account);
|
|
40
67
|
const NoteModel = (0, model_1.BasicDataModel)(Note, "partial_update_notes");
|
|
68
|
+
const AccountModel = (0, model_1.BasicDataModel)(Account, "partial_update_accounts");
|
|
69
|
+
async function schemaInstance() {
|
|
70
|
+
await (0, database_1.RegisterSchema)(SCHEMA_ID);
|
|
71
|
+
const instance = interface_database_1.Schema.get(SCHEMA_ID)?.instance();
|
|
72
|
+
if (!instance)
|
|
73
|
+
throw new Error("Partial update schema not found");
|
|
74
|
+
return instance;
|
|
75
|
+
}
|
|
41
76
|
describe("Integration - partial update", () => {
|
|
42
77
|
it("keeps modifier data on an update of another field", async () => {
|
|
43
|
-
|
|
44
|
-
const instance = interface_database_1.Schema.get(SCHEMA_ID)?.instance();
|
|
45
|
-
if (!instance)
|
|
46
|
-
throw new Error("Partial update schema not found");
|
|
47
|
-
const model = new NoteModel(instance);
|
|
78
|
+
const model = new NoteModel(await schemaInstance());
|
|
48
79
|
const [id] = await model.insert({ title: "First", secret: "kept" });
|
|
49
80
|
await model.update(id, { title: "Second" });
|
|
50
81
|
const note = await model.get(id);
|
|
51
82
|
(0, chai_1.expect)(note?.title).to.equal("Second");
|
|
52
83
|
(0, chai_1.expect)(note?.secret).to.equal("kept");
|
|
53
84
|
});
|
|
85
|
+
it("keeps the other encrypted field on an update of one", async () => {
|
|
86
|
+
const model = new NoteModel(await schemaInstance());
|
|
87
|
+
const [id] = await model.insert({ secret: "a", other: "kept" });
|
|
88
|
+
await model.update(id, { secret: "b" });
|
|
89
|
+
const note = await model.get(id);
|
|
90
|
+
(0, chai_1.expect)(note?.secret).to.equal("b");
|
|
91
|
+
(0, chai_1.expect)(note?.other).to.equal("kept");
|
|
92
|
+
});
|
|
93
|
+
it("keeps the other hashed field and the salt on an update by id", async () => {
|
|
94
|
+
const model = new AccountModel(await schemaInstance());
|
|
95
|
+
const [id] = await model.insert({ name: "Ann", pin: "1234", token: "abc" });
|
|
96
|
+
const before = await model.get(id);
|
|
97
|
+
if (!before)
|
|
98
|
+
throw new Error("Inserted account not found");
|
|
99
|
+
await model.update(id, { pin: "9999" });
|
|
100
|
+
const account = await model.get(id);
|
|
101
|
+
if (!account)
|
|
102
|
+
throw new Error("Updated account not found");
|
|
103
|
+
(0, chai_1.expect)(account.testHash("pin", "9999")).to.equal(true);
|
|
104
|
+
(0, chai_1.expect)(account.testHash("token", "abc")).to.equal(true);
|
|
105
|
+
(0, chai_1.expect)((0, records_1.getInternal)(account).meta).to.deep.equal((0, records_1.getInternal)(before).meta);
|
|
106
|
+
});
|
|
107
|
+
it("keeps the other hashed field and the salt on an update by row", async () => {
|
|
108
|
+
const model = new AccountModel(await schemaInstance());
|
|
109
|
+
const [id] = await model.insert({ name: "Ann", pin: "1234", token: "abc" });
|
|
110
|
+
const before = await model.get(id);
|
|
111
|
+
if (!before)
|
|
112
|
+
throw new Error("Inserted account not found");
|
|
113
|
+
await model.update({ _id: id, pin: "9999" });
|
|
114
|
+
const account = await model.get(id);
|
|
115
|
+
if (!account)
|
|
116
|
+
throw new Error("Updated account not found");
|
|
117
|
+
(0, chai_1.expect)(account.testHash("pin", "9999")).to.equal(true);
|
|
118
|
+
(0, chai_1.expect)(account.testHash("token", "abc")).to.equal(true);
|
|
119
|
+
(0, chai_1.expect)((0, records_1.getInternal)(account).meta).to.deep.equal((0, records_1.getInternal)(before).meta);
|
|
120
|
+
});
|
|
121
|
+
it("updates no row for an id the table does not hold", async () => {
|
|
122
|
+
const model = new AccountModel(await schemaInstance());
|
|
123
|
+
const count = await model.update("missing-account", { pin: "9999" });
|
|
124
|
+
(0, chai_1.expect)(count).to.equal(0);
|
|
125
|
+
(0, chai_1.expect)(await model.get("missing-account")).to.equal(undefined);
|
|
126
|
+
});
|
|
54
127
|
});
|
|
55
128
|
//# sourceMappingURL=partial_update.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"partial_update.test.js","sourceRoot":"","sources":["../../src/tests/partial_update.test.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,+BAA8B;AAC9B,uEAAwD;AACxD,0CAA6C;AAC7C,oCAA0C;AAC1C,oDAAmD;AACnD,wDAAwE;AACxE,sCAA0C;AAC1C,oCAAwC;AAExC,MAAM,SAAS,GAAG,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"partial_update.test.js","sourceRoot":"","sources":["../../src/tests/partial_update.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,7 +91,8 @@ class User extends Table.with(HashModifier) {
|
|
|
91
91
|
|
|
92
92
|
- The field hashes the value encoded as JSON, so `"secret"` is hashed as the text `"\"secret\""`.
|
|
93
93
|
- Each write draws a random 16-byte salt and stores `$scrypt$ln=15,r=8,p=3$<salt>$<key>`. The salt and the 32-byte key are base64 without padding. `ln` is the base-2 logarithm of the scrypt cost N, so N is 32768. The string holds the parameters, the salt, and the key, so the cost can change later.
|
|
94
|
-
-
|
|
94
|
+
- An assignment is synchronous, because a property setter cannot wait, and so are the conversions behind a model's `insert` and `update` of plain data. Each assignment blocks the event loop for one scrypt run, about 150 ms, which uses 32 MiB (128 × N × r bytes).
|
|
95
|
+
- `setHashAsync` runs that scrypt run on the thread pool, then assigns the result. It stores the same format as an assignment, so rows written either way verify the same way.
|
|
95
96
|
- Assigning the stored hash back to the field, or calling `lock` on a loaded row, keeps the hash as it is. Assigning `undefined` stores nothing.
|
|
96
97
|
- `testHash` and `testHashAsync` read `ln`, `r`, `p`, the salt, and the key from the stored string. They derive a key of the stored key's length from the candidate and compare the two with `crypto.timingSafeEqual`, in constant time.
|
|
97
98
|
- A stored scrypt string verifies only within these limits: `ln`, `r`, and `p` from 1 to 99, at most 128 MiB of memory, `p` at most 16, `ln` below 16 × `r`, and a salt and a key of 16 to 64 bytes each. A string outside them refuses every candidate.
|
|
@@ -110,23 +111,35 @@ A field with an `algorithm` stores the base64 digest of the row's salt followed
|
|
|
110
111
|
The `HashModifier` mixin adds these methods to table instances:
|
|
111
112
|
|
|
112
113
|
```typescript fragment
|
|
113
|
-
testHash<This extends {}, F extends keyof This>(this: This, field: F, value: This[F]):
|
|
114
|
+
testHash<This extends {}, F extends keyof This>(this: This, field: F, value: This[F]): boolean
|
|
114
115
|
testHashAsync<This extends {}, F extends keyof This>(this: This, field: F, value: This[F]): Promise<boolean>
|
|
116
|
+
setHashAsync<This extends object, F extends keyof This>(this: This, field: F, value: This[F]): Promise<void>
|
|
115
117
|
isHashOutdated<This extends {}>(this: This, field: keyof This): boolean
|
|
116
118
|
```
|
|
117
119
|
|
|
120
|
+
- `setHashAsync` hashes `value` on the thread pool and resolves once the field holds the hash, as `row[field] = value` would leave it. Use it on a server for every write of a scrypt field, such as a signup or a password change, then save the row instance with the model. It rejects with `Field <name> is not hashed` for a field without `@Hashed`. On a field with an `algorithm`, it assigns at once, because a digest is fast. On a field with another modifier beside `@Hashed`, it also assigns at once, on the event loop. Calls on one row that overlap settle in the order their scrypt runs end, so await each one before the next.
|
|
121
|
+
|
|
122
|
+
```typescript fragment
|
|
123
|
+
const user = new User();
|
|
124
|
+
user.email = email;
|
|
125
|
+
await user.setHashAsync("password", password);
|
|
126
|
+
await userModel.insert(user);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`userModel.insert({ email, password })` and `userModel.update(id, { password })` still hash on the event loop, because they convert plain data through the setter.
|
|
130
|
+
|
|
118
131
|
- `testHashAsync` resolves whether `value` matches the stored hash. It runs scrypt on the thread pool, so use it on a server. It rejects with `Field <name> is not hashed` for a field without `@Hashed`.
|
|
119
|
-
- `testHash` gives the same result and blocks the event loop while scrypt runs.
|
|
132
|
+
- `testHash` gives the same result and blocks the event loop while scrypt runs. It throws `Field <name> is not hashed` for a field without `@Hashed`.
|
|
120
133
|
- `isHashOutdated` returns whether the stored hash differs from what the field writes today, which is any stored string that does not start with `$scrypt$ln=15,r=8,p=3$`. It returns `false` when nothing is stored, and always on a field with an `algorithm`. It throws `Field <name> is not hashed` for a field without `@Hashed`.
|
|
121
134
|
|
|
122
135
|
#### Upgrade stored hashes
|
|
123
136
|
|
|
124
|
-
A row whose hash has another format still verifies. On a field without an `algorithm`, a string that is not a scrypt hash is tested as a salted SHA-256 digest, made with the salt in `_internal.meta.HashModifier.salt`, and `isHashOutdated` returns `true` for it. A scrypt hash of another cost verifies with its own parameters and is flagged too. To rewrite a flagged hash,
|
|
137
|
+
A row whose hash has another format still verifies. On a field without an `algorithm`, a string that is not a scrypt hash is tested as a salted SHA-256 digest, made with the salt in `_internal.meta.HashModifier.salt`, and `isHashOutdated` returns `true` for it. A scrypt hash of another cost verifies with its own parameters and is flagged too. To rewrite a flagged hash, set the value after a successful test, because only then is the plaintext known:
|
|
125
138
|
|
|
126
139
|
```typescript fragment
|
|
127
140
|
if (await user.testHashAsync("password", password)) {
|
|
128
141
|
if (user.isHashOutdated("password")) {
|
|
129
|
-
user.password
|
|
142
|
+
await user.setHashAsync("password", password);
|
|
130
143
|
await userModel.update(user);
|
|
131
144
|
}
|
|
132
145
|
}
|
|
@@ -187,11 +200,11 @@ console.log(german.name); // "Premium Headphones" (fallback)
|
|
|
187
200
|
|
|
188
201
|
#### Wildcard key
|
|
189
202
|
|
|
190
|
-
The wildcard key `"*"` reads or writes all translations at once. `localize()`
|
|
203
|
+
The wildcard key `"*"` reads or writes all translations at once. List the localized fields with it, and `localize("*", fields)` types each listed field as its values by locale, a `LocalizedRecords<T, K>`: a field declared as `string` reads as a `Record<string, string>`. Calling `localize()` on that view with one locale gives back the row type. The view is not the row type, so pass the row itself to `insert()` or `update()`. Write all translations with `Object.assign`, which calls the field's setter. `undefined` or `null` clears every translation. Any other value that is not a record, such as a single text, throws a `TypeError` and leaves the stored translations as they were:
|
|
191
204
|
|
|
192
205
|
```typescript fragment
|
|
193
206
|
// Get all translations
|
|
194
|
-
const allNames:
|
|
207
|
+
const allNames: Record<string, string> = product.localize("*", ["name"]).name;
|
|
195
208
|
// { en: "Premium Headphones", fr: "Casque Premium", es: "Auriculares Premium" }
|
|
196
209
|
|
|
197
210
|
// Set all translations
|
|
@@ -216,9 +229,12 @@ Object.assign(product.localize("*"), {
|
|
|
216
229
|
The `LocalizationModifier` mixin adds a `localize` method:
|
|
217
230
|
|
|
218
231
|
```typescript fragment
|
|
219
|
-
localize<This extends { constructor: any }>(this: This, locale:
|
|
232
|
+
localize<This extends { constructor: any }, K extends keyof This>(this: This, locale: "*", fields: readonly K[]): LocalizedRecords<This, K>
|
|
233
|
+
localize<This extends { constructor: any }>(this: This, locale: string, fields?: ReadonlyArray<keyof This>): This
|
|
220
234
|
```
|
|
221
235
|
|
|
236
|
+
Without `fields`, `localize("*")` unlocks every localized field but keeps the class's field types. A listed method stays callable.
|
|
237
|
+
|
|
222
238
|
`localize()` changes the active locale and returns the same object, not a copy for that locale.
|
|
223
239
|
|
|
224
240
|
- **References share state.** `spanish`, `german`, and `product` above refer to one object. A later `localize()` call changes what all three references read.
|
|
@@ -410,7 +426,7 @@ Base64 is an encoding, not encryption. The example declares its `LockedType` as
|
|
|
410
426
|
|
|
411
427
|
### `ContainerModifier`
|
|
412
428
|
|
|
413
|
-
A modifier that stores several values under keys, as `LocalizationModifier` does, extends `ContainerModifier`. Its `lock`, `unlock`, and `unlockrequest` take the key as their argument
|
|
429
|
+
A modifier that stores several values under keys, as `LocalizationModifier` does, extends `ContainerModifier`. Its `lock`, `unlock`, and `unlockrequest` take the key as their argument, a `string` or `undefined`. `lock` and `unlock` treat the wildcard key `"*"` as the whole record, and `lock` throws a `TypeError` for a value under `"*"` that is not a record. `undefined` is no key: `lock` stores nothing under it, and `unlock` and `unlockrequest` find no value, so a `LocalizationModifier` answers its `fallbackLocale`:
|
|
414
430
|
|
|
415
431
|
```typescript
|
|
416
432
|
import { ContainerModifier } from "@antelopejs/interface-database-decorators";
|
|
@@ -421,6 +437,16 @@ class MyContainerModifier extends ContainerModifier<{}, { fallback?: string }> {
|
|
|
421
437
|
}
|
|
422
438
|
```
|
|
423
439
|
|
|
440
|
+
### Attach a modifier
|
|
441
|
+
|
|
442
|
+
A decorator attaches its modifier with `attachModifier(target.constructor, Modifier, propertyKey, options)`, as the examples above do. TypeScript checks `options` against the modifier's options type. It does not check that the field names a member of the class.
|
|
443
|
+
|
|
444
|
+
A modifier with `lock` replaces the field with an accessor that routes reads and writes through the field's modifiers. `attachModifier` throws an `Error` when such a modifier goes on `constructor` or `__proto__`, or on a field that already has a one-way modifier. A modifier without `lock` only handles events, and the field keeps its plain value.
|
|
445
|
+
|
|
446
|
+
### Read a modified field in a query
|
|
447
|
+
|
|
448
|
+
`unlockrequest(table, row, field, modifiers)` reads a field unlocked inside a database query. It reads `table` only for its modifier metadata. Each two-way modifier on the field passes the stored value through its own `unlockrequest()`, with the arguments that `modifiers` gives for it by class name. A field with only one-way modifiers yields its stored value as it is. `unlockrequest` throws a `TypeError` when `modifiers` has no entry for a two-way modifier on the field. TypeScript checks that `field` is a key of the row, not each entry's arguments.
|
|
449
|
+
|
|
424
450
|
## Modifier events
|
|
425
451
|
|
|
426
452
|
A modifier hooks into a row's lifecycle through methods named after events. The engine calls each one with the modifier as `this`, then the table instance, the field name, and the event's arguments:
|
package/docs/4.data-models.md
CHANGED
|
@@ -95,6 +95,8 @@ await userModel.update({ _id: "user-123", name: "Updated Name" });
|
|
|
95
95
|
|
|
96
96
|
When you call `update` without a separate ID argument, the object must include the primary key. Its type requires `_id`, and a call without it throws `Missing primary key in object update.`
|
|
97
97
|
|
|
98
|
+
An update with plain data that sets a field whose modifiers lock without arguments, such as an encrypted or hashed field, first reads the row's stored modifier state, then locks the new value onto it. The row keeps its other modified fields and its hash salt. A table instance, such as one read with `get`, already holds that state and costs no extra read.
|
|
99
|
+
|
|
98
100
|
### Delete
|
|
99
101
|
|
|
100
102
|
```typescript fragment
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-database-decorators",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "AntelopeJS decorators for database tables and typed data models, with encrypted, hashed and localized fields",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antelopejs",
|
|
@@ -124,11 +124,11 @@
|
|
|
124
124
|
"lint:fix": "oxlint --fix",
|
|
125
125
|
"lint": "oxlint",
|
|
126
126
|
"prepack": "pnpm run build",
|
|
127
|
-
"release": "pnpm run lint && pnpm run prepack && release-it",
|
|
127
|
+
"release": "pnpm run typecheck && pnpm run lint && pnpm run prepack && release-it",
|
|
128
128
|
"test": "pnpm run build && ajs module test .",
|
|
129
129
|
"format:check": "oxfmt --check .",
|
|
130
130
|
"knip": "knip",
|
|
131
|
-
"prepare": "if
|
|
131
|
+
"prepare": "if [ -e .git ] && command -v git >/dev/null 2>&1 && command -v lefthook >/dev/null 2>&1 && GIT_DIR=.git GIT_WORK_TREE=. git rev-parse --git-dir >/dev/null 2>&1; then GIT_DIR=.git GIT_WORK_TREE=. lefthook install; fi",
|
|
132
132
|
"checks": "antelopejs-checks",
|
|
133
133
|
"size": "antelopejs-check-size",
|
|
134
134
|
"sync": "antelopejs-sync",
|
|
@@ -142,11 +142,11 @@
|
|
|
142
142
|
"reflect-metadata": "^0.2.2"
|
|
143
143
|
},
|
|
144
144
|
"devDependencies": {
|
|
145
|
-
"@antelopejs/core": "^1.
|
|
145
|
+
"@antelopejs/core": "^1.21.0",
|
|
146
146
|
"@antelopejs/interface-api": "^0.0.15",
|
|
147
147
|
"@antelopejs/interface-core": "^0.4.0",
|
|
148
148
|
"@antelopejs/interface-database": "^0.3.0",
|
|
149
|
-
"@antelopejs/tooling-configs": "^0.
|
|
149
|
+
"@antelopejs/tooling-configs": "^0.5.1",
|
|
150
150
|
"@types/chai": "^4.3.20",
|
|
151
151
|
"@types/mocha": "^10.0.10",
|
|
152
152
|
"@types/node": "^22.19.15",
|
|
@@ -110,7 +110,7 @@ class Chef extends Table.with(
|
|
|
110
110
|
EncryptionModifier,
|
|
111
111
|
LocalizationModifier,
|
|
112
112
|
) {
|
|
113
|
-
@Hashed() declare passphrase: string; // one-way scrypt; test via await instance.testHashAsync("passphrase", value)
|
|
113
|
+
@Hashed() declare passphrase: string; // one-way scrypt; set via await instance.setHashAsync("passphrase", value), test via await instance.testHashAsync("passphrase", value)
|
|
114
114
|
@Encrypted({ secretKey }) declare supplierCode: string; // transparent encrypt/decrypt (autolock + autounlock)
|
|
115
115
|
@Localized() declare motto: string; // read AND write via instance.localize("en", ["motto"])
|
|
116
116
|
@CreationTime() declare hiredAt: Date; // set on insert, stripped from updates
|
|
@@ -125,11 +125,15 @@ class Chef extends Table.with(
|
|
|
125
125
|
- `Hashed`, `Encrypted`, and `Localized` require the matching modifier class in `Table.with(...)`; `CreationTime`/`UpdateTime` are event-only and need no mixin.
|
|
126
126
|
- Modifier ordering matters: `attachModifier` throws if you stack a modifier after a one-way modifier (e.g. anything after `@Hashed` on the same field).
|
|
127
127
|
- Hashed fields cannot be read back or queried directly — only equality-tested with `testHashAsync`, or `testHash`, which blocks the event loop for one scrypt run.
|
|
128
|
-
-
|
|
128
|
+
- On a server, write a scrypt field with `await instance.setHashAsync(field, value)`, then insert or update the instance. Assigning the field, or passing it in plain data to `insert` or `update`, blocks the event loop for one scrypt run (about 150 ms).
|
|
129
|
+
- A row can hold an older hash that still verifies. After a successful test, when `instance.isHashOutdated(field)` is true, `await instance.setHashAsync(field, value)` with the tested value and save the row.
|
|
129
130
|
- `@Hashed({ algorithm })` stores a fast digest instead of scrypt: use it only for non-secret fingerprints, never for credentials.
|
|
130
131
|
- Localized fields must be written through a localized instance (`instance.localize(locale).field = ...`);
|
|
131
132
|
values assigned before `localize()` are held in floating state and silently dropped on insert/update.
|
|
133
|
+
- `instance.localize("*", ["motto"])` reads and writes every locale at once, typed `Record<string, string>` for each listed field (`LocalizedRecords<T, K>`); without a field list the field types stay unchanged.
|
|
134
|
+
- Under `localize("*")` a localized field takes the record of texts by locale, and `undefined` or `null` clears every locale. A single text throws a `TypeError`, whether it is assigned or held from `fromPlainData` when `localize("*")` runs.
|
|
132
135
|
- A localized value `""` is stored as no value: reads and queries in that locale get the `fallbackLocale` value.
|
|
136
|
+
- A `ContainerModifier` key of `undefined` is no key: writes store nothing under it, and reads and queries get no value, or the `fallbackLocale` value for a localized field.
|
|
133
137
|
- `@Relation({ to: () => Target })` is declarative metadata only: no foreign-key enforcement, consumed by introspection tooling via `RelationStaticMetadata`.
|
|
134
138
|
- `Model.validate` (and `{ validate: true }` on insert/update) only checks fields whose `@Field` type is an
|
|
135
139
|
io-ts-style codec with `.decode`; plain string field tokens are skipped. Update validates with
|