leoric 2.15.0-alpha.3 → 2.15.0-beta.1

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 (91) hide show
  1. package/Readme.md +13 -13
  2. package/dist/abstract_bone.d.ts +22 -2
  3. package/dist/abstract_bone.js +143 -47
  4. package/dist/abstract_bone.js.map +1 -1
  5. package/dist/adapters/sequelize.d.ts +62 -391
  6. package/dist/adapters/sequelize.js +15 -8
  7. package/dist/adapters/sequelize.js.map +1 -1
  8. package/dist/bone.js +3 -1
  9. package/dist/bone.js.map +1 -1
  10. package/dist/browser.d.ts +2 -0
  11. package/dist/browser.js +2 -0
  12. package/dist/browser.js.map +1 -1
  13. package/dist/collection.js +0 -1
  14. package/dist/collection.js.map +1 -1
  15. package/dist/constants.d.ts +2 -1
  16. package/dist/constants.js +2 -1
  17. package/dist/constants.js.map +1 -1
  18. package/dist/decorators.d.ts +3 -0
  19. package/dist/decorators.js +5 -0
  20. package/dist/decorators.js.map +1 -1
  21. package/dist/index.d.ts +6 -2
  22. package/dist/index.js +9 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/model.d.ts +8 -0
  25. package/dist/model.js +74 -0
  26. package/dist/model.js.map +1 -0
  27. package/dist/query_object.d.ts +5 -1
  28. package/dist/raw.d.ts +2 -0
  29. package/dist/raw.js +8 -3
  30. package/dist/raw.js.map +1 -1
  31. package/dist/realm/base.d.ts +5 -1
  32. package/dist/realm/base.js +48 -19
  33. package/dist/realm/base.js.map +1 -1
  34. package/dist/spell.js +12 -17
  35. package/dist/spell.js.map +1 -1
  36. package/dist/types/common.d.ts +8 -1
  37. package/dist/utils/index.d.ts +1 -0
  38. package/dist/utils/index.js +6 -1
  39. package/dist/utils/index.js.map +1 -1
  40. package/lib/abstract_bone.d.ts +22 -2
  41. package/lib/abstract_bone.js +150 -47
  42. package/lib/abstract_bone.js.map +1 -1
  43. package/lib/adapters/sequelize.d.ts +62 -391
  44. package/lib/adapters/sequelize.js +12 -7
  45. package/lib/adapters/sequelize.js.map +1 -1
  46. package/lib/bone.js +2 -0
  47. package/lib/bone.js.map +1 -1
  48. package/lib/browser.d.ts +2 -0
  49. package/lib/browser.js +6 -1
  50. package/lib/browser.js.map +1 -1
  51. package/lib/collection.js +0 -1
  52. package/lib/collection.js.map +1 -1
  53. package/lib/constants.d.ts +2 -1
  54. package/lib/constants.js +3 -1
  55. package/lib/constants.js.map +1 -1
  56. package/lib/decorators.d.ts +3 -0
  57. package/lib/decorators.js +6 -0
  58. package/lib/decorators.js.map +1 -1
  59. package/lib/drivers/sqljs/sqljs-connection.js +34 -1
  60. package/lib/drivers/sqljs/sqljs-connection.js.map +1 -1
  61. package/lib/index.d.ts +6 -2
  62. package/lib/index.js +11 -2
  63. package/lib/index.js.map +1 -1
  64. package/lib/model.d.ts +8 -0
  65. package/lib/model.js +80 -0
  66. package/lib/model.js.map +1 -0
  67. package/lib/query_object.d.ts +5 -1
  68. package/lib/raw.d.ts +2 -0
  69. package/lib/raw.js +4 -0
  70. package/lib/raw.js.map +1 -1
  71. package/lib/realm/base.d.ts +5 -1
  72. package/lib/realm/base.js +48 -19
  73. package/lib/realm/base.js.map +1 -1
  74. package/lib/spell.js +11 -16
  75. package/lib/spell.js.map +1 -1
  76. package/lib/types/common.d.ts +8 -1
  77. package/lib/utils/index.d.ts +1 -0
  78. package/lib/utils/index.js +6 -0
  79. package/lib/utils/index.js.map +1 -1
  80. package/package.json +6 -1
  81. package/types/ts4.9/abstract_bone.d.ts +22 -2
  82. package/types/ts4.9/browser.d.ts +2 -0
  83. package/types/ts4.9/constants.d.ts +2 -1
  84. package/types/ts4.9/decorators.d.ts +3 -0
  85. package/types/ts4.9/index.d.ts +6 -2
  86. package/types/ts4.9/model.d.ts +8 -0
  87. package/types/ts4.9/query_object.d.ts +5 -1
  88. package/types/ts4.9/raw.d.ts +2 -0
  89. package/types/ts4.9/realm/base.d.ts +5 -1
  90. package/types/ts4.9/types/common.d.ts +8 -1
  91. package/types/ts4.9/utils/index.d.ts +1 -0
package/Readme.md CHANGED
@@ -13,19 +13,19 @@ Leoric is an object-relational mapping library for Node.js, which is heavily inf
13
13
  Assume the tables of posts, users, and comments were setup already. We may declare the models as classes by extending from the base class `Bone` of Leoric. After the models are connected to the database, the columns of the tables are mapped as attributes, the associations are setup, feel free to start querying.
14
14
 
15
15
  ```js
16
- import { Bone, connect } from 'leoric'
16
+ import Realm, { Bone } from 'leoric'
17
17
 
18
- // define model
19
- class Post extends Bone {
18
+ const realm = new Realm({ host: 'example.com' })
19
+ const Post = realm.define(class Post extends Bone {
20
20
  static initialize() {
21
21
  this.belongsTo('author', { Model: 'User' })
22
22
  this.hasMany('comments')
23
23
  }
24
- }
24
+ })
25
25
 
26
26
  async function main() {
27
27
  // connect models to database
28
- await connect({ host: 'example.com', models: [ Post ], /* among other options */ })
28
+ await realm.connect()
29
29
 
30
30
  // CRUD
31
31
  await Post.create({ title: 'New Post' })
@@ -47,15 +47,15 @@ If table structures were intended to be maintained in the models, Leoric can be
47
47
  ```js
48
48
  import Realm, { Bone, DataTypes } from 'leoric';
49
49
  const { BIGINT, STRING } = DataTypes;
50
- class Post extends Bone {
50
+ const realm = new Realm();
51
+ const Post = realm.define(class Post extends Bone {
51
52
  static attributes = {
52
53
  id: { type: BIGINT, primaryKey: true },
53
54
  email: { type: STRING, allowNull: false },
54
55
  nickname: { type: STRING, allowNull: false },
55
56
  }
56
- }
57
+ });
57
58
 
58
- const realm = new Realm({ models: [ Post ] });
59
59
  await realm.sync();
60
60
  ```
61
61
 
@@ -83,19 +83,19 @@ import User from './user';
83
83
 
84
84
  export default class Post extends Bone {
85
85
  @Column({ autoIncrement: true })
86
- id: bigint;
86
+ declare id: bigint;
87
87
 
88
88
  @Column(TEXT)
89
- content: string;
89
+ declare content: string;
90
90
 
91
91
  @Column()
92
- description: string;
92
+ declare description: string;
93
93
 
94
94
  @Column()
95
- userId: bigint;
95
+ declare userId: bigint;
96
96
 
97
97
  @BelongsTo()
98
- user: User;
98
+ declare user: User;
99
99
  }
100
100
  ```
101
101
 
@@ -24,16 +24,26 @@ export interface InitOptions {
24
24
  export declare const columnAttributesKey: unique symbol;
25
25
  export declare const synchronizedKey: unique symbol;
26
26
  export declare const tableKey: unique symbol;
27
+ export declare const hasLoadedAttributesKey: unique symbol;
28
+ export declare class LeoricModelDefinitionError extends Error {
29
+ constructor(modelName: string);
30
+ }
31
+ export declare class LeoricClassFieldError extends Error {
32
+ modelName: string;
33
+ attributeName: string;
34
+ constructor(modelName: string, attributeName: string);
35
+ }
27
36
  export declare class AbstractBone {
28
- #private;
29
37
  static DataTypes: typeof DataTypes;
30
38
  [key: string]: any;
39
+ [key: symbol]: any;
31
40
  isNewRecord: boolean;
32
41
  static [columnAttributesKey]: {
33
42
  [key: string]: Attribute;
34
43
  } | null;
35
44
  static [synchronizedKey]: boolean;
36
45
  static [tableKey]: string;
46
+ static [hasLoadedAttributesKey]: boolean;
37
47
  static get synchronized(): boolean;
38
48
  static set synchronized(value: boolean);
39
49
  /**
@@ -199,6 +209,7 @@ export declare class AbstractBone {
199
209
  static select<T extends typeof AbstractBone>(this: T, ...names: Array<BoneColumns<T>> | string[]): Spell<T>;
200
210
  static select<T extends typeof AbstractBone>(this: T, ...names: string[]): Spell<T>;
201
211
  static select<T extends typeof AbstractBone>(this: T, ...names: Raw[]): Spell<T>;
212
+ static select<T extends typeof AbstractBone>(this: T, ...names: Array<string | Raw>): Spell<T>;
202
213
  static select<T extends typeof AbstractBone>(this: T, filter: (name: string) => boolean): Spell<T>;
203
214
  /**
204
215
  * JOIN arbitrary models with given ON conditions
@@ -317,6 +328,8 @@ export declare class AbstractBone {
317
328
  attribute<T, Key extends keyof T, U extends T[Key]>(this: T, name: Key): U extends Literal ? U : Literal;
318
329
  attribute<T, Key extends keyof Values<T>>(this: T, name: Key, value: Literal): this;
319
330
  attribute<T, Key extends keyof T>(this: T, name: Key, value: Literal): this;
331
+ attribute(name: string): Literal;
332
+ attribute(name: string, value: Literal): this;
320
333
  /**
321
334
  * instance.hasAttribute(name)
322
335
  * @param name
@@ -437,7 +450,9 @@ export declare class AbstractBone {
437
450
  */
438
451
  reload(): Promise<this>;
439
452
  /**
440
- * Protected clone
453
+ * Protected clone — replaces internal state with merged data from target.
454
+ * Note: `this` here is the proxy (all method calls go through proxy). The proxy
455
+ * has no `set` trap, so Symbol-key assignments delegate to the underlying target.
441
456
  */
442
457
  _clone(target: any): void;
443
458
  /**
@@ -479,3 +494,8 @@ export declare class AbstractBone {
479
494
  */
480
495
  toObject(): any;
481
496
  }
497
+ export declare function markModelClassReady<T extends typeof AbstractBone>(Model: T): T;
498
+ export declare function isModelClassReady(Model: typeof AbstractBone): boolean;
499
+ export declare function markModelClassFieldsChecked<T extends typeof AbstractBone>(Model: T): T;
500
+ export declare function hasCheckedModelClassFields(Model: typeof AbstractBone): boolean;
501
+ export declare function assertModelClassFields(instance: AbstractBone): void;
@@ -1,5 +1,4 @@
1
- var _AbstractBone_raw, _AbstractBone_rawSaved, _AbstractBone_rawUnset, _AbstractBone_rawPrevious;
2
- import { __awaiter, __classPrivateFieldGet, __classPrivateFieldSet, __rest } from "tslib";
1
+ import { __awaiter, __rest } from "tslib";
3
2
  import util, { isDeepStrictEqual } from 'util';
4
3
  import Debug from 'debug';
5
4
  import pluralize from 'pluralize';
@@ -17,6 +16,36 @@ export const columnAttributesKey = Symbol('leoric#columnAttributes');
17
16
  export const synchronizedKey = Symbol('leoric#synchronized');
18
17
  export const tableKey = Symbol('leoric#table');
19
18
  const debug = Debug('leoric');
19
+ // Module-private Symbol keys for internal instance state. The properties are initialized
20
+ // with enumerable: false so they are invisible to assert.deepStrictEqual (which only compares
21
+ // own enumerable Symbol keys), matching the behavior of the original private fields.
22
+ const RAW = Symbol('leoric#raw');
23
+ const RAW_SAVED = Symbol('leoric#rawSaved');
24
+ const RAW_UNSET = Symbol('leoric#rawUnset');
25
+ const RAW_PREVIOUS = Symbol('leoric#rawPrevious');
26
+ const MODEL_READY = Symbol('leoric#modelReady');
27
+ const MODEL_CLASS_FIELDS_CHECKED = Symbol('leoric#modelClassFieldsChecked');
28
+ // Short accessors for internal state
29
+ function $raw(self) { return self[RAW]; }
30
+ function $rawSaved(self) { return self[RAW_SAVED]; }
31
+ function $rawUnset(self) { return self[RAW_UNSET]; }
32
+ function $rawPrevious(self) { return self[RAW_PREVIOUS]; }
33
+ // Kept as a compatibility export for adapters and consumers that reference the symbol.
34
+ export const hasLoadedAttributesKey = Symbol('leoric#hasLoadedAttributes');
35
+ export class LeoricModelDefinitionError extends Error {
36
+ constructor(modelName) {
37
+ super(`${modelName} is not a registered Leoric model. Add it to the realm models, decorate it with @Model(), or define it through realm.define().`);
38
+ this.name = 'LeoricModelDefinitionError';
39
+ }
40
+ }
41
+ export class LeoricClassFieldError extends Error {
42
+ constructor(modelName, attributeName) {
43
+ super(`${modelName}.${attributeName} is emitted as an ES class field and shadows Leoric's attribute accessor. Add \`declare\`, decorate ${modelName} with @Model(), or define it through realm.define(${modelName}, attributes).`);
44
+ this.name = 'LeoricClassFieldError';
45
+ this.modelName = modelName;
46
+ this.attributeName = attributeName;
47
+ }
48
+ }
20
49
  export class AbstractBone {
21
50
  static get synchronized() {
22
51
  return this[synchronizedKey];
@@ -44,12 +73,17 @@ export class AbstractBone {
44
73
  return this[tableKey];
45
74
  }
46
75
  constructor(values, opts = {}) {
47
- // private state
48
- _AbstractBone_raw.set(this, {});
49
- _AbstractBone_rawSaved.set(this, {});
50
- _AbstractBone_rawUnset.set(this, new Set());
51
- _AbstractBone_rawPrevious.set(this, {});
52
76
  this.isNewRecord = true;
77
+ const Model = new.target;
78
+ if (Model !== AbstractBone && !isModelClassReady(Model)) {
79
+ throw new LeoricModelDefinitionError(Model.name);
80
+ }
81
+ // Initialize internal Symbol-keyed properties as non-enumerable so they are
82
+ // invisible to assert.deepStrictEqual (which only compares own enumerable Symbol keys).
83
+ Object.defineProperty(this, RAW, { value: {}, writable: true, configurable: true, enumerable: false });
84
+ Object.defineProperty(this, RAW_SAVED, { value: {}, writable: true, configurable: true, enumerable: false });
85
+ Object.defineProperty(this, RAW_UNSET, { value: new Set(), writable: true, configurable: true, enumerable: false });
86
+ Object.defineProperty(this, RAW_PREVIOUS, { value: {}, writable: true, configurable: true, enumerable: false });
53
87
  Object.defineProperty(this, 'isNewRecord', {
54
88
  value: opts.isNewRecord !== undefined ? opts.isNewRecord : true,
55
89
  configurable: true,
@@ -190,6 +224,7 @@ export class AbstractBone {
190
224
  set(value) {
191
225
  return this.attribute(name, value);
192
226
  } }, customDescriptor), { enumerable: true, configurable: true }));
227
+ this[hasLoadedAttributesKey] = true;
193
228
  }
194
229
  static hasOne(name, options) {
195
230
  options = (Object.assign(Object.assign({ className: capitalize(name), foreignKey: camelCase(`${this.name}Id`) }, options), { hasMany: false }));
@@ -236,6 +271,7 @@ export class AbstractBone {
236
271
  opts = opts !== null && opts !== void 0 ? opts : {};
237
272
  const data = Object.assign({}, values);
238
273
  const instance = new this(data);
274
+ assertModelClassFields(instance);
239
275
  return instance.create(Object.assign({}, opts));
240
276
  }
241
277
  /**
@@ -296,7 +332,11 @@ export class AbstractBone {
296
332
  const autoIncrement = attribute.autoIncrement || (attribute.jsType == Number && attribute.primaryKey);
297
333
  if (options.validate !== false)
298
334
  records.map(entry => this._validateAttributes(entry));
299
- const instances = records.map(entry => new this(entry));
335
+ const instances = records.map(entry => {
336
+ const instance = new this(entry);
337
+ assertModelClassFields(instance);
338
+ return instance;
339
+ });
300
340
  if (options.individualHooks) {
301
341
  yield Promise.all(instances.map(instance => instance.save(options)));
302
342
  return instances;
@@ -474,6 +514,7 @@ export class AbstractBone {
474
514
  if (!options || options.validate !== false) {
475
515
  const validateData = copyValues(values);
476
516
  const instance = new this(validateData);
517
+ assertModelClassFields(instance);
477
518
  instance._validateAttributes(validateData);
478
519
  }
479
520
  let spell = new Spell(this, options).$where(conditions).$update(data);
@@ -674,6 +715,7 @@ export class AbstractBone {
674
715
  var _a;
675
716
  const { attributes, attributeMap } = this;
676
717
  const instance = new this();
718
+ assertModelClassFields(instance);
677
719
  const skipCloneValue = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.skipCloneValue) === true;
678
720
  for (const columnName in row) {
679
721
  const value = row[columnName];
@@ -778,9 +820,10 @@ export class AbstractBone {
778
820
  }
779
821
  }
780
822
  this[columnAttributesKey] = null;
823
+ markModelClassReady(this);
781
824
  }
782
825
  static from(table) {
783
- return new Spell(this).$from(table);
826
+ return new Spell(this).$from(table).later(Collection.init);
784
827
  }
785
828
  /**
786
829
  * Restore soft-deleted rows by clearing deletedAt.
@@ -799,33 +842,33 @@ export class AbstractBone {
799
842
  // raw accessors
800
843
  getRaw(key) {
801
844
  if (key)
802
- return __classPrivateFieldGet(this, _AbstractBone_raw, "f")[key];
803
- return __classPrivateFieldGet(this, _AbstractBone_raw, "f");
845
+ return $raw(this)[key];
846
+ return $raw(this);
804
847
  }
805
848
  getRawSaved(key) {
806
849
  if (key)
807
- return __classPrivateFieldGet(this, _AbstractBone_rawSaved, "f")[key];
808
- return __classPrivateFieldGet(this, _AbstractBone_rawSaved, "f");
850
+ return $rawSaved(this)[key];
851
+ return $rawSaved(this);
809
852
  }
810
853
  getRawPrevious(key) {
811
854
  if (key)
812
- return __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[key];
813
- return __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f");
855
+ return $rawPrevious(this)[key];
856
+ return $rawPrevious(this);
814
857
  }
815
858
  _setRaw(...args) {
816
859
  const [name, value] = args;
817
860
  if (args.length > 1) {
818
- __classPrivateFieldGet(this, _AbstractBone_raw, "f")[name] = value;
861
+ $raw(this)[name] = value;
819
862
  }
820
863
  else if (args.length === 1 && name !== undefined && typeof name === 'object') {
821
- __classPrivateFieldSet(this, _AbstractBone_raw, name, "f");
864
+ this[RAW] = name;
822
865
  }
823
866
  }
824
867
  _getRawUnset() {
825
- return __classPrivateFieldGet(this, _AbstractBone_rawUnset, "f");
868
+ return $rawUnset(this);
826
869
  }
827
870
  _setRawSaved(key, value) {
828
- __classPrivateFieldGet(this, _AbstractBone_rawSaved, "f")[key] = value;
871
+ $rawSaved(this)[key] = value;
829
872
  }
830
873
  /**
831
874
  * @example
@@ -838,13 +881,13 @@ export class AbstractBone {
838
881
  if (!attribute)
839
882
  throw new Error(`${this.constructor.name} has no attribute "${name}"`);
840
883
  if (arguments.length > 1) {
841
- __classPrivateFieldGet(this, _AbstractBone_raw, "f")[name] = value instanceof Raw ? value : attribute.cast(value);
842
- __classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").delete(name);
884
+ $raw(this)[name] = value instanceof Raw ? value : attribute.cast(value);
885
+ $rawUnset(this).delete(name);
843
886
  return this;
844
887
  }
845
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(name))
888
+ if ($rawUnset(this).has(name))
846
889
  return;
847
- const rawValue = __classPrivateFieldGet(this, _AbstractBone_raw, "f")[name];
890
+ const rawValue = $raw(this)[name];
848
891
  return rawValue == null ? null : rawValue;
849
892
  }
850
893
  /**
@@ -863,7 +906,7 @@ export class AbstractBone {
863
906
  * bone.attributeWas('foo') // => 1
864
907
  */
865
908
  attributeWas(name) {
866
- const value = __classPrivateFieldGet(this, _AbstractBone_rawSaved, "f")[name];
909
+ const value = $rawSaved(this)[name];
867
910
  return value == null ? null : value;
868
911
  }
869
912
  /**
@@ -873,7 +916,7 @@ export class AbstractBone {
873
916
  * bone.attributeChanged('foo')
874
917
  */
875
918
  attributeChanged(name) {
876
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(name) || !this.hasAttribute(name))
919
+ if ($rawUnset(this).has(name) || !this.hasAttribute(name))
877
920
  return false;
878
921
  const value = this.attribute(name);
879
922
  const valueWas = this.attributeWas(name);
@@ -890,7 +933,7 @@ export class AbstractBone {
890
933
  */
891
934
  changes(name) {
892
935
  if (name != null) {
893
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(name) || !this.hasAttribute(name))
936
+ if ($rawUnset(this).has(name) || !this.hasAttribute(name))
894
937
  return {};
895
938
  const value = this.attribute(name);
896
939
  const valueWas = this.attributeWas(name);
@@ -900,7 +943,7 @@ export class AbstractBone {
900
943
  }
901
944
  const result = {};
902
945
  for (const attrKey of Object.keys(this.constructor.attributes)) {
903
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(attrKey))
946
+ if ($rawUnset(this).has(attrKey))
904
947
  continue;
905
948
  const value = this.attribute(attrKey);
906
949
  const valueWas = this.attributeWas(attrKey);
@@ -920,21 +963,21 @@ export class AbstractBone {
920
963
  }
921
964
  previousChanges(name) {
922
965
  if (name != null) {
923
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(name) || __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[name] === undefined || !this.hasAttribute(name)) {
966
+ if ($rawUnset(this).has(name) || $rawPrevious(this)[name] === undefined || !this.hasAttribute(name)) {
924
967
  return {};
925
968
  }
926
969
  const value = this.attribute(name);
927
- const valueWas = __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[name] == null ? null : __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[name];
970
+ const valueWas = $rawPrevious(this)[name] == null ? null : $rawPrevious(this)[name];
928
971
  if (isDeepStrictEqual(value, valueWas))
929
972
  return {};
930
973
  return { [name]: [valueWas, value] };
931
974
  }
932
975
  const result = {};
933
976
  for (const attrKey of Object.keys(this.constructor.attributes)) {
934
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(attrKey) || __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[attrKey] === undefined)
977
+ if ($rawUnset(this).has(attrKey) || $rawPrevious(this)[attrKey] === undefined)
935
978
  continue;
936
979
  const value = this.attribute(attrKey);
937
- const valueWas = __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[attrKey] == null ? null : __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[attrKey];
980
+ const valueWas = $rawPrevious(this)[attrKey] == null ? null : $rawPrevious(this)[attrKey];
938
981
  if (!isDeepStrictEqual(value, valueWas))
939
982
  result[attrKey] = [valueWas, value];
940
983
  }
@@ -958,8 +1001,9 @@ export class AbstractBone {
958
1001
  */
959
1002
  _save() {
960
1003
  return __awaiter(this, arguments, void 0, function* (opts = {}) {
1004
+ assertModelClassFields(this);
961
1005
  const { primaryKey } = this.constructor;
962
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(primaryKey))
1006
+ if ($rawUnset(this).has(primaryKey))
963
1007
  throw new Error(`unset primary key ${primaryKey}`);
964
1008
  if (this[primaryKey] == null) {
965
1009
  yield this.create(opts);
@@ -989,17 +1033,17 @@ export class AbstractBone {
989
1033
  const attribute = attributes[name];
990
1034
  let value;
991
1035
  try {
992
- value = attribute.uncast(__classPrivateFieldGet(this, _AbstractBone_raw, "f")[name]);
1036
+ value = attribute.uncast($raw(this)[name]);
993
1037
  }
994
1038
  catch (error) {
995
1039
  console.error(error);
996
- value = __classPrivateFieldGet(this, _AbstractBone_raw, "f")[name];
1040
+ value = $raw(this)[name];
997
1041
  }
998
- if (__classPrivateFieldGet(this, _AbstractBone_rawSaved, "f")[name] !== undefined)
999
- __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[name] = __classPrivateFieldGet(this, _AbstractBone_rawSaved, "f")[name];
1000
- else if (__classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[name] === undefined && __classPrivateFieldGet(this, _AbstractBone_raw, "f")[name] != null)
1001
- __classPrivateFieldGet(this, _AbstractBone_rawPrevious, "f")[name] = null;
1002
- __classPrivateFieldGet(this, _AbstractBone_rawSaved, "f")[name] = attribute.cast(value);
1042
+ if ($rawSaved(this)[name] !== undefined)
1043
+ $rawPrevious(this)[name] = $rawSaved(this)[name];
1044
+ else if ($rawPrevious(this)[name] === undefined && $raw(this)[name] != null)
1045
+ $rawPrevious(this)[name] = null;
1046
+ $rawSaved(this)[name] = attribute.cast(value);
1003
1047
  }
1004
1048
  }
1005
1049
  /**
@@ -1057,6 +1101,7 @@ export class AbstractBone {
1057
1101
  * Internal upsert implementation
1058
1102
  */
1059
1103
  _upsert(opts) {
1104
+ assertModelClassFields(this);
1060
1105
  const data = {};
1061
1106
  const Model = this.constructor;
1062
1107
  const { attributes, primaryKey } = Model;
@@ -1091,6 +1136,7 @@ export class AbstractBone {
1091
1136
  */
1092
1137
  _update(values, options) {
1093
1138
  return __awaiter(this, void 0, void 0, function* () {
1139
+ assertModelClassFields(this);
1094
1140
  const Model = this.constructor;
1095
1141
  const { attributes, primaryKey, shardingKey } = Model;
1096
1142
  const changes = {};
@@ -1195,6 +1241,7 @@ export class AbstractBone {
1195
1241
  * Internal create implementation
1196
1242
  */
1197
1243
  _create(opts = {}) {
1244
+ assertModelClassFields(this);
1198
1245
  const Model = this.constructor;
1199
1246
  const { primaryKey, attributes } = Model;
1200
1247
  const data = {};
@@ -1250,13 +1297,15 @@ export class AbstractBone {
1250
1297
  });
1251
1298
  }
1252
1299
  /**
1253
- * Protected clone
1300
+ * Protected clone — replaces internal state with merged data from target.
1301
+ * Note: `this` here is the proxy (all method calls go through proxy). The proxy
1302
+ * has no `set` trap, so Symbol-key assignments delegate to the underlying target.
1254
1303
  */
1255
1304
  _clone(target) {
1256
- __classPrivateFieldSet(this, _AbstractBone_raw, Object.assign({}, this.getRaw(), target.getRaw()), "f");
1257
- __classPrivateFieldSet(this, _AbstractBone_rawSaved, Object.assign({}, this.getRawSaved(), target.getRawSaved()), "f");
1258
- __classPrivateFieldSet(this, _AbstractBone_rawPrevious, Object.assign({}, this.getRawPrevious(), target.getRawPrevious()), "f");
1259
- __classPrivateFieldSet(this, _AbstractBone_rawUnset, target._getRawUnset(), "f");
1305
+ this[RAW] = Object.assign({}, this.getRaw(), target.getRaw());
1306
+ this[RAW_SAVED] = Object.assign({}, this.getRawSaved(), target.getRawSaved());
1307
+ this[RAW_PREVIOUS] = Object.assign({}, this.getRawPrevious(), target.getRawPrevious());
1308
+ this[RAW_UNSET] = target._getRawUnset();
1260
1309
  }
1261
1310
  /**
1262
1311
  * Validate current changes
@@ -1314,13 +1363,13 @@ export class AbstractBone {
1314
1363
  * post.toJSON() // => { id: 1, ... }
1315
1364
  * @return {Object}
1316
1365
  */
1317
- [(_AbstractBone_raw = new WeakMap(), _AbstractBone_rawSaved = new WeakMap(), _AbstractBone_rawUnset = new WeakMap(), _AbstractBone_rawPrevious = new WeakMap(), util.inspect.custom)]() {
1366
+ [util.inspect.custom]() {
1318
1367
  return this.constructor.name + ' ' + util.inspect(this.toJSON());
1319
1368
  }
1320
1369
  toJSON() {
1321
1370
  const obj = {};
1322
1371
  for (const key in this) {
1323
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(key))
1372
+ if ($rawUnset(this).has(key))
1324
1373
  continue;
1325
1374
  if (typeof this[key] !== 'function') {
1326
1375
  const value = this[key];
@@ -1342,7 +1391,7 @@ export class AbstractBone {
1342
1391
  toObject() {
1343
1392
  const obj = {};
1344
1393
  for (const key in this) {
1345
- if (__classPrivateFieldGet(this, _AbstractBone_rawUnset, "f").has(key))
1394
+ if ($rawUnset(this).has(key))
1346
1395
  continue;
1347
1396
  if (typeof this[key] !== 'function') {
1348
1397
  const value = this[key];
@@ -1357,6 +1406,48 @@ AbstractBone.DataTypes = DataTypes.invokable;
1357
1406
  * The primary key of the model, defaults to `id`.
1358
1407
  */
1359
1408
  AbstractBone.primaryKey = 'id';
1409
+ export function markModelClassReady(Model) {
1410
+ if (isModelClassReady(Model))
1411
+ return Model;
1412
+ Object.defineProperty(Model, MODEL_READY, {
1413
+ value: true,
1414
+ configurable: false,
1415
+ enumerable: false,
1416
+ writable: false,
1417
+ });
1418
+ return Model;
1419
+ }
1420
+ export function isModelClassReady(Model) {
1421
+ return Object.prototype.hasOwnProperty.call(Model, MODEL_READY);
1422
+ }
1423
+ export function markModelClassFieldsChecked(Model) {
1424
+ if (hasCheckedModelClassFields(Model))
1425
+ return Model;
1426
+ Object.defineProperty(Model, MODEL_CLASS_FIELDS_CHECKED, {
1427
+ value: true,
1428
+ configurable: false,
1429
+ enumerable: false,
1430
+ writable: false,
1431
+ });
1432
+ return Model;
1433
+ }
1434
+ export function hasCheckedModelClassFields(Model) {
1435
+ return Object.prototype.hasOwnProperty.call(Model, MODEL_CLASS_FIELDS_CHECKED);
1436
+ }
1437
+ export function assertModelClassFields(instance) {
1438
+ const Model = instance.constructor;
1439
+ if (hasCheckedModelClassFields(Model))
1440
+ return;
1441
+ const { attributes } = Model;
1442
+ if (!attributes)
1443
+ return;
1444
+ for (const name of Object.keys(attributes)) {
1445
+ if (Object.prototype.hasOwnProperty.call(instance, name)) {
1446
+ throw new LeoricClassFieldError(Model.name, name);
1447
+ }
1448
+ }
1449
+ markModelClassFieldsChecked(Model);
1450
+ }
1360
1451
  function looseReadonly(props) {
1361
1452
  return Object.keys(props).reduce((result, name) => {
1362
1453
  result[name] = { value: props[name], writable: false, enumerable: false, configurable: true };
@@ -1429,6 +1520,11 @@ function valuesValidate(values, attributes, ctx) {
1429
1520
  function cloneValue(value) {
1430
1521
  if (value instanceof Date && isNaN(value))
1431
1522
  return value;
1523
+ // structuredClone converts Buffer to Uint8Array, breaking isDeepStrictEqual comparisons.
1524
+ // Preserve Buffer type by copying manually.
1525
+ if (Buffer.isBuffer(value))
1526
+ return Buffer.from(value);
1527
+ // eslint-disable-next-line no-undef
1432
1528
  return typeof structuredClone === 'function' ? structuredClone(value) : JSON.parse(JSON.stringify(value));
1433
1529
  }
1434
1530
  Reflect.defineMetadata(IS_LEORIC_BONE, true, AbstractBone);