@antelopejs/interface-database-decorators 0.1.11 → 0.2.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.
Files changed (88) hide show
  1. package/README.md +17 -13
  2. package/dist/antelope.test.js +1 -1
  3. package/dist/common.d.ts +48 -2
  4. package/dist/common.js +51 -5
  5. package/dist/common.js.map +1 -1
  6. package/dist/database.js +18 -3
  7. package/dist/database.js.map +1 -1
  8. package/dist/internal/bound-schema.d.ts +8 -0
  9. package/dist/internal/bound-schema.js +14 -0
  10. package/dist/internal/bound-schema.js.map +1 -0
  11. package/dist/model.d.ts +21 -8
  12. package/dist/model.js +34 -15
  13. package/dist/model.js.map +1 -1
  14. package/dist/modifiers/autodate.d.ts +2 -2
  15. package/dist/modifiers/autodate.js.map +1 -1
  16. package/dist/modifiers/common.d.ts +37 -20
  17. package/dist/modifiers/common.js +81 -68
  18. package/dist/modifiers/common.js.map +1 -1
  19. package/dist/modifiers/encryption.js +26 -14
  20. package/dist/modifiers/encryption.js.map +1 -1
  21. package/dist/modifiers/hash.d.ts +46 -4
  22. package/dist/modifiers/hash.js +175 -14
  23. package/dist/modifiers/hash.js.map +1 -1
  24. package/dist/modifiers/internal/kinds.d.ts +15 -1
  25. package/dist/modifiers/internal/kinds.js +35 -0
  26. package/dist/modifiers/internal/kinds.js.map +1 -1
  27. package/dist/modifiers/internal/records.d.ts +40 -5
  28. package/dist/modifiers/internal/records.js +70 -1
  29. package/dist/modifiers/internal/records.js.map +1 -1
  30. package/dist/modifiers/localization.js +12 -7
  31. package/dist/modifiers/localization.js.map +1 -1
  32. package/dist/relation.d.ts +5 -0
  33. package/dist/relation.js +11 -0
  34. package/dist/relation.js.map +1 -1
  35. package/dist/schema.js +5 -6
  36. package/dist/schema.js.map +1 -1
  37. package/dist/table.d.ts +3 -2
  38. package/dist/table.js +29 -13
  39. package/dist/table.js.map +1 -1
  40. package/dist/tests/cross_instance.test.js +5 -2
  41. package/dist/tests/cross_instance.test.js.map +1 -1
  42. package/dist/tests/database.test.js +42 -2
  43. package/dist/tests/database.test.js.map +1 -1
  44. package/dist/tests/hash_upgrade.test.d.ts +1 -0
  45. package/dist/tests/hash_upgrade.test.js +132 -0
  46. package/dist/tests/hash_upgrade.test.js.map +1 -0
  47. package/dist/tests/helpers/hash-rows.d.ts +40 -0
  48. package/dist/tests/helpers/hash-rows.js +41 -0
  49. package/dist/tests/helpers/hash-rows.js.map +1 -0
  50. package/dist/tests/helpers/other-instance.js.map +1 -1
  51. package/dist/tests/integration.test.js +15 -4
  52. package/dist/tests/integration.test.js.map +1 -1
  53. package/dist/tests/metadata_inheritance.test.d.ts +1 -0
  54. package/dist/tests/metadata_inheritance.test.js +212 -0
  55. package/dist/tests/metadata_inheritance.test.js.map +1 -0
  56. package/dist/tests/modifiers/encryption_date_marker.test.d.ts +1 -0
  57. package/dist/tests/modifiers/encryption_date_marker.test.js +78 -0
  58. package/dist/tests/modifiers/encryption_date_marker.test.js.map +1 -0
  59. package/dist/tests/modifiers/hash.test.js +295 -0
  60. package/dist/tests/modifiers/hash.test.js.map +1 -1
  61. package/dist/tests/modifiers/inherited_names.test.d.ts +1 -0
  62. package/dist/tests/modifiers/inherited_names.test.js +96 -0
  63. package/dist/tests/modifiers/inherited_names.test.js.map +1 -0
  64. package/dist/tests/own_key_lookups.test.d.ts +1 -0
  65. package/dist/tests/own_key_lookups.test.js +49 -0
  66. package/dist/tests/own_key_lookups.test.js.map +1 -0
  67. package/dist/tests/partial_update.test.d.ts +1 -0
  68. package/dist/tests/partial_update.test.js +55 -0
  69. package/dist/tests/partial_update.test.js.map +1 -0
  70. package/dist/tests/row_forms.test.d.ts +1 -0
  71. package/dist/tests/row_forms.test.js +59 -0
  72. package/dist/tests/row_forms.test.js.map +1 -0
  73. package/dist/tests/stored_metadata.test.d.ts +1 -0
  74. package/dist/tests/stored_metadata.test.js +91 -0
  75. package/dist/tests/stored_metadata.test.js.map +1 -0
  76. package/dist/tests/subclass_schema_binding.test.d.ts +1 -0
  77. package/dist/tests/subclass_schema_binding.test.js +115 -0
  78. package/dist/tests/subclass_schema_binding.test.js.map +1 -0
  79. package/dist/tests/table.test.js +16 -0
  80. package/dist/tests/table.test.js.map +1 -1
  81. package/docs/1.introduction.md +24 -20
  82. package/docs/2.table-definitions.md +63 -41
  83. package/docs/3.table-modifiers.md +128 -98
  84. package/docs/4.data-models.md +63 -52
  85. package/docs/5.parameter-decoration.md +28 -24
  86. package/docs/tsconfig.json +3 -0
  87. package/package.json +10 -9
  88. package/skills/database-decorators-interface/SKILL.md +6 -3
@@ -4,31 +4,169 @@ exports.Hashed = exports.HashModifier = void 0;
4
4
  const randomstring_1 = require("randomstring");
5
5
  const node_crypto_1 = require("node:crypto");
6
6
  const decorators_1 = require("@antelopejs/interface-core/decorators");
7
- const common_1 = require("./common");
7
+ const common_1 = require("../common");
8
+ const common_2 = require("./common");
9
+ const records_1 = require("./internal/records");
10
+ const kinds_1 = require("./internal/kinds");
11
+ const SCRYPT_COST = { ln: 15, r: 8, p: 3 };
12
+ const SALT_BYTES = 16;
13
+ const KEY_BYTES = 32;
14
+ const DECOY_SALT = Buffer.alloc(SALT_BYTES);
15
+ const LEGACY_DIGEST = "sha256";
16
+ /** Most scrypt memory (128 * N * r bytes) a stored hash may ask for. */
17
+ const STORED_MAX_MEMORY = 128 * 1024 * 1024;
18
+ const STORED_MAX_P = 16;
19
+ const CURRENT_PREFIX = `$scrypt$ln=${SCRYPT_COST.ln},r=${SCRYPT_COST.r},p=${SCRYPT_COST.p}$`;
20
+ /** Salt and key take 22 to 86 characters, so 16 to 64 bytes. */
21
+ const STORED_SCRYPT = /^\$scrypt\$ln=([1-9]\d?),r=([1-9]\d?),p=([1-9]\d?)\$([A-Za-z0-9+/]{22,86})\$([A-Za-z0-9+/]{22,86})$/;
22
+ function unpaddedBase64(bytes) {
23
+ return bytes.toString("base64").replace(/=+$/, "");
24
+ }
25
+ function scryptArgs(password, salt, keylen, { ln, r, p }) {
26
+ return [
27
+ password,
28
+ salt,
29
+ keylen,
30
+ { N: 2 ** ln, r, p, maxmem: 2 * STORED_MAX_MEMORY },
31
+ ];
32
+ }
33
+ function scryptAsync(...[password, salt, keylen, options]) {
34
+ return new Promise((resolve, reject) => {
35
+ (0, node_crypto_1.scrypt)(password, salt, keylen, options, (error, key) => {
36
+ if (error)
37
+ reject(error);
38
+ else
39
+ resolve(key);
40
+ });
41
+ });
42
+ }
43
+ function parseScrypt(stored) {
44
+ const match = STORED_SCRYPT.exec(stored);
45
+ if (!match)
46
+ return undefined;
47
+ const cost = {
48
+ ln: Number(match[1]),
49
+ r: Number(match[2]),
50
+ p: Number(match[3]),
51
+ };
52
+ if (128 * cost.r * 2 ** cost.ln > STORED_MAX_MEMORY ||
53
+ cost.p > STORED_MAX_P ||
54
+ cost.ln >= 16 * cost.r) {
55
+ return undefined;
56
+ }
57
+ return {
58
+ cost,
59
+ salt: Buffer.from(match[4], "base64"),
60
+ key: Buffer.from(match[5], "base64"),
61
+ };
62
+ }
63
+ function digestOf(algorithm, salt, candidate) {
64
+ return (0, node_crypto_1.createHash)(algorithm).update(salt).update(candidate).digest("base64");
65
+ }
66
+ function digestMatches(stored, salt, algorithm, candidate) {
67
+ if (!salt || candidate === undefined)
68
+ return false;
69
+ const expected = Buffer.from(stored);
70
+ const actual = Buffer.from(digestOf(algorithm, salt, candidate));
71
+ return expected.length === actual.length && (0, node_crypto_1.timingSafeEqual)(expected, actual);
72
+ }
73
+ /**
74
+ * Plans the test of a candidate from what the row holds. A field that uses
75
+ * scrypt spends one scrypt run in every case, so the time of a refusal does not
76
+ * tell a missing or an older hash from a current one.
77
+ */
78
+ function planCheck(row, algorithm, candidate) {
79
+ const hash = parseScrypt(row.stored);
80
+ if (hash && candidate !== undefined) {
81
+ return {
82
+ run: scryptArgs(candidate, hash.salt, hash.key.length, hash.cost),
83
+ verdict: (derived) => derived !== undefined && (0, node_crypto_1.timingSafeEqual)(derived, hash.key),
84
+ };
85
+ }
86
+ const matches = digestMatches(row.stored, row.salt, algorithm ?? LEGACY_DIGEST, candidate);
87
+ return {
88
+ run: algorithm
89
+ ? undefined
90
+ : scryptArgs(candidate ?? "", DECOY_SALT, KEY_BYTES, SCRYPT_COST),
91
+ verdict: () => matches,
92
+ };
93
+ }
94
+ /** A row stores a string or nothing. Anything else cannot match a candidate. */
95
+ function storedText(stored) {
96
+ return String(stored ?? "");
97
+ }
98
+ function withHashedField(row, field, use) {
99
+ const metaTable = (0, common_1.getMetadata)(row.constructor, common_2.ModifiersStaticMetadata);
100
+ const entry = (0, records_1.fieldsByKey)(metaTable)[field]?.find(({ modifier }) => modifier instanceof HashModifier);
101
+ if (!entry || !(entry.modifier instanceof HashModifier)) {
102
+ throw new Error(`Field ${String(field)} is not hashed`);
103
+ }
104
+ const internal = (0, records_1.getInternal)(row);
105
+ const stored = (0, records_1.dataByKey)(internal)[field];
106
+ return (0, records_1.withRef)(internal, entry.id, entry.modifier, entry.metaRef, (modifier) => use(modifier, (0, kinds_1.isString)(stored) ? stored : ""));
107
+ }
8
108
  /**
9
109
  * Hash modifier. enables the use of {@link Hashed} on table fields.
10
110
  *
11
- * Hashed fields only contain a hash of the inserted value.
111
+ * Hashed fields only contain a hash of the inserted value, by default a scrypt
112
+ * hash in the self-describing form `$scrypt$ln=15,r=8,p=3$<salt>$<key>`.
12
113
  * Because of this, you lose the ability to query the information directly.
13
114
  * You can test equality using {@link testHash}
14
115
  */
15
- class HashModifier extends common_1.OneWayModifier {
116
+ class HashModifier extends common_2.OneWayModifier {
16
117
  autolock = true;
17
- lock(_locked_value, value) {
118
+ /**
119
+ * Hashes a new value. Assigning the stored hash back keeps it as it is.
120
+ * Blocks the event loop for one scrypt run: a setter and the conversions
121
+ * behind `insert` and `update` are synchronous.
122
+ */
123
+ // oxlint-disable-next-line anti-slop/no-unknown-parameters -- overrides OneWayModifier.lock; a modified field's value has its table class's type, which the shared modifier chain cannot name
124
+ lock(locked_value, value) {
18
125
  if (value === undefined) {
19
126
  return value;
20
127
  }
21
- if (!this.meta.salt) {
22
- this.meta.salt = (0, randomstring_1.generate)();
128
+ if (value === locked_value) {
129
+ return locked_value;
130
+ }
131
+ const candidate = JSON.stringify(value);
132
+ const { algorithm } = this.options;
133
+ if (algorithm) {
134
+ if (!this.meta.salt) {
135
+ this.meta.salt = (0, randomstring_1.generate)();
136
+ }
137
+ return digestOf(algorithm, this.meta.salt, candidate);
23
138
  }
24
- return (0, node_crypto_1.createHash)(this.options.algorithm || "sha256")
25
- .update(this.meta.salt)
26
- .update(JSON.stringify(value))
27
- .digest("base64");
139
+ const salt = (0, node_crypto_1.randomBytes)(SALT_BYTES);
140
+ const key = (0, node_crypto_1.scryptSync)(...scryptArgs(candidate, salt, KEY_BYTES, SCRYPT_COST));
141
+ return `${CURRENT_PREFIX}${unpaddedBase64(salt)}$${unpaddedBase64(key)}`;
28
142
  }
29
- [common_1.MixinSymbol] = class {
143
+ test(locked_value, value) {
144
+ const check = this.plan(storedText(locked_value), value);
145
+ return check.verdict(check.run && (0, node_crypto_1.scryptSync)(...check.run));
146
+ }
147
+ /** {@link test} on the thread pool, without blocking the event loop. */
148
+ async testAsync(locked_value, value) {
149
+ const check = this.plan(locked_value, value);
150
+ return check.verdict(check.run && (await scryptAsync(...check.run)));
151
+ }
152
+ /**
153
+ * @returns Whether a stored hash differs from what this field writes today. A
154
+ * field with an explicit `algorithm` never reports one: hashing again would
155
+ * give the same digest, or weaken a scrypt hash.
156
+ */
157
+ isOutdated(locked_value) {
158
+ return (!this.options.algorithm &&
159
+ locked_value !== "" &&
160
+ !locked_value.startsWith(CURRENT_PREFIX));
161
+ }
162
+ /** Reads the salt now: `this.meta` is bound to a row only synchronously. */
163
+ plan(locked_value, value) {
164
+ return planCheck({ stored: locked_value, salt: this.meta.salt }, this.options.algorithm, value === undefined ? undefined : JSON.stringify(value));
165
+ }
166
+ [common_2.MixinSymbol] = class {
30
167
  /**
31
- * Test a value against the stored hash.
168
+ * Test a value against the stored hash. Blocks the event loop for one
169
+ * scrypt run: on a server, prefer {@link testHashAsync}.
32
170
  *
33
171
  * @param field - Name of the field to test against.
34
172
  * @param value - Value to hash and test.
@@ -36,7 +174,30 @@ class HashModifier extends common_1.OneWayModifier {
36
174
  * @returns Whether the new value is identical to the original or not.
37
175
  */
38
176
  testHash(field, value) {
39
- return (0, common_1.testValue)(this, field, value);
177
+ return (0, common_2.testValue)(this, field, value);
178
+ }
179
+ /**
180
+ * Test a value against the stored hash on the thread pool.
181
+ *
182
+ * @param field - Name of the field to test against.
183
+ * @param value - Value to hash and test.
184
+ *
185
+ * @returns Whether the new value is identical to the original or not.
186
+ */
187
+ async testHashAsync(field, value) {
188
+ return withHashedField(this, field, (modifier, stored) => modifier.testAsync(stored, value));
189
+ }
190
+ /**
191
+ * Tell whether a stored hash needs writing again: it uses an older format
192
+ * or cost. After a successful test, assign the tested value to the field
193
+ * and save the row.
194
+ *
195
+ * @param field - Name of the field to inspect.
196
+ *
197
+ * @returns Whether the stored hash is outdated. False when nothing is stored.
198
+ */
199
+ isHashOutdated(field) {
200
+ return withHashedField(this, field, (modifier, stored) => modifier.isOutdated(stored));
40
201
  }
41
202
  };
42
203
  }
@@ -49,6 +210,6 @@ exports.HashModifier = HashModifier;
49
210
  * @param options Hash options.
50
211
  */
51
212
  exports.Hashed = (0, decorators_1.MakePropertyDecorator)((target, propertyKey, options) => {
52
- (0, common_1.attachModifier)(target.constructor, HashModifier, propertyKey, options || {});
213
+ (0, common_2.attachModifier)(target.constructor, HashModifier, propertyKey, options || {});
53
214
  });
54
215
  //# sourceMappingURL=hash.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/modifiers/hash.ts"],"names":[],"mappings":";;;AAAA,+CAAwC;AACxC,6CAAyC;AACzC,sEAA8E;AAE9E,qCAKkB;AAOlB;;;;;;GAMG;AACH,MAAa,YAAa,SAAQ,uBAKjC;IACiB,QAAQ,GAAG,IAAI,CAAC;IAEhB,IAAI,CAAC,aAAiC,EAAE,KAAc;QACpE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAA,uBAAQ,GAAE,CAAC;QAC9B,CAAC;QACD,OAAO,IAAA,wBAAU,EAAC,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,QAAQ,CAAC;aAClD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;aACtB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;aAC7B,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;IAED,CAAC,oBAAW,CAAC,GAAG;QACd;;;;;;;WAOG;QACH,QAAQ,CAEN,KAAQ,EACR,KAAc;YAEd,OAAO,IAAA,kBAAS,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;KACF,CAAC;CACH;AAtCD,oCAsCC;AAED;;;;;;GAMG;AACU,QAAA,MAAM,GAAG,IAAA,kCAAqB,EACzC,CAAC,MAAM,EAAE,WAAW,EAAE,OAAiB,EAAE,EAAE;IACzC,IAAA,uBAAc,EACZ,MAAM,CAAC,WAAW,EAClB,YAAY,EACZ,WAAW,EACX,OAAO,IAAI,EAAE,CACd,CAAC;AACJ,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/modifiers/hash.ts"],"names":[],"mappings":";;;AAAA,+CAAwC;AACxC,6CAOqB;AACrB,sEAA8E;AAE9E,sCAAwC;AACxC,qCAMkB;AAClB,gDAK4B;AAC5B,4CAA4C;AA4B5C,MAAM,WAAW,GAAe,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACvD,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC;AAE/B,wEAAwE;AACxE,MAAM,iBAAiB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,cAAc,GAAG,cAAc,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC,CAAC,MAAM,WAAW,CAAC,CAAC,GAAG,CAAC;AAE7F,gEAAgE;AAChE,MAAM,aAAa,GACjB,qGAAqG,CAAC;AAExG,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,UAAU,CACjB,QAAgB,EAChB,IAAY,EACZ,MAAc,EACd,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAc;IAExB,OAAO;QACL,QAAQ;QACR,IAAI;QACJ,MAAM;QACN,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,iBAAiB,EAAE;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAa;IACnE,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,IAAA,oBAAM,EAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACrD,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;gBACpB,OAAO,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACpB,CAAC;IACF,IACE,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,iBAAiB;QAC/C,IAAI,CAAC,CAAC,GAAG,YAAY;QACrB,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,EACtB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;QACrC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,SAAiB,EAAE,IAAY,EAAE,SAAiB;IAClE,OAAO,IAAA,wBAAU,EAAC,SAAS,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,aAAa,CACpB,MAAc,EACd,IAAwB,EACxB,SAAiB,EACjB,SAA6B;IAE7B,IAAI,CAAC,IAAI,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IACjE,OAAO,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,IAAA,6BAAe,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAChB,GAAiD,EACjD,SAA6B,EAC7B,SAA6B;IAE7B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;YACL,GAAG,EAAE,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC;YACjE,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CACnB,OAAO,KAAK,SAAS,IAAI,IAAA,6BAAe,EAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC;SAC9D,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAC3B,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,IAAI,EACR,SAAS,IAAI,aAAa,EAC1B,SAAS,CACV,CAAC;IACF,OAAO;QACL,GAAG,EAAE,SAAS;YACZ,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,UAAU,CAAC,SAAS,IAAI,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC;QACnE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,SAAS,UAAU,CAAC,MAA0B;IAC5C,OAAO,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,eAAe,CACtB,GAAyB,EACzB,KAAkB,EAClB,GAAkD;IAElD,MAAM,SAAS,GAAG,IAAA,oBAAW,EAAC,GAAG,CAAC,WAAW,EAAE,gCAAuB,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,IAAA,qBAAW,EAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,CAC/C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,YAAY,YAAY,CACnD,CAAC;IACF,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,YAAY,YAAY,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,QAAQ,GAAG,IAAA,qBAAW,EAAC,GAAG,CAAC,CAAC;IAClC,MAAM,MAAM,GAAY,IAAA,mBAAS,EAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;IACnD,OAAO,IAAA,iBAAO,EACZ,QAAQ,EACR,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,OAAO,EACb,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAA,gBAAQ,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAC5D,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAa,YAAa,SAAQ,uBAKjC;IACiB,QAAQ,GAAG,IAAI,CAAC;IAEhC;;;;OAIG;IACH,8LAA8L;IAC9K,IAAI,CAAC,YAAgC,EAAE,KAAc;QACnE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACpB,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAA,uBAAQ,GAAE,CAAC;YAC9B,CAAC;YACD,OAAO,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,IAAA,yBAAW,EAAC,UAAU,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,IAAA,wBAAU,EACpB,GAAG,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CACvD,CAAC;QACF,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;IAC3E,CAAC;IAEe,IAAI,CAAC,YAAgC,EAAE,KAAgB;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,IAAA,wBAAU,EAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,wEAAwE;IACjE,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,KAAgB;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAC7C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,WAAW,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IAED;;;;OAIG;IACI,UAAU,CAAC,YAAoB;QACpC,OAAO,CACL,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS;YACvB,YAAY,KAAK,EAAE;YACnB,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc,CAAC,CACzC,CAAC;IACJ,CAAC;IAED,4EAA4E;IACpE,IAAI,CAAC,YAAoB,EAAE,KAAgB;QACjD,OAAO,SAAS,CACd,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAC9C,IAAI,CAAC,OAAO,CAAC,SAAS,EACtB,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CACxD,CAAC;IACJ,CAAC;IAED,CAAC,oBAAW,CAAC,GAAG;QACd;;;;;;;;WAQG;QACH,QAAQ,CAEN,KAAQ,EACR,KAAc;YAEd,OAAO,IAAA,kBAAS,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;QAED;;;;;;;WAOG;QACH,KAAK,CAAC,aAAa,CAEjB,KAAQ,EACR,KAAc;YAEd,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CACvD,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAClC,CAAC;QACJ,CAAC;QAED;;;;;;;;WAQG;QACH,cAAc,CAA8B,KAAiB;YAC3D,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CACvD,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAC5B,CAAC;QACJ,CAAC;KACF,CAAC;CACH;AAxHD,oCAwHC;AAED;;;;;;GAMG;AACU,QAAA,MAAM,GAAG,IAAA,kCAAqB,EACzC,CAAC,MAAM,EAAE,WAAW,EAAE,OAAiB,EAAE,EAAE;IACzC,IAAA,uBAAc,EACZ,MAAM,CAAC,WAAW,EAClB,YAAY,EACZ,WAAW,EACX,OAAO,IAAI,EAAE,CACd,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -1,5 +1,6 @@
1
1
  /** @internal @packageDocumentation */
2
- import type { Modifier, OneWayModifier, TwoWayModifier } from "../common";
2
+ import type { Constructible } from "../../common";
3
+ import type { Modifier, ModifierEvent, OneWayModifier, TwoWayModifier } from "../common";
3
4
  export declare function isWriteOnly(m: Modifier): m is OneWayModifier<unknown, any[]>;
4
5
  export declare function isLocking(m: Modifier): m is OneWayModifier<unknown, any[]>;
5
6
  export declare function isTwoWay(m: Modifier): m is TwoWayModifier<unknown, any[]>;
@@ -10,3 +11,16 @@ export declare const ignoredEventNames: {
10
11
  unlock: boolean;
11
12
  };
12
13
  export declare function isCallable(value: unknown): value is CallableFunction;
14
+ /**
15
+ * Whether a modifier prototype member is a method the engine can run for an
16
+ * event: any function takes the instance, the field and the event arguments.
17
+ */
18
+ export declare function isEventHandler(value: unknown): value is ModifierEvent;
19
+ export declare function isString(value: unknown): value is string;
20
+ /** Whether a value is an object or a function: what a prototype chain holds. */
21
+ export declare function isObjectLike(value: unknown): value is object;
22
+ /** The object the instances of a class inherit from. */
23
+ export declare function prototypeOf(target: Constructible): object;
24
+ /** Whether `candidate` is the class `base` or a class extending it. */
25
+ export declare function isSameOrSubclass<Base extends Constructible>(candidate: Constructible, base: Base): candidate is Base;
26
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
@@ -6,6 +6,12 @@ exports.isLocking = isLocking;
6
6
  exports.isTwoWay = isTwoWay;
7
7
  exports.isOnlyEvents = isOnlyEvents;
8
8
  exports.isCallable = isCallable;
9
+ exports.isEventHandler = isEventHandler;
10
+ exports.isString = isString;
11
+ exports.isObjectLike = isObjectLike;
12
+ exports.prototypeOf = prototypeOf;
13
+ exports.isSameOrSubclass = isSameOrSubclass;
14
+ exports.isRecord = isRecord;
9
15
  function isWriteOnly(m) {
10
16
  return "lock" in m && !("unlock" in m);
11
17
  }
@@ -26,4 +32,33 @@ exports.ignoredEventNames = {
26
32
  function isCallable(value) {
27
33
  return typeof value === "function";
28
34
  }
35
+ /**
36
+ * Whether a modifier prototype member is a method the engine can run for an
37
+ * event: any function takes the instance, the field and the event arguments.
38
+ */
39
+ function isEventHandler(value) {
40
+ return typeof value === "function";
41
+ }
42
+ function isString(value) {
43
+ return typeof value === "string";
44
+ }
45
+ /** Whether a value is an object or a function: what a prototype chain holds. */
46
+ function isObjectLike(value) {
47
+ return ((typeof value === "object" || typeof value === "function") && value !== null);
48
+ }
49
+ /** The object the instances of a class inherit from. */
50
+ function prototypeOf(target) {
51
+ const prototype = target.prototype;
52
+ if (!isObjectLike(prototype)) {
53
+ throw new TypeError("A class prototype must be an object.");
54
+ }
55
+ return prototype;
56
+ }
57
+ /** Whether `candidate` is the class `base` or a class extending it. */
58
+ function isSameOrSubclass(candidate, base) {
59
+ return candidate === base || base.isPrototypeOf(candidate);
60
+ }
61
+ function isRecord(value) {
62
+ return typeof value === "object" && value !== null;
63
+ }
29
64
  //# sourceMappingURL=kinds.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../../src/modifiers/internal/kinds.ts"],"names":[],"mappings":";;;AAGA,kCAEC;AAED,8BAEC;AAED,4BAEC;AAED,oCAEC;AAQD,gCAEC;AAxBD,SAAgB,WAAW,CAAC,CAAW;IACrC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,SAAS,CAAC,CAAW;IACnC,OAAO,MAAM,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAW;IAClC,OAAO,QAAQ,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,SAAgB,YAAY,CAAC,QAAkB;IAC7C,OAAO,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAEY,QAAA,iBAAiB,GAAG;IAC/B,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;CACb,CAAC;AAEF,SAAgB,UAAU,CAAC,KAAc;IACvC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../../src/modifiers/internal/kinds.ts"],"names":[],"mappings":";;;AASA,kCAEC;AAED,8BAEC;AAED,4BAEC;AAED,oCAEC;AAQD,gCAEC;AAMD,wCAEC;AAED,4BAEC;AAGD,oCAIC;AAGD,kCAMC;AAGD,4CAKC;AAED,4BAEC;AAhED,SAAgB,WAAW,CAAC,CAAW;IACrC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,SAAS,CAAC,CAAW;IACnC,OAAO,MAAM,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAW;IAClC,OAAO,QAAQ,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,SAAgB,YAAY,CAAC,QAAkB;IAC7C,OAAO,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAEY,QAAA,iBAAiB,GAAG;IAC/B,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;CACb,CAAC;AAEF,SAAgB,UAAU,CAAC,KAAc;IACvC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC;AACnC,CAAC;AAED,gFAAgF;AAChF,SAAgB,YAAY,CAAC,KAAc;IACzC,OAAO,CACL,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,CAAC,IAAI,KAAK,KAAK,IAAI,CAC7E,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,SAAgB,WAAW,CAAC,MAAqB;IAC/C,MAAM,SAAS,GAAY,MAAM,CAAC,SAAS,CAAC;IAC5C,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uEAAuE;AACvE,SAAgB,gBAAgB,CAC9B,SAAwB,EACxB,IAAU;IAEV,OAAO,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;AAC7D,CAAC;AAED,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}
@@ -1,20 +1,51 @@
1
1
  /** @internal @packageDocumentation */
2
- import type { DatumStaticMetadata } from "../../common";
3
- import type { Modifier, ModifiersDynamicMetadata, ModifiersStaticMetadata } from "../common";
2
+ import type { Constructible, DatumStaticMetadata } from "../../common";
3
+ import type { Modifier, ModifierEvent, ModifiersDynamicMetadata, ModifiersStaticMetadata } from "../common";
4
4
  type ModifiedFieldList = ModifiersStaticMetadata["fields"][string];
5
5
  type ModifiedField = ModifiedFieldList[number];
6
- type InternalRecord = Parameters<ModifiersDynamicMetadata["get"]>[1];
6
+ /** What a modifier keeps for a field of a stored row, beside the locked value. */
7
+ export type ModifierState = {
8
+ [key: PropertyKey]: unknown;
9
+ };
10
+ /**
11
+ * Where a row holds its modified fields: the locked values by field name, and
12
+ * each modifier's state by modifier name. What the values hold is known to the
13
+ * modifiers that wrote them, not to the row.
14
+ */
15
+ export interface InternalRecord {
16
+ meta: Record<string, ModifierState>;
17
+ data: {
18
+ [field: PropertyKey]: unknown;
19
+ };
20
+ }
21
+ export interface InternalHolder {
22
+ constructor: any;
23
+ _internal?: InternalRecord;
24
+ }
25
+ /** The modifier state of a table instance, created on first use. */
26
+ export declare function getInternal(object: InternalHolder): InternalRecord;
27
+ /** Whether a row's modifier state holds no locked value and no modifier state. */
28
+ export declare function isEmptyInternal({ meta, data }: InternalRecord): boolean;
29
+ /**
30
+ * Throws when a modifier cannot be attached to the field named `field`: the
31
+ * two names the table's own structures live under.
32
+ */
33
+ export declare function assertModifiableField(tableName: string, modifierId: string, field: PropertyKey): void;
7
34
  export declare function fieldsByKey(meta: ModifiersStaticMetadata): {
8
35
  [field: PropertyKey]: ModifiedFieldList;
9
36
  };
10
- export declare function eventsByKey(meta: ModifiersStaticMetadata): Map<string, Array<[field: PropertyKey, modified: ModifiedFieldList[number]]>>;
37
+ export declare function eventsByKey(meta: ModifiersStaticMetadata): Map<string, Array<[
38
+ field: PropertyKey,
39
+ modified: ModifiedFieldList[number],
40
+ handler: ModifierEvent
41
+ ]>>;
11
42
  export declare function unlockArgsOf(meta: ModifiersDynamicMetadata, field: PropertyKey): ModifiersDynamicMetadata["fields"][string];
12
43
  export declare function fieldTypesByKey(meta: DatumStaticMetadata): {
13
44
  [field: PropertyKey]: DatumStaticMetadata["fields"][string];
14
45
  };
15
46
  export declare function floatingOf<V>(meta: {
16
47
  floating: Record<string, V>;
17
- }, field: PropertyKey): V;
48
+ }, field: PropertyKey): V | undefined;
18
49
  export declare function floatingByKey<V>(meta: {
19
50
  floating: Record<string, V>;
20
51
  }): {
@@ -25,5 +56,9 @@ export declare function dataByKey<V>(internal: {
25
56
  }): {
26
57
  [field: PropertyKey]: V;
27
58
  };
59
+ /** A field entry for a new `Modifier`, whose `meta` reads and writes the record its `metaRef` points at. */
60
+ export declare function newModifiedField(Modifier: Constructible<Modifier>): ModifiedField;
28
61
  export declare function withRef<T extends Modifier, U>(internal: InternalRecord, id: ModifiedField["id"], modifier: T, metaRef: ModifiedField["metaRef"], callback: (modifier: T) => U): U;
62
+ /** Fills `copy` with the modified fields and events of `parent`, every list copied. */
63
+ export declare function copyModifierLists(copy: ModifiersStaticMetadata, parent: ModifiersStaticMetadata): ModifiersStaticMetadata;
29
64
  export {};
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getInternal = getInternal;
4
+ exports.isEmptyInternal = isEmptyInternal;
5
+ exports.assertModifiableField = assertModifiableField;
3
6
  exports.fieldsByKey = fieldsByKey;
4
7
  exports.eventsByKey = eventsByKey;
5
8
  exports.unlockArgsOf = unlockArgsOf;
@@ -7,7 +10,37 @@ exports.fieldTypesByKey = fieldTypesByKey;
7
10
  exports.floatingOf = floatingOf;
8
11
  exports.floatingByKey = floatingByKey;
9
12
  exports.dataByKey = dataByKey;
13
+ exports.newModifiedField = newModifiedField;
10
14
  exports.withRef = withRef;
15
+ exports.copyModifierLists = copyModifierLists;
16
+ /** The modifier state of a table instance, created on first use. */
17
+ function getInternal(object) {
18
+ if (!object._internal) {
19
+ object._internal = {
20
+ meta: {},
21
+ data: {},
22
+ };
23
+ }
24
+ return object._internal;
25
+ }
26
+ /** Whether a row's modifier state holds no locked value and no modifier state. */
27
+ function isEmptyInternal({ meta, data }) {
28
+ return Object.keys(meta).length === 0 && Object.keys(data).length === 0;
29
+ }
30
+ /**
31
+ * Throws when a modifier cannot be attached to the field named `field`: the
32
+ * two names the table's own structures live under.
33
+ */
34
+ function assertModifiableField(tableName, modifierId, field) {
35
+ const reason = field === "constructor"
36
+ ? "the field would replace the class constructor that locates the metadata of every instance"
37
+ : field === "__proto__"
38
+ ? "the field would replace the prototype of the record of modified fields and never be recorded"
39
+ : undefined;
40
+ if (reason) {
41
+ throw new Error(`Cannot add Modifier ${modifierId} on ${tableName}.${String(field)}: ${reason}.`);
42
+ }
43
+ }
11
44
  function fieldsByKey(meta) {
12
45
  return meta.fields;
13
46
  }
@@ -16,6 +49,9 @@ function eventsByKey(meta) {
16
49
  }
17
50
  function unlockArgsOf(meta, field) {
18
51
  const byKey = meta.fields;
52
+ if (!Object.hasOwn(byKey, field)) {
53
+ throw new TypeError(`${String(field)} holds no modifier arguments`);
54
+ }
19
55
  return byKey[field];
20
56
  }
21
57
  function fieldTypesByKey(meta) {
@@ -23,7 +59,7 @@ function fieldTypesByKey(meta) {
23
59
  }
24
60
  function floatingOf(meta, field) {
25
61
  const byKey = meta.floating;
26
- return byKey[field];
62
+ return Object.hasOwn(byKey, field) ? byKey[field] : undefined;
27
63
  }
28
64
  function floatingByKey(meta) {
29
65
  return meta.floating;
@@ -31,6 +67,29 @@ function floatingByKey(meta) {
31
67
  function dataByKey(internal) {
32
68
  return internal.data;
33
69
  }
70
+ /** A field entry for a new `Modifier`, whose `meta` reads and writes the record its `metaRef` points at. */
71
+ function newModifiedField(Modifier) {
72
+ const entry = {
73
+ id: Modifier.name,
74
+ modifier: new Modifier(),
75
+ metaRef: { _ref: {} },
76
+ };
77
+ Object.assign(entry.modifier, {
78
+ meta: new Proxy(entry.metaRef, {
79
+ get: (self, p) => {
80
+ if (!self._ref)
81
+ return undefined;
82
+ return self._ref[p];
83
+ },
84
+ set: (self, p, v) => {
85
+ if (!self._ref)
86
+ self._ref = {};
87
+ return Reflect.set(self._ref, p, v, self._ref);
88
+ },
89
+ }),
90
+ });
91
+ return entry;
92
+ }
34
93
  function withRef(internal, id, modifier, metaRef, callback) {
35
94
  metaRef._ref = internal.meta[id];
36
95
  const ret = callback(modifier);
@@ -39,4 +98,14 @@ function withRef(internal, id, modifier, metaRef, callback) {
39
98
  }
40
99
  return ret;
41
100
  }
101
+ /** The entries of a record or map with every list copied, not shared. */
102
+ function listsCopied(entries) {
103
+ return Array.from(entries, ([key, list]) => [key, [...list]]);
104
+ }
105
+ /** Fills `copy` with the modified fields and events of `parent`, every list copied. */
106
+ function copyModifierLists(copy, parent) {
107
+ copy.fields = Object.fromEntries(listsCopied(Object.entries(parent.fields)));
108
+ copy.events = new Map(listsCopied(parent.events));
109
+ return copy;
110
+ }
42
111
  //# sourceMappingURL=records.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"records.js","sourceRoot":"","sources":["../../../src/modifiers/internal/records.ts"],"names":[],"mappings":";;AAYA,kCAIC;AAED,kCAOC;AAED,oCAQC;AAED,0CAIC;AAED,gCAMC;AAED,sCAIC;AAED,8BAIC;AAED,0BAaC;AAhED,SAAgB,WAAW,CAAC,IAA6B;IAGvD,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,SAAgB,WAAW,CACzB,IAA6B;IAK7B,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,SAAgB,YAAY,CAC1B,IAA8B,EAC9B,KAAkB;IAElB,MAAM,KAAK,GAEP,IAAI,CAAC,MAAM,CAAC;IAChB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;AACtB,CAAC;AAED,SAAgB,eAAe,CAAC,IAAyB;IAGvD,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,SAAgB,UAAU,CACxB,IAAqC,EACrC,KAAkB;IAElB,MAAM,KAAK,GAAgC,IAAI,CAAC,QAAQ,CAAC;IACzD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;AACtB,CAAC;AAED,SAAgB,aAAa,CAAI,IAAqC;IAGpE,OAAO,IAAI,CAAC,QAAQ,CAAC;AACvB,CAAC;AAED,SAAgB,SAAS,CAAI,QAAqC;IAGhE,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC;AAED,SAAgB,OAAO,CACrB,QAAwB,EACxB,EAAuB,EACvB,QAAW,EACX,OAAiC,EACjC,QAA4B;IAE5B,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../../src/modifiers/internal/records.ts"],"names":[],"mappings":"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"}
@@ -4,11 +4,9 @@ exports.Localized = exports.LocalizationModifier = void 0;
4
4
  const decorators_1 = require("@antelopejs/interface-core/decorators");
5
5
  const common_1 = require("../common");
6
6
  const common_2 = require("./common");
7
+ const kinds_1 = require("./internal/kinds");
7
8
  /** A text left empty in one language counts as no text in that language. */
8
9
  const EMPTY_TEXT = "";
9
- function isObject(value) {
10
- return typeof value === "object" && value !== null;
11
- }
12
10
  function withoutEmptyTexts(values) {
13
11
  return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== EMPTY_TEXT));
14
12
  }
@@ -40,14 +38,19 @@ class LocalizationModifier extends common_2.ContainerModifier {
40
38
  * Stores an empty text as no text, so that the fallback locale answers for
41
39
  * it in queries too (`unlockrequest`).
42
40
  */
43
- lock(locked_value, value, key) {
41
+ lock(
42
+ // oxlint-disable-next-line anti-slop/no-unsafe-dictionary-type -- the container modifier leaves the values by locale untyped
43
+ locked_value,
44
+ // oxlint-disable-next-line anti-slop/no-unknown-parameters -- overrides ContainerModifier.lock; a modified field's value has its table class's type, which the shared modifier chain cannot name
45
+ value, key) {
44
46
  if (key === "*") {
45
- return isObject(value)
47
+ return (0, kinds_1.isRecord)(value)
46
48
  ? withoutEmptyTexts(value)
47
- : value;
49
+ : super.lock(locked_value, value, key);
48
50
  }
49
51
  return withoutEmptyTexts(super.lock(locked_value, value, key));
50
52
  }
53
+ // oxlint-disable-next-line anti-slop/no-unsafe-dictionary-type -- the container modifier leaves the values by locale untyped
51
54
  unlock(locked_value, key) {
52
55
  const unlocked = super.unlock(locked_value, key);
53
56
  if (unlocked !== undefined && unlocked !== EMPTY_TEXT) {
@@ -57,7 +60,9 @@ class LocalizationModifier extends common_2.ContainerModifier {
57
60
  return super.unlock(locked_value, this.options.fallbackLocale);
58
61
  }
59
62
  }
60
- unlockrequest(data, _meta, key) {
63
+ unlockrequest(
64
+ // oxlint-disable-next-line anti-slop/no-unsafe-dictionary-type -- the container modifier leaves the values by locale untyped
65
+ data, _meta, key) {
61
66
  if (this.options.fallbackLocale) {
62
67
  return data.key(key).default(data.key(this.options.fallbackLocale));
63
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"localization.js","sourceRoot":"","sources":["../../src/modifiers/localization.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localization.js","sourceRoot":"","sources":["../../src/modifiers/localization.ts"],"names":[],"mappings":";;;AACA,sEAA8E;AAE9E,sCAA4D;AAC5D,qCAMkB;AAClB,4CAA4C;AAU5C,4EAA4E;AAC5E,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,SAAS,iBAAiB,CAAI,MAAyB;IACrD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,UAAU,CAAC,CACnE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAa,oBAAqB,SAAQ,0BAGzC;IACC;;;;;;;OAOG;IACI,MAAM,CAAC,gBAAgB,CAC5B,UAAyB,EACzB,KAAa;QAEb,MAAM,QAAQ,GAAG,IAAA,oBAAW,EAAC,UAAU,EAAE,gCAAuB,CAAC,CAAC,MAAM,CACtE,KAAK,CACN,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACtD,0QAA0Q;QAC1Q,OAAQ,QAAQ,EAAE,QAA6C,EAAE,OAAO;aACrE,cAAc,CAAC;IACpB,CAAC;IAED;;;OAGG;IACa,IAAI;IAClB,6HAA6H;IAC7H,YAAiD;IACjD,iMAAiM;IACjM,KAAc,EACd,GAAW;QAEX,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAChB,OAAO,IAAA,gBAAQ,EAAC,KAAK,CAAC;gBACpB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC;gBAC1B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,6HAA6H;IAC7G,MAAM,CAAC,YAAqC,EAAE,GAAW;QACvE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;YACtD,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAEe,aAAa;IAC3B,6HAA6H;IAC7H,IAAqD,EACrD,KAAoD,EACpD,GAA0C;QAE1C,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,CAAC,oBAAW,CAAC,GAAG;QACd;;;;;;;WAOG;QACH,QAAQ,CAEN,MAAc,EACd,MAA0B;YAE1B,IAAA,eAAM,EAAC,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;CACH;AApFD,oDAoFC;AAED;;;;;;GAMG;AACU,QAAA,SAAS,GAAG,IAAA,kCAAqB,EAC5C,CAAC,MAAM,EAAE,WAAW,EAAE,OAAiB,EAAE,EAAE;IACzC,IAAA,uBAAc,EACZ,MAAM,CAAC,WAAW,EAClB,oBAAoB,EACpB,WAAW,EACX,OAAO,IAAI,EAAE,CACd,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -23,6 +23,11 @@ export interface RelationOptions {
23
23
  */
24
24
  export declare class RelationStaticMetadata {
25
25
  static key: symbol;
26
+ /**
27
+ * The metadata of a subclass of a table: a copy of its parent's, so that
28
+ * relations declared on the subclass never reach the parent or its siblings.
29
+ */
30
+ static inherit(parent: RelationStaticMetadata): RelationStaticMetadata;
26
31
  readonly relations: Record<string, RelationOptions>;
27
32
  }
28
33
  /**
package/dist/relation.js CHANGED
@@ -8,6 +8,17 @@ const common_1 = require("./common");
8
8
  */
9
9
  class RelationStaticMetadata {
10
10
  static key = Symbol.for("@antelopejs/interface-database-decorators/RelationStaticMetadata@1");
11
+ /**
12
+ * The metadata of a subclass of a table: a copy of its parent's, so that
13
+ * relations declared on the subclass never reach the parent or its siblings.
14
+ */
15
+ static inherit(parent) {
16
+ const copy = new RelationStaticMetadata();
17
+ for (const [field, options] of Object.entries(parent.relations)) {
18
+ copy.relations[field] = options;
19
+ }
20
+ return copy;
21
+ }
11
22
  relations = {};
12
23
  }
13
24
  exports.RelationStaticMetadata = RelationStaticMetadata;
@@ -1 +1 @@
1
- {"version":3,"file":"relation.js","sourceRoot":"","sources":["../src/relation.ts"],"names":[],"mappings":";;;AAAA,sEAA8E;AAG9E,qCAAuC;AAsBvC;;GAEG;AACH,MAAa,sBAAsB;IAC1B,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAC5B,oEAAoE,CACrE,CAAC;IAEc,SAAS,GAAoC,EAAE,CAAC;;AALlE,wDAMC;AAED;;;;;;;;;;;;;GAaG;AACU,QAAA,QAAQ,GAAG,IAAA,kCAAqB,EAC3C,CAAC,MAAM,EAAE,WAAW,EAAE,OAAwB,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAG,IAAA,oBAAW,EAAC,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;IACzE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC;AACpD,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"relation.js","sourceRoot":"","sources":["../src/relation.ts"],"names":[],"mappings":";;;AAAA,sEAA8E;AAG9E,qCAAuC;AAsBvC;;GAEG;AACH,MAAa,sBAAsB;IAC1B,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAC5B,oEAAoE,CACrE,CAAC;IAEF;;;OAGG;IACI,MAAM,CAAC,OAAO,CACnB,MAA8B;QAE9B,MAAM,IAAI,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEe,SAAS,GAAoC,EAAE,CAAC;;AAnBlE,wDAoBC;AAED;;;;;;;;;;;;;GAaG;AACU,QAAA,QAAQ,GAAG,IAAA,kCAAqB,EAC3C,CAAC,MAAM,EAAE,WAAW,EAAE,OAAwB,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAG,IAAA,oBAAW,EAAC,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;IACzE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC;AACpD,CAAC,CACF,CAAC"}
package/dist/schema.js CHANGED
@@ -5,18 +5,17 @@ exports.getTablesForSchema = getTablesForSchema;
5
5
  const decorators_1 = require("@antelopejs/interface-core/decorators");
6
6
  const interface_database_1 = require("@antelopejs/interface-database");
7
7
  const common_1 = require("./common");
8
- const schemaTableRegistry = {};
8
+ const schemaTableRegistry = new Map();
9
9
  exports.RegisterTable = (0, decorators_1.MakeClassDecorator)((target, tableName, schemaName) => {
10
10
  const metadata = (0, common_1.getMetadata)(target, common_1.DatumStaticMetadata);
11
11
  metadata.tableName = tableName;
12
12
  metadata.schemaName = schemaName;
13
13
  metadata.schema = interface_database_1.Schema.get(schemaName);
14
- if (!(schemaName in schemaTableRegistry)) {
15
- schemaTableRegistry[schemaName] = {};
16
- }
17
- schemaTableRegistry[schemaName][tableName] = target;
14
+ const tables = schemaTableRegistry.get(schemaName) ?? {};
15
+ tables[tableName] = target;
16
+ schemaTableRegistry.set(schemaName, tables);
18
17
  });
19
18
  function getTablesForSchema(schemaName) {
20
- return schemaTableRegistry[schemaName];
19
+ return schemaTableRegistry.get(schemaName);
21
20
  }
22
21
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":";;;AA6BA,gDAIC;AAjCD,sEAI+C;AAC/C,uEAAwD;AAGxD,qCAA4D;AAE5D,MAAM,mBAAmB,GAAiD,EAAE,CAAC;AAEhE,QAAA,aAAa,GAGU,IAAA,+BAAkB,EACpD,CAAC,MAAM,EAAE,SAAiB,EAAE,UAAkB,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAG,IAAA,oBAAW,EAAC,MAAM,EAAE,4BAAmB,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,QAAQ,CAAC,MAAM,GAAG,2BAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzC,IAAI,CAAC,CAAC,UAAU,IAAI,mBAAmB,CAAC,EAAE,CAAC;QACzC,mBAAmB,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;IACvC,CAAC;IACD,mBAAmB,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC;AACtD,CAAC,CACF,CAAC;AAEF,SAAgB,kBAAkB,CAChC,UAAkB;IAElB,OAAO,mBAAmB,CAAC,UAAU,CAAC,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":";;;AA4BA,gDAIC;AAhCD,sEAI+C;AAC/C,uEAAwD;AAGxD,qCAA4D;AAE5D,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAwC,CAAC;AAE/D,QAAA,aAAa,GAGU,IAAA,+BAAkB,EACpD,CAAC,MAAM,EAAE,SAAiB,EAAE,UAAkB,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAG,IAAA,oBAAW,EAAC,MAAM,EAAE,4BAAmB,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,QAAQ,CAAC,MAAM,GAAG,2BAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzC,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IACzD,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC;IAC3B,mBAAmB,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAC9C,CAAC,CACF,CAAC;AAEF,SAAgB,kBAAkB,CAChC,UAAkB;IAElB,OAAO,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC"}