@tyravel/database 0.2.0 → 0.2.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.
- package/dist/eager-loader.d.ts +6 -0
- package/dist/eager-loader.d.ts.map +1 -0
- package/dist/eager-loader.js +23 -0
- package/dist/eager-loader.js.map +1 -0
- package/dist/eager-loading.test.d.ts +2 -0
- package/dist/eager-loading.test.d.ts.map +1 -0
- package/dist/eager-loading.test.js +150 -0
- package/dist/eager-loading.test.js.map +1 -0
- package/dist/factory-helpers.d.ts +7 -0
- package/dist/factory-helpers.d.ts.map +1 -0
- package/dist/factory-helpers.js +23 -0
- package/dist/factory-helpers.js.map +1 -0
- package/dist/factory.d.ts +12 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +25 -0
- package/dist/factory.js.map +1 -0
- package/dist/factory.test.d.ts +2 -0
- package/dist/factory.test.d.ts.map +1 -0
- package/dist/factory.test.js +53 -0
- package/dist/factory.test.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/migrator.d.ts.map +1 -1
- package/dist/migrator.js +11 -12
- package/dist/migrator.js.map +1 -1
- package/dist/model-query-builder.d.ts +3 -0
- package/dist/model-query-builder.d.ts.map +1 -1
- package/dist/model-query-builder.js +17 -1
- package/dist/model-query-builder.js.map +1 -1
- package/dist/model.d.ts +5 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +14 -0
- package/dist/model.js.map +1 -1
- package/dist/relations/belongs-to-many.d.ts +8 -0
- package/dist/relations/belongs-to-many.d.ts.map +1 -1
- package/dist/relations/belongs-to-many.js +49 -0
- package/dist/relations/belongs-to-many.js.map +1 -1
- package/dist/relations/belongs-to.d.ts +7 -0
- package/dist/relations/belongs-to.d.ts.map +1 -1
- package/dist/relations/belongs-to.js +33 -2
- package/dist/relations/belongs-to.js.map +1 -1
- package/dist/relations/has-many.d.ts +5 -0
- package/dist/relations/has-many.d.ts.map +1 -1
- package/dist/relations/has-many.js +32 -0
- package/dist/relations/has-many.js.map +1 -1
- package/dist/relations/has-one.d.ts +5 -0
- package/dist/relations/has-one.d.ts.map +1 -1
- package/dist/relations/has-one.js +28 -0
- package/dist/relations/has-one.js.map +1 -1
- package/dist/relations/relation.d.ts +6 -0
- package/dist/relations/relation.d.ts.map +1 -1
- package/dist/relations/relation.js +15 -0
- package/dist/relations/relation.js.map +1 -1
- package/dist/schema/blueprint.d.ts +6 -1
- package/dist/schema/blueprint.d.ts.map +1 -1
- package/dist/schema/blueprint.js +88 -13
- package/dist/schema/blueprint.js.map +1 -1
- package/dist/schema/blueprint.test.d.ts +2 -0
- package/dist/schema/blueprint.test.d.ts.map +1 -0
- package/dist/schema/blueprint.test.js +36 -0
- package/dist/schema/blueprint.test.js.map +1 -0
- package/dist/schema/schema-builder.d.ts +2 -0
- package/dist/schema/schema-builder.d.ts.map +1 -1
- package/dist/schema/schema-builder.js +53 -3
- package/dist/schema/schema-builder.js.map +1 -1
- package/dist/seeder-runner.d.ts +10 -0
- package/dist/seeder-runner.d.ts.map +1 -0
- package/dist/seeder-runner.js +52 -0
- package/dist/seeder-runner.js.map +1 -0
- package/dist/seeder-runner.test.d.ts +2 -0
- package/dist/seeder-runner.test.d.ts.map +1 -0
- package/dist/seeder-runner.test.js +58 -0
- package/dist/seeder-runner.test.js.map +1 -0
- package/dist/seeder.d.ts +5 -0
- package/dist/seeder.d.ts.map +1 -0
- package/dist/seeder.js +6 -0
- package/dist/seeder.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Model } from './model.js';
|
|
2
|
+
import type { ModelStatic } from './model-types.js';
|
|
3
|
+
export declare class EagerLoader {
|
|
4
|
+
static load(parents: Model[], relations: string[], ModelClass: ModelStatic): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=eager-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eager-loader.d.ts","sourceRoot":"","sources":["../src/eager-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,qBAAa,WAAW;WACT,IAAI,CACf,OAAO,EAAE,KAAK,EAAE,EAChB,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,EAAE,WAAW,GACtB,OAAO,CAAC,IAAI,CAAC;CA2BjB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class EagerLoader {
|
|
2
|
+
static async load(parents, relations, ModelClass) {
|
|
3
|
+
if (parents.length === 0 || relations.length === 0) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
const instance = new ModelClass();
|
|
7
|
+
for (const relationName of relations) {
|
|
8
|
+
const relationMethod = instance[relationName];
|
|
9
|
+
if (typeof relationMethod !== 'function') {
|
|
10
|
+
throw new Error(`Relation [${relationName}] not defined on model [${ModelClass.name}].`);
|
|
11
|
+
}
|
|
12
|
+
const relation = relationMethod.call(instance);
|
|
13
|
+
relation.initRelation(parents, relationName);
|
|
14
|
+
const keys = relation.eagerLoadKeys(parents);
|
|
15
|
+
if (keys.length === 0) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const results = await relation.eagerLoad(keys);
|
|
19
|
+
relation.matchEager(parents, results, relationName);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=eager-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eager-loader.js","sourceRoot":"","sources":["../src/eager-loader.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,WAAW;IACtB,MAAM,CAAC,KAAK,CAAC,IAAI,CACf,OAAgB,EAChB,SAAmB,EACnB,UAAuB;QAEvB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAK,UAA8B,EAAE,CAAC;QAEvD,KAAK,MAAM,YAAY,IAAI,SAAS,EAAE,CAAC;YACrC,MAAM,cAAc,GAAI,QAA+C,CAAC,YAAY,CAAC,CAAC;YACtF,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CACb,aAAa,YAAY,2BAA2B,UAAU,CAAC,IAAI,IAAI,CACxE,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAa,CAAC;YAC3D,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAE7C,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/C,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eager-loading.test.d.ts","sourceRoot":"","sources":["../src/eager-loading.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
+
import { Model } from './model.js';
|
|
3
|
+
import { SqliteConnection } from './sqlite-connection.js';
|
|
4
|
+
class User extends Model {
|
|
5
|
+
static table = 'users';
|
|
6
|
+
posts() {
|
|
7
|
+
return this.hasMany(Post);
|
|
8
|
+
}
|
|
9
|
+
latestPost() {
|
|
10
|
+
return this.hasOne(Post);
|
|
11
|
+
}
|
|
12
|
+
roles() {
|
|
13
|
+
return this.belongsToMany(Role);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class Post extends Model {
|
|
17
|
+
static table = 'posts';
|
|
18
|
+
user() {
|
|
19
|
+
return this.belongsTo(User);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
class Role extends Model {
|
|
23
|
+
static table = 'roles';
|
|
24
|
+
}
|
|
25
|
+
function trackQueries(connection) {
|
|
26
|
+
let queryCount = 0;
|
|
27
|
+
const originalQuery = connection.query.bind(connection);
|
|
28
|
+
connection.query = async (sql, bindings) => {
|
|
29
|
+
queryCount++;
|
|
30
|
+
return originalQuery(sql, bindings);
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
count: () => queryCount,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
describe('eager loading', () => {
|
|
37
|
+
const connection = new SqliteConnection(':memory:');
|
|
38
|
+
beforeAll(async () => {
|
|
39
|
+
User.useConnection(connection);
|
|
40
|
+
Post.useConnection(connection);
|
|
41
|
+
Role.useConnection(connection);
|
|
42
|
+
await connection.exec(`
|
|
43
|
+
CREATE TABLE "users" (
|
|
44
|
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
+
"name" TEXT NOT NULL
|
|
46
|
+
);
|
|
47
|
+
CREATE TABLE "posts" (
|
|
48
|
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
49
|
+
"user_id" INTEGER NOT NULL,
|
|
50
|
+
"title" TEXT NOT NULL
|
|
51
|
+
);
|
|
52
|
+
CREATE TABLE "roles" (
|
|
53
|
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
54
|
+
"name" TEXT NOT NULL
|
|
55
|
+
);
|
|
56
|
+
CREATE TABLE "user_role" (
|
|
57
|
+
"user_id" INTEGER NOT NULL,
|
|
58
|
+
"role_id" INTEGER NOT NULL
|
|
59
|
+
);
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
62
|
+
it('eager loads hasMany relations without N+1 queries', async () => {
|
|
63
|
+
const ada = await User.create({ name: 'Ada' });
|
|
64
|
+
const grace = await User.create({ name: 'Grace' });
|
|
65
|
+
await Post.create({ user_id: ada.getAttribute('id'), title: 'Ada 1' });
|
|
66
|
+
await Post.create({ user_id: ada.getAttribute('id'), title: 'Ada 2' });
|
|
67
|
+
await Post.create({ user_id: grace.getAttribute('id'), title: 'Grace 1' });
|
|
68
|
+
const tracker = trackQueries(connection);
|
|
69
|
+
const users = await User.query()
|
|
70
|
+
.whereIn('id', [ada.getAttribute('id'), grace.getAttribute('id')])
|
|
71
|
+
.with('posts')
|
|
72
|
+
.getModels();
|
|
73
|
+
expect(tracker.count()).toBe(2);
|
|
74
|
+
expect(users).toHaveLength(2);
|
|
75
|
+
expect(users.every((user) => user.relationLoaded('posts'))).toBe(true);
|
|
76
|
+
const adaPosts = users
|
|
77
|
+
.find((user) => user.getAttribute('name') === 'Ada')
|
|
78
|
+
?.getRelation('posts');
|
|
79
|
+
const gracePosts = users
|
|
80
|
+
.find((user) => user.getAttribute('name') === 'Grace')
|
|
81
|
+
?.getRelation('posts');
|
|
82
|
+
expect(adaPosts).toHaveLength(2);
|
|
83
|
+
expect(gracePosts).toHaveLength(1);
|
|
84
|
+
expect(adaPosts?.map((post) => post.getAttribute('title')).sort()).toEqual([
|
|
85
|
+
'Ada 1',
|
|
86
|
+
'Ada 2',
|
|
87
|
+
]);
|
|
88
|
+
});
|
|
89
|
+
it('eager loads hasOne relations', async () => {
|
|
90
|
+
const user = await User.create({ name: 'Katherine' });
|
|
91
|
+
await Post.create({ user_id: user.getAttribute('id'), title: 'Only' });
|
|
92
|
+
const tracker = trackQueries(connection);
|
|
93
|
+
const loaded = await User.query()
|
|
94
|
+
.where('id', user.getAttribute('id'))
|
|
95
|
+
.with('latestPost')
|
|
96
|
+
.firstModel();
|
|
97
|
+
expect(tracker.count()).toBe(2);
|
|
98
|
+
expect(loaded?.relationLoaded('latestPost')).toBe(true);
|
|
99
|
+
expect(loaded?.getRelation('latestPost')?.getAttribute('title')).toBe('Only');
|
|
100
|
+
});
|
|
101
|
+
it('eager loads belongsTo relations', async () => {
|
|
102
|
+
const ada = await User.create({ name: 'Ada' });
|
|
103
|
+
const grace = await User.create({ name: 'Grace' });
|
|
104
|
+
const adaPost = await Post.create({
|
|
105
|
+
user_id: ada.getAttribute('id'),
|
|
106
|
+
title: 'Ada eager post',
|
|
107
|
+
});
|
|
108
|
+
const gracePost = await Post.create({
|
|
109
|
+
user_id: grace.getAttribute('id'),
|
|
110
|
+
title: 'Grace eager post',
|
|
111
|
+
});
|
|
112
|
+
const tracker = trackQueries(connection);
|
|
113
|
+
const posts = await Post.query()
|
|
114
|
+
.whereIn('id', [adaPost.getAttribute('id'), gracePost.getAttribute('id')])
|
|
115
|
+
.with('user')
|
|
116
|
+
.getModels();
|
|
117
|
+
expect(tracker.count()).toBe(2);
|
|
118
|
+
expect(posts).toHaveLength(2);
|
|
119
|
+
expect(posts.every((post) => post.relationLoaded('user'))).toBe(true);
|
|
120
|
+
expect(posts
|
|
121
|
+
.map((post) => post.getRelation('user')?.getAttribute('name'))
|
|
122
|
+
.sort()).toEqual(['Ada', 'Grace']);
|
|
123
|
+
});
|
|
124
|
+
it('eager loads belongsToMany relations', async () => {
|
|
125
|
+
const user = await User.create({ name: 'Alan' });
|
|
126
|
+
const admin = await Role.create({ name: 'admin' });
|
|
127
|
+
const editor = await Role.create({ name: 'editor' });
|
|
128
|
+
await connection.query('INSERT INTO "user_role" ("user_id", "role_id") VALUES (?, ?), (?, ?)', [
|
|
129
|
+
user.getAttribute('id'),
|
|
130
|
+
admin.getAttribute('id'),
|
|
131
|
+
user.getAttribute('id'),
|
|
132
|
+
editor.getAttribute('id'),
|
|
133
|
+
]);
|
|
134
|
+
const tracker = trackQueries(connection);
|
|
135
|
+
const users = await User.query()
|
|
136
|
+
.where('id', user.getAttribute('id'))
|
|
137
|
+
.with('roles')
|
|
138
|
+
.getModels();
|
|
139
|
+
expect(tracker.count()).toBe(2);
|
|
140
|
+
expect(users[0]?.relationLoaded('roles')).toBe(true);
|
|
141
|
+
expect(users[0]?.getRelation('roles')?.map((role) => role.getAttribute('name')).sort()).toEqual([
|
|
142
|
+
'admin',
|
|
143
|
+
'editor',
|
|
144
|
+
]);
|
|
145
|
+
});
|
|
146
|
+
it('throws when eager loading an undefined relation', async () => {
|
|
147
|
+
await expect(User.with('missing').getModels()).rejects.toThrow('Relation [missing] not defined on model [User].');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
//# sourceMappingURL=eager-loading.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eager-loading.test.js","sourceRoot":"","sources":["../src/eager-loading.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function resetFactoryHelpers(): void;
|
|
2
|
+
export declare function fakeSequence(): number;
|
|
3
|
+
export declare function fakeEmail(prefix?: string): string;
|
|
4
|
+
export declare function fakeName(): string;
|
|
5
|
+
export declare function fakeSlug(prefix?: string): string;
|
|
6
|
+
export declare function fakeText(wordCount?: number): string;
|
|
7
|
+
//# sourceMappingURL=factory-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory-helpers.d.ts","sourceRoot":"","sources":["../src/factory-helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,wBAAgB,SAAS,CAAC,MAAM,SAAS,GAAG,MAAM,CAEjD;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAIjC;AAED,wBAAgB,QAAQ,CAAC,MAAM,SAAS,GAAG,MAAM,CAEhD;AAED,wBAAgB,QAAQ,CAAC,SAAS,SAAI,GAAG,MAAM,CAI9C"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
let sequence = 0;
|
|
2
|
+
export function resetFactoryHelpers() {
|
|
3
|
+
sequence = 0;
|
|
4
|
+
}
|
|
5
|
+
export function fakeSequence() {
|
|
6
|
+
sequence += 1;
|
|
7
|
+
return sequence;
|
|
8
|
+
}
|
|
9
|
+
export function fakeEmail(prefix = 'user') {
|
|
10
|
+
return `${prefix}.${fakeSequence()}.${Date.now()}@example.com`;
|
|
11
|
+
}
|
|
12
|
+
export function fakeName() {
|
|
13
|
+
const names = ['Ada', 'Grace', 'Alan', 'Katherine', 'Linus', 'Margaret'];
|
|
14
|
+
const index = (fakeSequence() - 1) % names.length;
|
|
15
|
+
return names[index] ?? `User ${fakeSequence()}`;
|
|
16
|
+
}
|
|
17
|
+
export function fakeSlug(prefix = 'item') {
|
|
18
|
+
return `${prefix}-${fakeSequence()}`;
|
|
19
|
+
}
|
|
20
|
+
export function fakeText(wordCount = 3) {
|
|
21
|
+
return Array.from({ length: wordCount }, (_, index) => `word${fakeSequence() + index}`).join(' ');
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=factory-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory-helpers.js","sourceRoot":"","sources":["../src/factory-helpers.ts"],"names":[],"mappings":"AAAA,IAAI,QAAQ,GAAG,CAAC,CAAC;AAEjB,MAAM,UAAU,mBAAmB;IACjC,QAAQ,GAAG,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,QAAQ,IAAI,CAAC,CAAC;IACd,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAM,GAAG,MAAM;IACvC,OAAO,GAAG,MAAM,IAAI,YAAY,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IAClD,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,YAAY,EAAE,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAM,GAAG,MAAM;IACtC,OAAO,GAAG,MAAM,IAAI,YAAY,EAAE,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,SAAS,GAAG,CAAC;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,YAAY,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,IAAI,CAC1F,GAAG,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Model } from './model.js';
|
|
2
|
+
import type { ModelAttributes } from './model-types.js';
|
|
3
|
+
export declare abstract class Factory<TModel extends Model = Model, TAttributes extends ModelAttributes = ModelAttributes> {
|
|
4
|
+
protected abstract readonly ModelClass: new (attributes?: Partial<TAttributes>) => TModel;
|
|
5
|
+
abstract definition(): Partial<TAttributes>;
|
|
6
|
+
private pendingCount;
|
|
7
|
+
count(amount: number): this;
|
|
8
|
+
make(attributes?: Partial<TAttributes>): TModel;
|
|
9
|
+
makeMany(count: number, attributes?: Partial<TAttributes>): TModel[];
|
|
10
|
+
create(attributes?: Partial<TAttributes>): Promise<TModel | TModel[]>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,8BAAsB,OAAO,CAC3B,MAAM,SAAS,KAAK,GAAG,KAAK,EAC5B,WAAW,SAAS,eAAe,GAAG,eAAe;IAErD,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,KAAK,UAAU,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,MAAM,CAAC;IAE1F,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAE3C,OAAO,CAAC,YAAY,CAAK;IAEzB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,CAAC,UAAU,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,MAAM;IAInD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,MAAM,EAAE;IAIlE,MAAM,CAAC,UAAU,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;CAahF"}
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export class Factory {
|
|
2
|
+
pendingCount = 1;
|
|
3
|
+
count(amount) {
|
|
4
|
+
this.pendingCount = amount;
|
|
5
|
+
return this;
|
|
6
|
+
}
|
|
7
|
+
make(attributes = {}) {
|
|
8
|
+
return new this.ModelClass({ ...this.definition(), ...attributes });
|
|
9
|
+
}
|
|
10
|
+
makeMany(count, attributes = {}) {
|
|
11
|
+
return Array.from({ length: count }, () => this.make(attributes));
|
|
12
|
+
}
|
|
13
|
+
async create(attributes = {}) {
|
|
14
|
+
const count = this.pendingCount;
|
|
15
|
+
this.pendingCount = 1;
|
|
16
|
+
const models = [];
|
|
17
|
+
for (let index = 0; index < count; index += 1) {
|
|
18
|
+
const model = this.make(attributes);
|
|
19
|
+
await model.save();
|
|
20
|
+
models.push(model);
|
|
21
|
+
}
|
|
22
|
+
return count === 1 ? models[0] : models;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAGA,MAAM,OAAgB,OAAO;IAQnB,YAAY,GAAG,CAAC,CAAC;IAEzB,KAAK,CAAC,MAAc;QAClB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,aAAmC,EAAE;QACxC,OAAO,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,aAAmC,EAAE;QAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,aAAmC,EAAE;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;QAChC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QAEtB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACpC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.test.d.ts","sourceRoot":"","sources":["../src/factory.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
+
import { fakeEmail, fakeName, resetFactoryHelpers } from './factory-helpers.js';
|
|
3
|
+
import { Factory } from './factory.js';
|
|
4
|
+
import { Model } from './model.js';
|
|
5
|
+
import { SqliteConnection } from './sqlite-connection.js';
|
|
6
|
+
class User extends Model {
|
|
7
|
+
static table = 'users';
|
|
8
|
+
}
|
|
9
|
+
class UserFactory extends Factory {
|
|
10
|
+
ModelClass = User;
|
|
11
|
+
definition() {
|
|
12
|
+
return {
|
|
13
|
+
name: fakeName(),
|
|
14
|
+
email: fakeEmail(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
describe('Factory', () => {
|
|
19
|
+
const connection = new SqliteConnection(':memory:');
|
|
20
|
+
const userFactory = new UserFactory();
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
resetFactoryHelpers();
|
|
23
|
+
});
|
|
24
|
+
beforeAll(async () => {
|
|
25
|
+
User.useConnection(connection);
|
|
26
|
+
await connection.exec(`
|
|
27
|
+
CREATE TABLE "users" (
|
|
28
|
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
29
|
+
"name" TEXT NOT NULL,
|
|
30
|
+
"email" TEXT NOT NULL
|
|
31
|
+
);
|
|
32
|
+
`);
|
|
33
|
+
});
|
|
34
|
+
it('makes unsaved model instances', () => {
|
|
35
|
+
const user = userFactory.make({ name: 'Ada' });
|
|
36
|
+
expect(user.getAttribute('name')).toBe('Ada');
|
|
37
|
+
expect(user.getAttribute('id')).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
it('creates persisted models', async () => {
|
|
40
|
+
const user = (await userFactory.create());
|
|
41
|
+
expect(user.getAttribute('id')).toBeDefined();
|
|
42
|
+
expect(user.getAttribute('email')).toContain('@example.com');
|
|
43
|
+
const found = await User.find(user.getAttribute('id'));
|
|
44
|
+
expect(found?.getAttribute('name')).toBe(user.getAttribute('name'));
|
|
45
|
+
});
|
|
46
|
+
it('creates multiple models with count()', async () => {
|
|
47
|
+
const users = (await userFactory.count(3).create());
|
|
48
|
+
expect(users).toHaveLength(3);
|
|
49
|
+
const emails = users.map((user) => user.getAttribute('email'));
|
|
50
|
+
expect(new Set(emails).size).toBe(3);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=factory.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.test.js","sourceRoot":"","sources":["../src/factory.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAS1D,MAAM,IAAK,SAAQ,KAAc;IAC/B,MAAM,CAAU,KAAK,GAAG,OAAO,CAAC;;AAGlC,MAAM,WAAY,SAAQ,OAAsB;IAC3B,UAAU,GAAG,IAAI,CAAC;IAErC,UAAU;QACR,OAAO;YACL,IAAI,EAAE,QAAQ,EAAE;YAChB,KAAK,EAAE,SAAS,EAAE;SACnB,CAAC;IACJ,CAAC;CACF;AAED,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,mBAAmB,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,UAAU,CAAC,IAAI,CAAC;;;;;;KAMrB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,IAAI,GAAG,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,CAAS,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAE7D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAE,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,KAAK,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAW,CAAC;QAC9D,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAE9B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export type { DatabaseConnection, QueryResult } from './connection.js';
|
|
2
2
|
export { DatabaseManager } from './database-manager.js';
|
|
3
|
+
export { Factory } from './factory.js';
|
|
4
|
+
export { fakeEmail, fakeName, fakeSequence, fakeSlug, fakeText, resetFactoryHelpers, } from './factory-helpers.js';
|
|
3
5
|
export { MysqlGrammar, PostgresGrammar, SqliteGrammar, } from './grammar.js';
|
|
4
6
|
export type { DriverName, SqlGrammar } from './grammar.js';
|
|
5
7
|
export { Migration } from './migration.js';
|
|
6
8
|
export { Migrator } from './migrator.js';
|
|
9
|
+
export { Seeder } from './seeder.js';
|
|
10
|
+
export { SeederRunner } from './seeder-runner.js';
|
|
7
11
|
export { Model } from './model.js';
|
|
8
12
|
export { ModelQueryBuilder } from './model-query-builder.js';
|
|
9
13
|
export { QueryBuilder } from './query-builder.js';
|
|
@@ -13,7 +17,7 @@ export { HasManyRelation } from './relations/has-many.js';
|
|
|
13
17
|
export { HasOneRelation } from './relations/has-one.js';
|
|
14
18
|
export { Relation } from './relations/relation.js';
|
|
15
19
|
export { Blueprint } from './schema/blueprint.js';
|
|
16
|
-
export { SchemaBuilder } from './schema/schema-builder.js';
|
|
20
|
+
export { SchemaBuilder, migrationsTableSql } from './schema/schema-builder.js';
|
|
17
21
|
export type { GlobalScope, LocalScope } from './scopes.js';
|
|
18
22
|
export { MysqlConnection } from './mysql-connection.js';
|
|
19
23
|
export { PostgresConnection } from './postgres-connection.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC/E,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,GAAG,EACH,QAAQ,EACR,sBAAsB,EACtB,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export { DatabaseManager } from './database-manager.js';
|
|
2
|
+
export { Factory } from './factory.js';
|
|
3
|
+
export { fakeEmail, fakeName, fakeSequence, fakeSlug, fakeText, resetFactoryHelpers, } from './factory-helpers.js';
|
|
2
4
|
export { MysqlGrammar, PostgresGrammar, SqliteGrammar, } from './grammar.js';
|
|
3
5
|
export { Migration } from './migration.js';
|
|
4
6
|
export { Migrator } from './migrator.js';
|
|
7
|
+
export { Seeder } from './seeder.js';
|
|
8
|
+
export { SeederRunner } from './seeder-runner.js';
|
|
5
9
|
export { Model } from './model.js';
|
|
6
10
|
export { ModelQueryBuilder } from './model-query-builder.js';
|
|
7
11
|
export { QueryBuilder } from './query-builder.js';
|
|
@@ -11,7 +15,7 @@ export { HasManyRelation } from './relations/has-many.js';
|
|
|
11
15
|
export { HasOneRelation } from './relations/has-one.js';
|
|
12
16
|
export { Relation } from './relations/relation.js';
|
|
13
17
|
export { Blueprint } from './schema/blueprint.js';
|
|
14
|
-
export { SchemaBuilder } from './schema/schema-builder.js';
|
|
18
|
+
export { SchemaBuilder, migrationsTableSql } from './schema/schema-builder.js';
|
|
15
19
|
export { MysqlConnection } from './mysql-connection.js';
|
|
16
20
|
export { PostgresConnection } from './postgres-connection.js';
|
|
17
21
|
export { SqliteConnection } from './sqlite-connection.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAE/E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/migrator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../src/migrator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI1D,qBAAa,QAAQ;IAEjB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,UAAU,EAAE,kBAAkB,EAC9B,cAAc,EAAE,MAAM;IAGnC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../src/migrator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI1D,qBAAa,QAAQ;IAEjB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,UAAU,EAAE,kBAAkB,EAC9B,cAAc,EAAE,MAAM;IAGnC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAM5B,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAsBhB,QAAQ;YAQR,WAAW;IAUzB,OAAO,CAAC,KAAK;YAUC,IAAI;YAcJ,MAAM;CAMrB"}
|
package/dist/migrator.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readdirSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { SchemaBuilder } from './schema/schema-builder.js';
|
|
4
|
+
import { migrationsTableSql, SchemaBuilder } from './schema/schema-builder.js';
|
|
5
5
|
export class Migrator {
|
|
6
6
|
connection;
|
|
7
7
|
migrationsPath;
|
|
@@ -10,14 +10,7 @@ export class Migrator {
|
|
|
10
10
|
this.migrationsPath = migrationsPath;
|
|
11
11
|
}
|
|
12
12
|
async ensureMigrationsTable() {
|
|
13
|
-
await this.connection.exec(
|
|
14
|
-
CREATE TABLE IF NOT EXISTS "migrations" (
|
|
15
|
-
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16
|
-
"migration" TEXT NOT NULL,
|
|
17
|
-
"batch" INTEGER NOT NULL,
|
|
18
|
-
"executed_at" TEXT NOT NULL
|
|
19
|
-
)
|
|
20
|
-
`);
|
|
13
|
+
await this.connection.exec(migrationsTableSql(this.connection.grammar));
|
|
21
14
|
}
|
|
22
15
|
async pending() {
|
|
23
16
|
await this.ensureMigrationsTable();
|
|
@@ -43,11 +36,14 @@ export class Migrator {
|
|
|
43
36
|
return ran;
|
|
44
37
|
}
|
|
45
38
|
async executed() {
|
|
46
|
-
const
|
|
39
|
+
const grammar = this.connection.grammar;
|
|
40
|
+
const result = await this.connection.query(`SELECT ${grammar.wrapIdentifier('migration')} FROM ${grammar.wrapIdentifier('migrations')} ORDER BY ${grammar.wrapIdentifier('id')} ASC`);
|
|
47
41
|
return result.rows.map((row) => String(row.migration));
|
|
48
42
|
}
|
|
49
43
|
async latestBatch() {
|
|
50
|
-
const
|
|
44
|
+
const grammar = this.connection.grammar;
|
|
45
|
+
const batchColumn = grammar.wrapIdentifier('batch');
|
|
46
|
+
const result = await this.connection.query(`SELECT MAX(${batchColumn}) as ${batchColumn} FROM ${grammar.wrapIdentifier('migrations')}`);
|
|
51
47
|
const batch = result.rows[0]?.batch;
|
|
52
48
|
return typeof batch === 'number' ? batch : 0;
|
|
53
49
|
}
|
|
@@ -71,7 +67,10 @@ export class Migrator {
|
|
|
71
67
|
return MigrationClass;
|
|
72
68
|
}
|
|
73
69
|
async record(migration, batch) {
|
|
74
|
-
|
|
70
|
+
const grammar = this.connection.grammar;
|
|
71
|
+
const table = grammar.wrapIdentifier('migrations');
|
|
72
|
+
const sql = `INSERT INTO ${table} (${grammar.wrapIdentifier('migration')}, ${grammar.wrapIdentifier('batch')}, ${grammar.wrapIdentifier('executed_at')}) VALUES (${grammar.parameter(1)}, ${grammar.parameter(2)}, ${grammar.parameter(3)})`;
|
|
73
|
+
await this.connection.query(sql, [migration, batch, new Date().toISOString()]);
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
76
|
//# sourceMappingURL=migrator.js.map
|
package/dist/migrator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrator.js","sourceRoot":"","sources":["../src/migrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"migrator.js","sourceRoot":"","sources":["../src/migrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,11 @@ import type { ModelStatic } from './model-types.js';
|
|
|
5
5
|
import { type GlobalScope } from './scopes.js';
|
|
6
6
|
export declare class ModelQueryBuilder extends QueryBuilder {
|
|
7
7
|
private readonly model;
|
|
8
|
+
protected eagerLoad: string[];
|
|
8
9
|
constructor(connection: DatabaseConnection, tableName: string, model: ModelStatic);
|
|
10
|
+
with(...relations: string[]): this;
|
|
9
11
|
clone(): ModelQueryBuilder;
|
|
12
|
+
protected copyTo(builder: QueryBuilder): void;
|
|
10
13
|
applyScope(name: string, ...args: unknown[]): this;
|
|
11
14
|
getModels<TModel extends Model>(): Promise<TModel[]>;
|
|
12
15
|
firstModel<TModel extends Model>(): Promise<TModel | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-query-builder.d.ts","sourceRoot":"","sources":["../src/model-query-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"model-query-builder.d.ts","sourceRoot":"","sources":["../src/model-query-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAmB,KAAK,WAAW,EAAmB,MAAM,aAAa,CAAC;AAEjF,qBAAa,iBAAkB,SAAQ,YAAY;IAM/C,OAAO,CAAC,QAAQ,CAAC,KAAK;IALxB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,CAAM;gBAGjC,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,EACA,KAAK,EAAE,WAAW;IAKrC,IAAI,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAKzB,KAAK,IAAI,iBAAiB;cAUhB,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAOtD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAc5C,SAAS,CAAC,MAAM,SAAS,KAAK,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;IAcpD,UAAU,CAAC,MAAM,SAAS,KAAK,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAIjE;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,WAAW,EAAE,GACpB,iBAAiB,CASnB"}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
+
import { EagerLoader } from './eager-loader.js';
|
|
1
2
|
import { QueryBuilder } from './query-builder.js';
|
|
2
3
|
import { scopeMethodName } from './scopes.js';
|
|
3
4
|
export class ModelQueryBuilder extends QueryBuilder {
|
|
4
5
|
model;
|
|
6
|
+
eagerLoad = [];
|
|
5
7
|
constructor(connection, tableName, model) {
|
|
6
8
|
super(connection, tableName);
|
|
7
9
|
this.model = model;
|
|
8
10
|
}
|
|
11
|
+
with(...relations) {
|
|
12
|
+
this.eagerLoad.push(...relations);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
9
15
|
clone() {
|
|
10
16
|
const builder = new ModelQueryBuilder(this.connection, this.getTableName(), this.model);
|
|
11
17
|
this.copyTo(builder);
|
|
12
18
|
return builder;
|
|
13
19
|
}
|
|
20
|
+
copyTo(builder) {
|
|
21
|
+
super.copyTo(builder);
|
|
22
|
+
if (builder instanceof ModelQueryBuilder) {
|
|
23
|
+
builder.eagerLoad = [...this.eagerLoad];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
14
26
|
applyScope(name, ...args) {
|
|
15
27
|
const scopeName = scopeMethodName(name);
|
|
16
28
|
const scope = this.model[scopeName];
|
|
@@ -23,7 +35,11 @@ export class ModelQueryBuilder extends QueryBuilder {
|
|
|
23
35
|
async getModels() {
|
|
24
36
|
const rows = await this.get();
|
|
25
37
|
const ModelClass = this.model;
|
|
26
|
-
|
|
38
|
+
const models = rows.map((row) => new ModelClass(row));
|
|
39
|
+
if (this.eagerLoad.length > 0) {
|
|
40
|
+
await EagerLoader.load(models, this.eagerLoad, this.model);
|
|
41
|
+
}
|
|
42
|
+
return models;
|
|
27
43
|
}
|
|
28
44
|
async firstModel() {
|
|
29
45
|
const rows = await this.clone().limit(1).getModels();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-query-builder.js","sourceRoot":"","sources":["../src/model-query-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,eAAe,EAAqC,MAAM,aAAa,CAAC;AAEjF,MAAM,OAAO,iBAAkB,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"model-query-builder.js","sourceRoot":"","sources":["../src/model-query-builder.ts"],"names":[],"mappings":"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"}
|
package/dist/model.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare class Model<T extends ModelAttributes = ModelAttributes> {
|
|
|
14
14
|
private static resolver;
|
|
15
15
|
private static globalScopes;
|
|
16
16
|
protected attributes: Partial<T>;
|
|
17
|
+
private relations;
|
|
17
18
|
constructor(attributes?: Partial<T>);
|
|
18
19
|
static setConnectionResolver(resolver: () => DatabaseConnection): void;
|
|
19
20
|
static useConnection(connection: DatabaseConnection): void;
|
|
@@ -24,11 +25,15 @@ export declare class Model<T extends ModelAttributes = ModelAttributes> {
|
|
|
24
25
|
static find<TModel extends Model>(this: new (attributes?: Partial<ModelAttributes>) => TModel, id: RowValue): Promise<TModel | null>;
|
|
25
26
|
static all<TModel extends Model>(this: new (attributes?: Partial<ModelAttributes>) => TModel): Promise<TModel[]>;
|
|
26
27
|
static create<TModel extends Model>(this: new (attributes?: Partial<ModelAttributes>) => TModel, attributes: Partial<ModelAttributes>): Promise<TModel>;
|
|
28
|
+
static with(...relations: string[]): ModelQueryBuilder;
|
|
27
29
|
static where(column: string, operatorOrValue?: RowValue | string, value?: RowValue): ModelQueryBuilder;
|
|
28
30
|
hasMany<Related extends Model>(RelatedModel: ModelStatic, foreignKey?: string, localKey?: string): HasManyRelation<Related>;
|
|
29
31
|
hasOne<Related extends Model>(RelatedModel: ModelStatic, foreignKey?: string, localKey?: string): HasOneRelation<Related>;
|
|
30
32
|
belongsTo<Related extends Model>(RelatedModel: ModelStatic, foreignKey?: string, ownerKey?: string): BelongsToRelation<Related>;
|
|
31
33
|
belongsToMany<Related extends Model>(RelatedModel: ModelStatic, pivotTable?: string, foreignPivotKey?: string, relatedPivotKey?: string, parentKey?: string, relatedKey?: string): BelongsToManyRelation<Related>;
|
|
34
|
+
setRelation(name: string, value: unknown): void;
|
|
35
|
+
getRelation<TRelation>(name: string): TRelation | undefined;
|
|
36
|
+
relationLoaded(name: string): boolean;
|
|
32
37
|
getAttribute<K extends keyof T>(key: K): T[K] | undefined;
|
|
33
38
|
setAttribute<K extends keyof T>(key: K, value: T[K]): void;
|
|
34
39
|
toJSON(): Partial<T>;
|