@bunnykit/orm 0.1.19 → 0.1.20
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/dist/src/model/Model.d.ts +3 -0
- package/dist/src/model/Model.js +36 -17
- package/package.json +1 -1
|
@@ -105,6 +105,7 @@ export declare class Model<T extends Record<string, any> = Record<string, any>>
|
|
|
105
105
|
static attributes: Record<string, any>;
|
|
106
106
|
static softDeletes: boolean;
|
|
107
107
|
static deletedAtColumn: string;
|
|
108
|
+
static preventLazyLoading: boolean;
|
|
108
109
|
$attributes: T;
|
|
109
110
|
$original: Partial<T>;
|
|
110
111
|
$exists: boolean;
|
|
@@ -112,6 +113,8 @@ export declare class Model<T extends Record<string, any> = Record<string, any>>
|
|
|
112
113
|
$casts: Record<string, CastDefinition>;
|
|
113
114
|
$connection?: Connection;
|
|
114
115
|
constructor(attributes?: Partial<T>);
|
|
116
|
+
private defineAttributeProperty;
|
|
117
|
+
private syncAttributeProperties;
|
|
115
118
|
static getTable(): string;
|
|
116
119
|
static getConnection(): Connection;
|
|
117
120
|
static setConnection(connection: Connection): void;
|
package/dist/src/model/Model.js
CHANGED
|
@@ -38,6 +38,15 @@ export class Relation {
|
|
|
38
38
|
this.builder = related.on(parent.getConnection());
|
|
39
39
|
this.foreignKey = foreignKey || this.defaultForeignKey();
|
|
40
40
|
this.localKey = localKey || related.primaryKey;
|
|
41
|
+
// Wrap getResults with lazy-loading guard
|
|
42
|
+
const originalGetResults = this.getResults.bind(this);
|
|
43
|
+
this.getResults = async () => {
|
|
44
|
+
if (this.parent.constructor.preventLazyLoading) {
|
|
45
|
+
throw new Error(`Lazy loading is prevented on ${this.parent.constructor.name}. ` +
|
|
46
|
+
`Eager load the relation using with().`);
|
|
47
|
+
}
|
|
48
|
+
return await originalGetResults();
|
|
49
|
+
};
|
|
41
50
|
}
|
|
42
51
|
defaultForeignKey() {
|
|
43
52
|
return `${snakeCase(this.parent.constructor.name)}_id`;
|
|
@@ -291,6 +300,7 @@ export class Model {
|
|
|
291
300
|
static attributes = {};
|
|
292
301
|
static softDeletes = false;
|
|
293
302
|
static deletedAtColumn = "deleted_at";
|
|
303
|
+
static preventLazyLoading = false;
|
|
294
304
|
$attributes = {};
|
|
295
305
|
$original = {};
|
|
296
306
|
$exists = false;
|
|
@@ -305,6 +315,9 @@ export class Model {
|
|
|
305
315
|
if (attributes) {
|
|
306
316
|
this.fill(attributes);
|
|
307
317
|
}
|
|
318
|
+
this.syncAttributeProperties();
|
|
319
|
+
// Minimal Proxy fallback for dynamic property access on undefined keys.
|
|
320
|
+
// Pre-defined attribute getters/setters bypass the Proxy entirely.
|
|
308
321
|
return new Proxy(this, {
|
|
309
322
|
get(target, prop, receiver) {
|
|
310
323
|
if (typeof prop === "string" && !(prop in target) && prop in target.$attributes) {
|
|
@@ -319,25 +332,23 @@ export class Model {
|
|
|
319
332
|
}
|
|
320
333
|
return Reflect.set(target, prop, value, receiver);
|
|
321
334
|
},
|
|
322
|
-
has(target, prop) {
|
|
323
|
-
return prop in target || (typeof prop === "string" && prop in target.$attributes);
|
|
324
|
-
},
|
|
325
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
326
|
-
if (typeof prop === "string" && !(prop in target) && prop in target.$attributes) {
|
|
327
|
-
return {
|
|
328
|
-
enumerable: true,
|
|
329
|
-
configurable: true,
|
|
330
|
-
writable: true,
|
|
331
|
-
value: target.getAttribute(prop),
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
335
|
-
},
|
|
336
|
-
ownKeys(target) {
|
|
337
|
-
return [...new Set([...Reflect.ownKeys(target), ...Object.keys(target.$attributes)])];
|
|
338
|
-
},
|
|
339
335
|
});
|
|
340
336
|
}
|
|
337
|
+
defineAttributeProperty(key) {
|
|
338
|
+
if (key in this)
|
|
339
|
+
return;
|
|
340
|
+
Object.defineProperty(this, key, {
|
|
341
|
+
get: () => this.getAttribute(key),
|
|
342
|
+
set: (value) => this.setAttribute(key, value),
|
|
343
|
+
enumerable: true,
|
|
344
|
+
configurable: true,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
syncAttributeProperties() {
|
|
348
|
+
for (const key of Object.keys(this.$attributes)) {
|
|
349
|
+
this.defineAttributeProperty(key);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
341
352
|
static getTable() {
|
|
342
353
|
return this.table || snakeCase(this.name) + "s";
|
|
343
354
|
}
|
|
@@ -662,6 +673,7 @@ export class Model {
|
|
|
662
673
|
}
|
|
663
674
|
setAttribute(key, value) {
|
|
664
675
|
this.$attributes[key] = this.serializeCastAttribute(key, value);
|
|
676
|
+
this.defineAttributeProperty(key);
|
|
665
677
|
}
|
|
666
678
|
castAttribute(key, value) {
|
|
667
679
|
const cast = this.getCastDefinition(key);
|
|
@@ -817,6 +829,7 @@ export class Model {
|
|
|
817
829
|
await ObserverRegistry.dispatch("created", this);
|
|
818
830
|
await ObserverRegistry.dispatch("saved", this);
|
|
819
831
|
}
|
|
832
|
+
this.syncAttributeProperties();
|
|
820
833
|
const identityMap = IdentityMap.current();
|
|
821
834
|
if (identityMap) {
|
|
822
835
|
const pk = this.getAttribute(constructor.primaryKey);
|
|
@@ -835,6 +848,7 @@ export class Model {
|
|
|
835
848
|
if (!this.$exists) {
|
|
836
849
|
this.$attributes["created_at"] = now;
|
|
837
850
|
}
|
|
851
|
+
this.syncAttributeProperties();
|
|
838
852
|
}
|
|
839
853
|
async touch() {
|
|
840
854
|
if (!this.$exists)
|
|
@@ -850,6 +864,7 @@ export class Model {
|
|
|
850
864
|
.update({ updated_at: now });
|
|
851
865
|
this.$attributes["updated_at"] = now;
|
|
852
866
|
this.$original = { ...this.$attributes };
|
|
867
|
+
this.syncAttributeProperties();
|
|
853
868
|
return true;
|
|
854
869
|
}
|
|
855
870
|
async increment(column, amount = 1, extra = {}) {
|
|
@@ -869,6 +884,7 @@ export class Model {
|
|
|
869
884
|
this.$attributes[key] = value;
|
|
870
885
|
}
|
|
871
886
|
this.$original = { ...this.$attributes };
|
|
887
|
+
this.syncAttributeProperties();
|
|
872
888
|
return this;
|
|
873
889
|
}
|
|
874
890
|
async decrement(column, amount = 1, extra = {}) {
|
|
@@ -893,6 +909,7 @@ export class Model {
|
|
|
893
909
|
.update({ [constructor.deletedAtColumn]: deletedAt });
|
|
894
910
|
this.$attributes[constructor.deletedAtColumn] = deletedAt;
|
|
895
911
|
this.$original = { ...this.$attributes };
|
|
912
|
+
this.syncAttributeProperties();
|
|
896
913
|
}
|
|
897
914
|
else {
|
|
898
915
|
const connection = this.getConnection();
|
|
@@ -918,6 +935,7 @@ export class Model {
|
|
|
918
935
|
this.$attributes[constructor.deletedAtColumn] = null;
|
|
919
936
|
this.$original = { ...this.$attributes };
|
|
920
937
|
this.$exists = true;
|
|
938
|
+
this.syncAttributeProperties();
|
|
921
939
|
return true;
|
|
922
940
|
}
|
|
923
941
|
async forceDelete() {
|
|
@@ -941,6 +959,7 @@ export class Model {
|
|
|
941
959
|
if (result) {
|
|
942
960
|
this.$attributes = result.$attributes;
|
|
943
961
|
this.$original = { ...result.$attributes };
|
|
962
|
+
this.syncAttributeProperties();
|
|
944
963
|
}
|
|
945
964
|
return this;
|
|
946
965
|
}
|
package/package.json
CHANGED