@cheetah.js/orm 0.1.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.
- package/README.md +228 -0
- package/build.ts +14 -0
- package/cheetah.config.ts +14 -0
- package/dist/SqlBuilder.d.ts +57 -0
- package/dist/SqlBuilder.js +436 -0
- package/dist/SqlBuilder.js.map +1 -0
- package/dist/bun/index.d.ts +13 -0
- package/dist/bun/index.js +224319 -0
- package/dist/bun/index.js.map +306 -0
- package/dist/cheetah.d.ts +1 -0
- package/dist/cheetah.js +24 -0
- package/dist/cheetah.js.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/decorators/entity.decorator.d.ts +3 -0
- package/dist/decorators/entity.decorator.js +10 -0
- package/dist/decorators/entity.decorator.js.map +1 -0
- package/dist/decorators/index.decorator.d.ts +3 -0
- package/dist/decorators/index.decorator.js +17 -0
- package/dist/decorators/index.decorator.js.map +1 -0
- package/dist/decorators/one-many.decorator.d.ts +3 -0
- package/dist/decorators/one-many.decorator.js +17 -0
- package/dist/decorators/one-many.decorator.js.map +1 -0
- package/dist/decorators/primary-key.decorator.d.ts +2 -0
- package/dist/decorators/primary-key.decorator.js +6 -0
- package/dist/decorators/primary-key.decorator.js.map +1 -0
- package/dist/decorators/property.decorator.d.ts +15 -0
- package/dist/decorators/property.decorator.js +25 -0
- package/dist/decorators/property.decorator.js.map +1 -0
- package/dist/domain/base-entity.d.ts +42 -0
- package/dist/domain/base-entity.js +106 -0
- package/dist/domain/base-entity.js.map +1 -0
- package/dist/domain/collection.d.ts +6 -0
- package/dist/domain/collection.js +11 -0
- package/dist/domain/collection.js.map +1 -0
- package/dist/domain/entities.d.ts +40 -0
- package/dist/domain/entities.js +137 -0
- package/dist/domain/entities.js.map +1 -0
- package/dist/domain/reference.d.ts +4 -0
- package/dist/domain/reference.js +7 -0
- package/dist/domain/reference.js.map +1 -0
- package/dist/driver/driver.interface.d.ts +270 -0
- package/dist/driver/driver.interface.js +2 -0
- package/dist/driver/driver.interface.js.map +1 -0
- package/dist/driver/pg-driver.d.ts +43 -0
- package/dist/driver/pg-driver.js +255 -0
- package/dist/driver/pg-driver.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/migration/diff-calculator.d.ts +17 -0
- package/dist/migration/diff-calculator.js +230 -0
- package/dist/migration/diff-calculator.js.map +1 -0
- package/dist/migration/migrator.d.ts +18 -0
- package/dist/migration/migrator.js +233 -0
- package/dist/migration/migrator.js.map +1 -0
- package/dist/orm.d.ts +14 -0
- package/dist/orm.js +23 -0
- package/dist/orm.js.map +1 -0
- package/dist/orm.service.d.ts +8 -0
- package/dist/orm.service.js +115 -0
- package/dist/orm.service.js.map +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +16 -0
- package/dist/utils.js.map +1 -0
- package/package.json +50 -0
- package/src/SqlBuilder.ts +542 -0
- package/src/cheetah.ts +28 -0
- package/src/constants.ts +4 -0
- package/src/decorators/entity.decorator.ts +10 -0
- package/src/decorators/index.decorator.ts +18 -0
- package/src/decorators/one-many.decorator.ts +19 -0
- package/src/decorators/primary-key.decorator.ts +6 -0
- package/src/decorators/property.decorator.ts +41 -0
- package/src/domain/base-entity.ts +149 -0
- package/src/domain/collection.ts +10 -0
- package/src/domain/entities.ts +159 -0
- package/src/domain/reference.ts +5 -0
- package/src/driver/driver.interface.ts +331 -0
- package/src/driver/pg-driver.ts +308 -0
- package/src/index.ts +17 -0
- package/src/migration/diff-calculator.ts +258 -0
- package/src/migration/migrator.ts +278 -0
- package/src/orm.service.ts +115 -0
- package/src/orm.ts +30 -0
- package/src/utils.ts +18 -0
- package/test/domain/base-entity.spec.ts +463 -0
- package/test/migration/.sql +5 -0
- package/test/migration/cheetah.config.ts +13 -0
- package/test/migration/migator.spec.ts +251 -0
- package/test/migration/test.sql +5 -0
- package/test/node-database.ts +32 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, jest, test, setSystemTime } from 'bun:test'
|
|
2
|
+
import { app, execute, mockLogger, purgeDatabase, startDatabase } from '../node-database';
|
|
3
|
+
import { BaseEntity, Entity, OneToMany, PrimaryKey, Property } from '../../src';
|
|
4
|
+
|
|
5
|
+
@Entity()
|
|
6
|
+
class UserTest extends BaseEntity {
|
|
7
|
+
@PrimaryKey()
|
|
8
|
+
id: number;
|
|
9
|
+
|
|
10
|
+
@Property()
|
|
11
|
+
createdAt: Date = new Date();
|
|
12
|
+
|
|
13
|
+
@Property({onUpdate: () => new Date()})
|
|
14
|
+
updatedAt: Date;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('Creation, update and deletion of entities', () => {
|
|
18
|
+
|
|
19
|
+
const DLL = `
|
|
20
|
+
CREATE TABLE "user"
|
|
21
|
+
(
|
|
22
|
+
"id" SERIAL PRIMARY KEY,
|
|
23
|
+
"email" varchar(255) NOT NULL
|
|
24
|
+
);
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
const DDL_ADDRESS = `
|
|
28
|
+
CREATE TABLE "address"
|
|
29
|
+
(
|
|
30
|
+
"id" SERIAL PRIMARY KEY,
|
|
31
|
+
"address" varchar(255) NOT NULL,
|
|
32
|
+
"user" integer REFERENCES "user" ("id")
|
|
33
|
+
);
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
@Entity()
|
|
37
|
+
class User extends BaseEntity {
|
|
38
|
+
@PrimaryKey()
|
|
39
|
+
id: number;
|
|
40
|
+
|
|
41
|
+
@Property()
|
|
42
|
+
email: string;
|
|
43
|
+
|
|
44
|
+
@OneToMany(() => Address, (address) => address.user)
|
|
45
|
+
addresses: Address[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Entity()
|
|
49
|
+
class Address extends BaseEntity {
|
|
50
|
+
@PrimaryKey()
|
|
51
|
+
id: number;
|
|
52
|
+
|
|
53
|
+
@Property()
|
|
54
|
+
address: string;
|
|
55
|
+
|
|
56
|
+
@Property()
|
|
57
|
+
user: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
beforeEach(async () => {
|
|
61
|
+
await startDatabase();
|
|
62
|
+
await execute(DLL);
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
afterEach(async () => {
|
|
66
|
+
await purgeDatabase();
|
|
67
|
+
(mockLogger as jest.Mock).mockClear();
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
test('should create a entity', async () => {
|
|
72
|
+
const user = await User.create({
|
|
73
|
+
email: 'test@test.com',
|
|
74
|
+
id: 1,
|
|
75
|
+
})
|
|
76
|
+
const result = await execute(`SELECT *
|
|
77
|
+
FROM "user"
|
|
78
|
+
WHERE id = '1';`);
|
|
79
|
+
|
|
80
|
+
expect(result.rows[0]).toEqual({
|
|
81
|
+
id: 1,
|
|
82
|
+
email: 'test@test.com',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(user).toBeInstanceOf(User);
|
|
86
|
+
expect(mockLogger).toHaveBeenCalledTimes(1);
|
|
87
|
+
expect((mockLogger as jest.Mock).mock.calls[0][0]).toStartWith("SQL: INSERT INTO \"public\".\"user\" (\"email\", \"id\") VALUES ('test@test.com', 1) RETURNING \"id\" as \"u1_id\", \"email\" as \"u1_email\" ");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('should create a entity by new instance', async () => {
|
|
91
|
+
const user = new User();
|
|
92
|
+
user.email = 'test@test.com';
|
|
93
|
+
user.id = 1;
|
|
94
|
+
await user.save();
|
|
95
|
+
|
|
96
|
+
const result = await execute(`SELECT *
|
|
97
|
+
FROM "user"
|
|
98
|
+
WHERE id = '1';`);
|
|
99
|
+
|
|
100
|
+
expect(result.rows[0]).toEqual({
|
|
101
|
+
id: 1,
|
|
102
|
+
email: 'test@test.com',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(user).toBeInstanceOf(User);
|
|
106
|
+
expect(mockLogger).toHaveBeenCalledTimes(1);
|
|
107
|
+
expect((mockLogger as jest.Mock).mock.calls[0][0]).toStartWith("SQL: INSERT INTO \"public\".\"user\" (\"email\", \"id\") VALUES ('test@test.com', 1) RETURNING \"id\" as \"u1_id\", \"email\" as \"u1_email\" ");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('should a find a entity', async () => {
|
|
111
|
+
const user = await User.create({
|
|
112
|
+
email: 'test@test.com',
|
|
113
|
+
id: 1,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const result = await User.findOne({id: 1});
|
|
117
|
+
|
|
118
|
+
expect(result).toBeInstanceOf(User);
|
|
119
|
+
expect(result).toEqual(user!);
|
|
120
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
121
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id = 1) LIMIT 1");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('should a update a entity', async () => {
|
|
125
|
+
const user = await User.create({
|
|
126
|
+
email: 'test@test.com',
|
|
127
|
+
id: 1,
|
|
128
|
+
})
|
|
129
|
+
user!.email = 'updated@test.com';
|
|
130
|
+
await user!.save();
|
|
131
|
+
|
|
132
|
+
const result = await User.findOne({id: 1});
|
|
133
|
+
expect(result!.email).toEqual('updated@test.com')
|
|
134
|
+
expect(mockLogger).toHaveBeenCalledTimes(3);
|
|
135
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: UPDATE public.user as u1 SET email = 'updated@test.com' WHERE (u1.id = 1)");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('should a find relationship', async () => {
|
|
139
|
+
await execute(DDL_ADDRESS);
|
|
140
|
+
const user = await User.create({
|
|
141
|
+
email: 'test@test.com',
|
|
142
|
+
id: 1,
|
|
143
|
+
});
|
|
144
|
+
const address = await Address.create({
|
|
145
|
+
address: 'Street 1',
|
|
146
|
+
user: user.id,
|
|
147
|
+
id: 1,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const result = await User.findOne({
|
|
151
|
+
addresses: {
|
|
152
|
+
id: 1,
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
expect(result).toBeInstanceOf(User);
|
|
157
|
+
expect(result!.addresses).toBeInstanceOf(Array);
|
|
158
|
+
expect(result!.addresses[0]).toEqual(address);
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('when findOrFail but not found, throw error', async () => {
|
|
162
|
+
expect(async () => {
|
|
163
|
+
await User.findOneOrFail({id: 1})
|
|
164
|
+
}).toThrow()
|
|
165
|
+
expect(mockLogger).toHaveBeenCalledTimes(1);
|
|
166
|
+
expect((mockLogger as jest.Mock).mock.calls[0][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id = 1) LIMIT 1");
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('When create a entity, return the created entity', async () => {
|
|
170
|
+
const id = 1;
|
|
171
|
+
const email = 'test@test.com';
|
|
172
|
+
|
|
173
|
+
const user = await User.create({
|
|
174
|
+
email,
|
|
175
|
+
id,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(user).toBeInstanceOf(User);
|
|
179
|
+
expect(user.id).toEqual(id);
|
|
180
|
+
expect(user.email).toEqual(email);
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('When search with $eq operator', async () => {
|
|
184
|
+
const id = 1;
|
|
185
|
+
const email = 'test@test.com';
|
|
186
|
+
|
|
187
|
+
await User.create({
|
|
188
|
+
email,
|
|
189
|
+
id,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const user = await User.findOneOrFail({
|
|
193
|
+
id: {
|
|
194
|
+
$eq: id,
|
|
195
|
+
},
|
|
196
|
+
email: email,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
expect(user).toBeInstanceOf(User);
|
|
200
|
+
expect(user.id).toEqual(id);
|
|
201
|
+
expect(user.email).toEqual(email);
|
|
202
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
203
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id = 1 AND u1.email = 'test@test.com') LIMIT 1");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test('When search with $ne operator', async () => {
|
|
207
|
+
const id = 1;
|
|
208
|
+
const email = 'test@test.com';
|
|
209
|
+
|
|
210
|
+
await User.create({
|
|
211
|
+
email,
|
|
212
|
+
id,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const user = await User.findOneOrFail({
|
|
216
|
+
id: {
|
|
217
|
+
$ne: 2,
|
|
218
|
+
},
|
|
219
|
+
email: email,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
expect(user).toBeInstanceOf(User);
|
|
223
|
+
expect(user.id).toEqual(id);
|
|
224
|
+
expect(user.email).toEqual(email);
|
|
225
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
226
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id != 2 AND u1.email = 'test@test.com') LIMIT 1");
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('When search with $gt and $lt operator', async () => {
|
|
230
|
+
const id = 1;
|
|
231
|
+
const email = 'test@test.com';
|
|
232
|
+
|
|
233
|
+
await User.create({
|
|
234
|
+
email,
|
|
235
|
+
id,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const user = await User.findOneOrFail({
|
|
239
|
+
id: {
|
|
240
|
+
$gt: 0,
|
|
241
|
+
$lt: 2,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
expect(user).toBeInstanceOf(User);
|
|
246
|
+
expect(user.id).toEqual(id);
|
|
247
|
+
expect(user.email).toEqual(email);
|
|
248
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
249
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id > 0 AND u1.id < 2) LIMIT 1");
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test('When search with $gte and $lte operator', async () => {
|
|
253
|
+
const id = 1;
|
|
254
|
+
const email = 'test@test.com';
|
|
255
|
+
|
|
256
|
+
await User.create({
|
|
257
|
+
email,
|
|
258
|
+
id,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const user = await User.findOneOrFail({
|
|
262
|
+
id: {
|
|
263
|
+
$gte: 1,
|
|
264
|
+
$lte: 1,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
expect(user).toBeInstanceOf(User);
|
|
269
|
+
expect(user.id).toEqual(id);
|
|
270
|
+
expect(user.email).toEqual(email);
|
|
271
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
272
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id >= 1 AND u1.id <= 1) LIMIT 1");
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test('When search with $in operator', async () => {
|
|
276
|
+
const user = await createUser();
|
|
277
|
+
|
|
278
|
+
const result = await User.findOneOrFail({
|
|
279
|
+
id: {
|
|
280
|
+
$in: [1, 2],
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
expect(result).toEqual(user);
|
|
285
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
286
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id IN (1, 2)) LIMIT 1");
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
test('When search with $nin operator', async () => {
|
|
290
|
+
const user = await createUser();
|
|
291
|
+
|
|
292
|
+
const result = await User.findOneOrFail({
|
|
293
|
+
id: {
|
|
294
|
+
$nin: [2],
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
expect(result).toEqual(user);
|
|
299
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
300
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (u1.id NOT IN (2)) LIMIT 1");
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test('When search with $or operator', async () => {
|
|
304
|
+
const user = await createUser();
|
|
305
|
+
|
|
306
|
+
const result = await User.findOneOrFail({
|
|
307
|
+
$or: [
|
|
308
|
+
{id: 1},
|
|
309
|
+
{email: 'test_error@test.com'},
|
|
310
|
+
]
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
expect(result).toEqual(user);
|
|
314
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
315
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (((u1.id = 1) OR (u1.email = 'test_error@test.com'))) LIMIT 1");
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('When search with $and operator', async () => {
|
|
319
|
+
const user = await createUser();
|
|
320
|
+
|
|
321
|
+
const result = await User.findOneOrFail({
|
|
322
|
+
$and: [
|
|
323
|
+
{id: 1},
|
|
324
|
+
{email: 'test@test.com'},
|
|
325
|
+
]
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
expect(result).toEqual(user);
|
|
329
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
330
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1 WHERE (((u1.id = 1) AND (u1.email = 'test@test.com'))) LIMIT 1");
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
test('When find all', async () => {
|
|
334
|
+
const user = await createUser();
|
|
335
|
+
|
|
336
|
+
const result = await User.findAll({});
|
|
337
|
+
|
|
338
|
+
expect(result).toEqual([user]);
|
|
339
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
340
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as \"u1_id\", u1.\"email\" as \"u1_email\" FROM \"public\".\"user\" u1");
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('When find with columns defined', async () => {
|
|
344
|
+
await execute(DDL_ADDRESS)
|
|
345
|
+
const user = await createUser();
|
|
346
|
+
const address = await Address.create({
|
|
347
|
+
address: 'Street 1',
|
|
348
|
+
user: user.id,
|
|
349
|
+
id: 1,
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
const result = await User.findOneOrFail({
|
|
353
|
+
addresses: {
|
|
354
|
+
id: 1
|
|
355
|
+
}
|
|
356
|
+
},{fields: ['id', 'addresses.id']});
|
|
357
|
+
|
|
358
|
+
expect(result.id).toEqual(user.id);
|
|
359
|
+
expect(result.email).toBeUndefined();
|
|
360
|
+
expect(result.addresses[0].id).toEqual(address.id);
|
|
361
|
+
expect(result.addresses[0].address).toBeUndefined();
|
|
362
|
+
expect(mockLogger).toHaveBeenCalledTimes(3);
|
|
363
|
+
expect((mockLogger as jest.Mock).mock.calls[2][0]).toStartWith("SQL: SELECT u1.\"id\" as u1_id, a1.\"id\" as a1_id FROM \"public\".\"user\" u1 LEFT JOIN public.address a1 ON a1.user = u1.id WHERE ((a1.id = 1)) LIMIT 1");
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
test('When find with orderBy defined', async () => {
|
|
367
|
+
await execute(DDL_ADDRESS)
|
|
368
|
+
const user = await createUser();
|
|
369
|
+
const address = await Address.create({
|
|
370
|
+
address: 'Street 1',
|
|
371
|
+
user: user.id,
|
|
372
|
+
id: 1,
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const result = await User.findOneOrFail({
|
|
376
|
+
addresses: {
|
|
377
|
+
id: 1
|
|
378
|
+
}
|
|
379
|
+
},{fields: ['id', 'addresses.id'], orderBy: {id: 'DESC', addresses: {address: 'DESC'}}});
|
|
380
|
+
|
|
381
|
+
expect(result.id).toEqual(user.id);
|
|
382
|
+
expect(mockLogger).toHaveBeenCalledTimes(3);
|
|
383
|
+
expect((mockLogger as jest.Mock).mock.calls[2][0]).toStartWith("SQL: SELECT u1.\"id\" as u1_id, a1.\"id\" as a1_id FROM \"public\".\"user\" u1 LEFT JOIN public.address a1 ON a1.user = u1.id WHERE ((a1.id = 1)) ORDER BY u1.\"id\" DESC, a1.\"address\" DESC LIMIT 1");
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
test('When find with limit defined', async () => {
|
|
387
|
+
const user = await createUser();
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
const result = await User.find({},{
|
|
391
|
+
fields: ['id'],
|
|
392
|
+
limit: 1,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
expect(result.length).toEqual(1)
|
|
396
|
+
expect(result[0].id).toEqual(user.id);
|
|
397
|
+
expect(mockLogger).toHaveBeenCalledTimes(2);
|
|
398
|
+
expect((mockLogger as jest.Mock).mock.calls[1][0]).toStartWith("SQL: SELECT u1.\"id\" as u1_id FROM \"public\".\"user\" u1 LIMIT 1");
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
test('When find with offset defined', async () => {
|
|
402
|
+
await createUser();
|
|
403
|
+
const user2 = await User.create({
|
|
404
|
+
email: 'test2@test.com',
|
|
405
|
+
id: 2,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const result = await User.find({},{
|
|
409
|
+
fields: ['id'],
|
|
410
|
+
offset: 1,
|
|
411
|
+
limit: 1,
|
|
412
|
+
orderBy: {id: 'ASC'}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
expect(result[0].id).toEqual(user2.id);
|
|
416
|
+
expect(mockLogger).toHaveBeenCalledTimes(3);
|
|
417
|
+
expect((mockLogger as jest.Mock).mock.calls[2][0]).toStartWith("SQL: SELECT u1.\"id\" as u1_id FROM \"public\".\"user\" u1 ORDER BY u1.\"id\" ASC OFFSET 1 LIMIT 1");
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
test('When use a querybuilder', async() => {
|
|
421
|
+
const created = await app.createQueryBuilder<User>(User)
|
|
422
|
+
.insert({id: 1, email: 'test@test.com'})
|
|
423
|
+
.executeAndReturnFirst()
|
|
424
|
+
|
|
425
|
+
expect(created).toBeInstanceOf(User);
|
|
426
|
+
expect(created!.id).toEqual(1);
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
test('When have update column and default column', async() => {
|
|
430
|
+
const dateNow = new Date();
|
|
431
|
+
setSystemTime(dateNow)
|
|
432
|
+
|
|
433
|
+
const DLL = `
|
|
434
|
+
CREATE TABLE "usertest"
|
|
435
|
+
(
|
|
436
|
+
"id" SERIAL PRIMARY KEY,
|
|
437
|
+
"createdAt" timestamp,
|
|
438
|
+
"updatedAt" timestamp
|
|
439
|
+
);
|
|
440
|
+
`;
|
|
441
|
+
|
|
442
|
+
await purgeDatabase()
|
|
443
|
+
await startDatabase(import.meta.path)
|
|
444
|
+
await execute(DLL)
|
|
445
|
+
|
|
446
|
+
Entity()(UserTest)
|
|
447
|
+
const created = await UserTest.create({
|
|
448
|
+
id: 1
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
expect(created).toBeInstanceOf(UserTest);
|
|
452
|
+
expect(created!.id).toEqual(1);
|
|
453
|
+
expect(created!.createdAt).toEqual(dateNow);
|
|
454
|
+
expect(created!.updatedAt).toEqual(dateNow);
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
async function createUser() {
|
|
458
|
+
return User.create({
|
|
459
|
+
email: 'test@test.com',
|
|
460
|
+
id: 1,
|
|
461
|
+
})
|
|
462
|
+
}
|
|
463
|
+
})
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
CREATE TABLE "public"."user" ("id" numeric(11) NOT NULL PRIMARY KEY UNIQUE,"email" character varying(255) NOT NULL);
|
|
2
|
+
CREATE INDEX "id_email_index" ON "public"."user" ("id", "email");
|
|
3
|
+
CREATE INDEX "email_index" ON "public"."user" ("email");
|
|
4
|
+
CREATE TABLE "public"."address" ("id" numeric(11) NOT NULL PRIMARY KEY UNIQUE,"user" numeric(11) NOT NULL);
|
|
5
|
+
ALTER TABLE "public"."address" ADD CONSTRAINT "address_user_fk" FOREIGN KEY ("user") REFERENCES "user" ("id");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PgDriver } from '@cheetah.js/orm';
|
|
2
|
+
|
|
3
|
+
const config = {
|
|
4
|
+
host: 'localhost',
|
|
5
|
+
port: 5432,
|
|
6
|
+
database: 'postgres',
|
|
7
|
+
username: 'postgres',
|
|
8
|
+
password: 'postgres',
|
|
9
|
+
driver: PgDriver,
|
|
10
|
+
migrationPath: '/packages/orm/test/migration'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default config;
|