@bunnykit/orm 0.1.18 → 0.1.19
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/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/model/IdentityMap.d.ts +8 -0
- package/dist/src/model/IdentityMap.js +28 -0
- package/dist/src/model/Model.d.ts +1 -0
- package/dist/src/model/Model.js +11 -0
- package/dist/src/query/Builder.js +19 -0
- package/package.json +1 -1
package/dist/src/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { ObserverRegistry, type ObserverContract } from "./model/Observer.js";
|
|
|
20
20
|
export { MorphMap } from "./model/MorphMap.js";
|
|
21
21
|
export { MorphTo, MorphOne, MorphMany, MorphToMany } from "./model/MorphRelations.js";
|
|
22
22
|
export { BelongsToMany } from "./model/BelongsToMany.js";
|
|
23
|
+
export { IdentityMap } from "./model/IdentityMap.js";
|
|
23
24
|
export { Migration } from "./migration/Migration.js";
|
|
24
25
|
export { Migrator } from "./migration/Migrator.js";
|
|
25
26
|
export type { MigrationEvent, MigrationEventListener, MigrationEventPayload } from "./migration/Migrator.js";
|
package/dist/src/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export { ObserverRegistry } from "./model/Observer.js";
|
|
|
15
15
|
export { MorphMap } from "./model/MorphMap.js";
|
|
16
16
|
export { MorphTo, MorphOne, MorphMany, MorphToMany } from "./model/MorphRelations.js";
|
|
17
17
|
export { BelongsToMany } from "./model/BelongsToMany.js";
|
|
18
|
+
export { IdentityMap } from "./model/IdentityMap.js";
|
|
18
19
|
export { Migration } from "./migration/Migration.js";
|
|
19
20
|
export { Migrator } from "./migration/Migrator.js";
|
|
20
21
|
export { MigrationCreator } from "./migration/MigrationCreator.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Model } from "./Model.js";
|
|
2
|
+
export declare class IdentityMap {
|
|
3
|
+
static current(): Map<string, Model> | undefined;
|
|
4
|
+
static run<T>(callback: () => T | Promise<T>): Promise<T>;
|
|
5
|
+
static get(table: string, key: string | number): Model | undefined;
|
|
6
|
+
static set(table: string, key: string | number, model: Model): void;
|
|
7
|
+
static clear(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
const storage = new AsyncLocalStorage();
|
|
3
|
+
export class IdentityMap {
|
|
4
|
+
static current() {
|
|
5
|
+
return storage.getStore();
|
|
6
|
+
}
|
|
7
|
+
static async run(callback) {
|
|
8
|
+
return await storage.run(new Map(), callback);
|
|
9
|
+
}
|
|
10
|
+
static get(table, key) {
|
|
11
|
+
const map = this.current();
|
|
12
|
+
if (!map)
|
|
13
|
+
return undefined;
|
|
14
|
+
return map.get(`${table}:${String(key)}`);
|
|
15
|
+
}
|
|
16
|
+
static set(table, key, model) {
|
|
17
|
+
const map = this.current();
|
|
18
|
+
if (!map)
|
|
19
|
+
return;
|
|
20
|
+
map.set(`${table}:${String(key)}`, model);
|
|
21
|
+
}
|
|
22
|
+
static clear() {
|
|
23
|
+
const map = this.current();
|
|
24
|
+
if (!map)
|
|
25
|
+
return;
|
|
26
|
+
map.clear();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -115,6 +115,7 @@ export declare class Model<T extends Record<string, any> = Record<string, any>>
|
|
|
115
115
|
static getTable(): string;
|
|
116
116
|
static getConnection(): Connection;
|
|
117
117
|
static setConnection(connection: Connection): void;
|
|
118
|
+
static useIdentityMap<T>(callback: () => T | Promise<T>): Promise<T>;
|
|
118
119
|
static on<M extends ModelConstructor>(this: M, connection: string | Connection): Builder<InstanceType<M>>;
|
|
119
120
|
static forTenant<M extends ModelConstructor>(this: M, tenantId: string): Builder<InstanceType<M>>;
|
|
120
121
|
static query<M extends ModelConstructor>(this: M): Builder<InstanceType<M>>;
|
package/dist/src/model/Model.js
CHANGED
|
@@ -7,6 +7,7 @@ import { Schema } from "../schema/Schema.js";
|
|
|
7
7
|
import { ModelNotFoundError } from "./ModelNotFoundError.js";
|
|
8
8
|
import { ConnectionManager } from "../connection/ConnectionManager.js";
|
|
9
9
|
import { TenantContext } from "../connection/TenantContext.js";
|
|
10
|
+
import { IdentityMap } from "./IdentityMap.js";
|
|
10
11
|
const globalScopes = new WeakMap();
|
|
11
12
|
function getGlobalScopes(model) {
|
|
12
13
|
const scopes = new Map();
|
|
@@ -353,6 +354,9 @@ export class Model {
|
|
|
353
354
|
this.connection = connection;
|
|
354
355
|
ConnectionManager.setDefault(connection);
|
|
355
356
|
}
|
|
357
|
+
static useIdentityMap(callback) {
|
|
358
|
+
return IdentityMap.run(callback);
|
|
359
|
+
}
|
|
356
360
|
static on(connection) {
|
|
357
361
|
const resolved = typeof connection === "string" ? ConnectionManager.require(connection) : connection;
|
|
358
362
|
const builder = new Builder(resolved, resolved.qualifyTable(this.getTable()));
|
|
@@ -813,6 +817,13 @@ export class Model {
|
|
|
813
817
|
await ObserverRegistry.dispatch("created", this);
|
|
814
818
|
await ObserverRegistry.dispatch("saved", this);
|
|
815
819
|
}
|
|
820
|
+
const identityMap = IdentityMap.current();
|
|
821
|
+
if (identityMap) {
|
|
822
|
+
const pk = this.getAttribute(constructor.primaryKey);
|
|
823
|
+
if (pk !== null && pk !== undefined && pk !== "") {
|
|
824
|
+
IdentityMap.set(constructor.getTable(), pk, this);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
816
827
|
return this;
|
|
817
828
|
}
|
|
818
829
|
updateTimestamps() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ModelNotFoundError } from "../model/ModelNotFoundError.js";
|
|
2
|
+
import { IdentityMap } from "../model/IdentityMap.js";
|
|
2
3
|
export class Builder {
|
|
3
4
|
connection;
|
|
4
5
|
tableName;
|
|
@@ -589,13 +590,31 @@ export class Builder {
|
|
|
589
590
|
const results = await this.connection.query(sql, this.bindings);
|
|
590
591
|
const rows = Array.from(results);
|
|
591
592
|
if (this.model) {
|
|
593
|
+
const identityMap = IdentityMap.current();
|
|
594
|
+
const table = this.model.getTable();
|
|
595
|
+
const primaryKey = this.model.primaryKey || "id";
|
|
592
596
|
const models = rows.map((row) => {
|
|
597
|
+
if (identityMap) {
|
|
598
|
+
const pk = row[primaryKey];
|
|
599
|
+
if (pk !== null && pk !== undefined) {
|
|
600
|
+
const cached = IdentityMap.get(table, pk);
|
|
601
|
+
if (cached) {
|
|
602
|
+
return cached;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
593
606
|
const instance = new this.model(row);
|
|
594
607
|
instance.$exists = true;
|
|
595
608
|
instance.$original = { ...row };
|
|
596
609
|
if (typeof instance.setConnection === "function") {
|
|
597
610
|
instance.setConnection(this.connection);
|
|
598
611
|
}
|
|
612
|
+
if (identityMap) {
|
|
613
|
+
const pk = row[primaryKey];
|
|
614
|
+
if (pk !== null && pk !== undefined) {
|
|
615
|
+
IdentityMap.set(table, pk, instance);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
599
618
|
return instance;
|
|
600
619
|
});
|
|
601
620
|
if (this.eagerLoads.length > 0) {
|
package/package.json
CHANGED