orchid-orm 1.4.17 → 1.4.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.
@@ -0,0 +1,647 @@
1
+ import fs from 'fs/promises';
2
+ import { asMock, ast, makeTestWritten, tablePath } from '../testUtils';
3
+ import { updateTableFile } from './updateTableFile';
4
+ import path from 'path';
5
+ import { columnTypes, newTableData, TableData } from 'pqb';
6
+ import { RakeDbAst } from 'rake-db';
7
+
8
+ jest.mock('fs/promises', () => ({
9
+ readFile: jest.fn(),
10
+ writeFile: jest.fn(),
11
+ }));
12
+
13
+ const baseTablePath = path.resolve('baseTable.ts');
14
+ const baseTableName = 'BaseTable';
15
+ const params = { baseTablePath, baseTableName, tablePath };
16
+ const t = columnTypes;
17
+
18
+ const testWritten = makeTestWritten(tablePath('table'));
19
+
20
+ const tableData = newTableData();
21
+
22
+ const change = (
23
+ data: Partial<RakeDbAst.ChangeTableItem.Change>,
24
+ ): RakeDbAst.ChangeTableItem.Change => ({
25
+ type: 'change',
26
+ from: {},
27
+ to: {},
28
+ ...data,
29
+ });
30
+
31
+ class Table {
32
+ table = 'table';
33
+ }
34
+
35
+ describe('updateTableFile', () => {
36
+ beforeEach(() => {
37
+ jest.resetAllMocks();
38
+ });
39
+
40
+ it('should add a single column into empty columns list', async () => {
41
+ asMock(fs.readFile)
42
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
43
+
44
+ export class Table extends BaseTable {
45
+ table = 'table';
46
+ columns = this.setColumns((t) => ({}));
47
+ }`);
48
+
49
+ await updateTableFile({
50
+ ...params,
51
+ ast: {
52
+ ...ast.changeTable,
53
+ shape: {
54
+ name: { type: 'add', item: t.text(1, 10) },
55
+ },
56
+ },
57
+ });
58
+
59
+ testWritten(`import { BaseTable } from '../baseTable';
60
+
61
+ export class Table extends BaseTable {
62
+ table = 'table';
63
+ columns = this.setColumns((t) => ({
64
+ name: t.text(1, 10),
65
+ }));
66
+ }`);
67
+ });
68
+
69
+ it('should add a single column', async () => {
70
+ asMock(fs.readFile)
71
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
72
+
73
+ export class Table extends BaseTable {
74
+ table = 'table';
75
+ columns = this.setColumns((t) => ({
76
+ id: t.serial().primaryKey(),
77
+ }));
78
+ }`);
79
+
80
+ await updateTableFile({
81
+ ...params,
82
+ ast: {
83
+ ...ast.changeTable,
84
+ shape: {
85
+ name: { type: 'add', item: t.text(1, 10) },
86
+ },
87
+ },
88
+ });
89
+
90
+ testWritten(`import { BaseTable } from '../baseTable';
91
+
92
+ export class Table extends BaseTable {
93
+ table = 'table';
94
+ columns = this.setColumns((t) => ({
95
+ id: t.serial().primaryKey(),
96
+ name: t.text(1, 10),
97
+ }));
98
+ }`);
99
+ });
100
+
101
+ it('should add multiple column', async () => {
102
+ asMock(fs.readFile)
103
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
104
+
105
+ export class Table extends BaseTable {
106
+ table = 'table';
107
+ columns = this.setColumns((t) => ({
108
+ id: t.serial().primaryKey(),
109
+ }));
110
+ }`);
111
+
112
+ await updateTableFile({
113
+ ...params,
114
+ ast: {
115
+ ...ast.changeTable,
116
+ shape: {
117
+ name: { type: 'add', item: t.text(1, 10) },
118
+ active: { type: 'add', item: t.boolean() },
119
+ },
120
+ },
121
+ });
122
+
123
+ testWritten(`import { BaseTable } from '../baseTable';
124
+
125
+ export class Table extends BaseTable {
126
+ table = 'table';
127
+ columns = this.setColumns((t) => ({
128
+ id: t.serial().primaryKey(),
129
+ name: t.text(1, 10),
130
+ active: t.boolean(),
131
+ }));
132
+ }`);
133
+ });
134
+
135
+ it('should insert ending comma before adding', async () => {
136
+ asMock(fs.readFile)
137
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
138
+
139
+ export class Table extends BaseTable {
140
+ table = 'table';
141
+ columns = this.setColumns((t) => ({
142
+ id: t.serial().primaryKey()
143
+ }));
144
+ }`);
145
+
146
+ await updateTableFile({
147
+ ...params,
148
+ ast: {
149
+ ...ast.changeTable,
150
+ shape: {
151
+ name: { type: 'add', item: t.text(1, 10) },
152
+ active: { type: 'add', item: t.boolean() },
153
+ },
154
+ },
155
+ });
156
+
157
+ testWritten(`import { BaseTable } from '../baseTable';
158
+
159
+ export class Table extends BaseTable {
160
+ table = 'table';
161
+ columns = this.setColumns((t) => ({
162
+ id: t.serial().primaryKey(),
163
+ name: t.text(1, 10),
164
+ active: t.boolean(),
165
+ }));
166
+ }`);
167
+ });
168
+
169
+ it('should drop column', async () => {
170
+ asMock(fs.readFile)
171
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
172
+
173
+ export class Table extends BaseTable {
174
+ table = 'table';
175
+ columns = this.setColumns((t) => ({
176
+ id: t.serial().primaryKey(),
177
+ name: t.text(),
178
+ active: t.boolean(),
179
+ }));
180
+ }`);
181
+
182
+ await updateTableFile({
183
+ ...params,
184
+ ast: {
185
+ ...ast.changeTable,
186
+ shape: {
187
+ name: { type: 'drop', item: t.text(1, 10) },
188
+ },
189
+ },
190
+ });
191
+
192
+ testWritten(`import { BaseTable } from '../baseTable';
193
+
194
+ export class Table extends BaseTable {
195
+ table = 'table';
196
+ columns = this.setColumns((t) => ({
197
+ id: t.serial().primaryKey(),
198
+ active: t.boolean(),
199
+ }));
200
+ }`);
201
+ });
202
+
203
+ it('should drop column at the end', async () => {
204
+ asMock(fs.readFile)
205
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
206
+
207
+ export class Table extends BaseTable {
208
+ table = 'table';
209
+ columns = this.setColumns((t) => ({
210
+ id: t.serial().primaryKey(),
211
+ name: t.text(),
212
+ }));
213
+ }`);
214
+
215
+ await updateTableFile({
216
+ ...params,
217
+ ast: {
218
+ ...ast.changeTable,
219
+ shape: {
220
+ name: { type: 'drop', item: t.text(1, 10) },
221
+ },
222
+ },
223
+ });
224
+
225
+ testWritten(`import { BaseTable } from '../baseTable';
226
+
227
+ export class Table extends BaseTable {
228
+ table = 'table';
229
+ columns = this.setColumns((t) => ({
230
+ id: t.serial().primaryKey(),
231
+ }));
232
+ }`);
233
+ });
234
+
235
+ it('should change column type', async () => {
236
+ asMock(fs.readFile)
237
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
238
+
239
+ export class Table extends BaseTable {
240
+ table = 'table';
241
+ columns = this.setColumns((t) => ({
242
+ name: t.integer(),
243
+ }));
244
+ }`);
245
+
246
+ await updateTableFile({
247
+ ...params,
248
+ ast: {
249
+ ...ast.changeTable,
250
+ shape: {
251
+ name: {
252
+ type: 'change',
253
+ from: {},
254
+ to: {
255
+ column: t.text(1, 10),
256
+ type: 'text',
257
+ },
258
+ },
259
+ },
260
+ },
261
+ });
262
+
263
+ testWritten(`import { BaseTable } from '../baseTable';
264
+
265
+ export class Table extends BaseTable {
266
+ table = 'table';
267
+ columns = this.setColumns((t) => ({
268
+ name: t.text(1, 10),
269
+ }));
270
+ }`);
271
+ });
272
+
273
+ it('should change properties', async () => {
274
+ asMock(fs.readFile)
275
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
276
+
277
+ export class Table extends BaseTable {
278
+ table = 'table';
279
+ columns = this.setColumns((t) => ({
280
+ changeCollate: t.text().collate('one'),
281
+ addCollate: t.text(),
282
+ dropCollate: t.text().collate('one'),
283
+ changeDefault: t.text().default('one'),
284
+ addDefault: t.text(),
285
+ dropDefault: t.text().default('one'),
286
+ addNullable: t.text(),
287
+ dropNullable: t.text().nullable(),
288
+ changeCompression: t.text().compression('one'),
289
+ addCompression: t.text(),
290
+ dropCompression: t.text().compression('one'),
291
+ addPrimaryKey: t.text(),
292
+ dropPrimaryKey: t.text().primaryKey(),
293
+ }));
294
+ }`);
295
+
296
+ await updateTableFile({
297
+ ...params,
298
+ ast: {
299
+ ...ast.changeTable,
300
+ shape: {
301
+ changeCollate: change({ to: { collate: 'two' } }),
302
+ addCollate: change({ to: { collate: 'two' } }),
303
+ dropCollate: change({ from: { collate: 'two' } }),
304
+ changeDefault: change({ to: { default: 'two' } }),
305
+ addDefault: change({ to: { default: 'two' } }),
306
+ dropDefault: change({ from: { default: 'two' } }),
307
+ addNullable: change({ to: { nullable: true } }),
308
+ dropNullable: change({ from: { nullable: true } }),
309
+ changeCompression: change({ to: { compression: 'two' } }),
310
+ addCompression: change({ to: { compression: 'two' } }),
311
+ dropCompression: change({ from: { compression: 'two' } }),
312
+ addPrimaryKey: change({ to: { primaryKey: true } }),
313
+ dropPrimaryKey: change({ from: { primaryKey: true } }),
314
+ },
315
+ },
316
+ });
317
+
318
+ testWritten(`import { BaseTable } from '../baseTable';
319
+
320
+ export class Table extends BaseTable {
321
+ table = 'table';
322
+ columns = this.setColumns((t) => ({
323
+ changeCollate: t.text().collate('two'),
324
+ addCollate: t.text().collate('two'),
325
+ dropCollate: t.text(),
326
+ changeDefault: t.text().default('two'),
327
+ addDefault: t.text().default('two'),
328
+ dropDefault: t.text(),
329
+ addNullable: t.text().nullable(),
330
+ dropNullable: t.text(),
331
+ changeCompression: t.text().compression('two'),
332
+ addCompression: t.text().compression('two'),
333
+ dropCompression: t.text(),
334
+ addPrimaryKey: t.text().primaryKey(),
335
+ dropPrimaryKey: t.text(),
336
+ }));
337
+ }`);
338
+ });
339
+
340
+ describe('primaryKey', () => {
341
+ const result = `import { BaseTable } from '../baseTable';
342
+
343
+ export class Table extends BaseTable {
344
+ table = 'table';
345
+ columns = this.setColumns((t) => ({
346
+ ...t.primaryKey(['one', 'two'], { name: 'name' }),
347
+ }));
348
+ }`;
349
+
350
+ const add = {
351
+ ...tableData,
352
+ primaryKey: {
353
+ columns: ['one', 'two'],
354
+ options: { name: 'name' },
355
+ },
356
+ };
357
+
358
+ it('should change primaryKey', async () => {
359
+ asMock(fs.readFile)
360
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
361
+
362
+ export class Table extends BaseTable {
363
+ table = 'table';
364
+ columns = this.setColumns((t) => ({
365
+ ...t.primaryKey(['foo', 'bar'], { name: 'baz' }),
366
+ }));
367
+ }`);
368
+
369
+ await updateTableFile({
370
+ ...params,
371
+ ast: {
372
+ ...ast.changeTable,
373
+ add,
374
+ },
375
+ });
376
+
377
+ testWritten(result);
378
+ });
379
+
380
+ it('should add primaryKey', async () => {
381
+ asMock(fs.readFile)
382
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
383
+
384
+ export class Table extends BaseTable {
385
+ table = 'table';
386
+ columns = this.setColumns((t) => ({
387
+ }));
388
+ }`);
389
+
390
+ await updateTableFile({
391
+ ...params,
392
+ ast: {
393
+ ...ast.changeTable,
394
+ add,
395
+ },
396
+ });
397
+
398
+ testWritten(result);
399
+ });
400
+ });
401
+
402
+ describe('indexes', () => {
403
+ const result = `import { BaseTable } from '../baseTable';
404
+
405
+ export class Table extends BaseTable {
406
+ table = 'table';
407
+ columns = this.setColumns((t) => ({
408
+ ...t.index(['6']),
409
+ ...t.index(['7', '8']),
410
+ ...t.index(
411
+ [
412
+ '9',
413
+ {
414
+ column: '10',
415
+ expression: 321,
416
+ order: 'new',
417
+ },
418
+ ],
419
+ {
420
+ name: 'newName',
421
+ },
422
+ ),
423
+ }));
424
+ }`;
425
+
426
+ const add = {
427
+ ...tableData,
428
+ indexes: [
429
+ {
430
+ columns: [{ column: '6' }],
431
+ options: {},
432
+ },
433
+ {
434
+ columns: [{ column: '7' }, { column: '8' }],
435
+ options: {},
436
+ },
437
+ {
438
+ columns: [
439
+ { column: '9' },
440
+ { column: '10', order: 'new', expression: 321 },
441
+ ],
442
+ options: { name: 'newName' },
443
+ },
444
+ ],
445
+ };
446
+
447
+ it('should change indexes', async () => {
448
+ asMock(fs.readFile)
449
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
450
+
451
+ export class Table extends BaseTable {
452
+ table = 'table';
453
+ columns = this.setColumns((t) => ({
454
+ ...t.index('1'),
455
+ ...t.index(['2', '3']),
456
+ ...t.index(['4', { column: '5', order: 'order', expression: 123 }], { name: 'indexName' }),
457
+ }));
458
+ }`);
459
+
460
+ await updateTableFile({
461
+ ...params,
462
+ ast: {
463
+ ...ast.changeTable,
464
+ drop: {
465
+ ...tableData,
466
+ indexes: [
467
+ {
468
+ columns: [{ column: '1' }],
469
+ options: {},
470
+ },
471
+ {
472
+ columns: [{ column: '2' }, { column: '3' }],
473
+ options: {},
474
+ },
475
+ {
476
+ columns: [
477
+ { column: '4' },
478
+ { column: '5', order: 'order', expression: 123 },
479
+ ],
480
+ options: { name: 'indexName' },
481
+ },
482
+ ],
483
+ },
484
+ add,
485
+ },
486
+ });
487
+
488
+ testWritten(result);
489
+ });
490
+
491
+ it('should add indexes', async () => {
492
+ asMock(fs.readFile)
493
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
494
+
495
+ export class Table extends BaseTable {
496
+ table = 'table';
497
+ columns = this.setColumns((t) => ({
498
+ }));
499
+ }`);
500
+
501
+ await updateTableFile({
502
+ ...params,
503
+ ast: {
504
+ ...ast.changeTable,
505
+ add,
506
+ },
507
+ });
508
+
509
+ testWritten(result);
510
+ });
511
+ });
512
+
513
+ describe('foreignKeys', () => {
514
+ const result = `import { BaseTable } from '../baseTable';
515
+
516
+ export class Table extends BaseTable {
517
+ table = 'table';
518
+ columns = this.setColumns((t) => ({
519
+ ...t.foreignKey(
520
+ ['7'],
521
+ 'table',
522
+ ['8'],
523
+ {
524
+ name: 'first',
525
+ match: 'PARTIAL',
526
+ },
527
+ ),
528
+ ...t.foreignKey(
529
+ ['9', '10'],
530
+ ()=>Table,
531
+ ['11', '12'],
532
+ {
533
+ name: 'second',
534
+ match: 'SIMPLE',
535
+ onUpdate: 'NO ACTION',
536
+ },
537
+ ),
538
+ }));
539
+ }`;
540
+
541
+ const add = {
542
+ ...tableData,
543
+ foreignKeys: [
544
+ {
545
+ columns: ['7'],
546
+ fnOrTable: 'table',
547
+ foreignColumns: ['8'],
548
+ options: {
549
+ name: 'first',
550
+ match: 'PARTIAL',
551
+ },
552
+ },
553
+ {
554
+ columns: ['9', '10'],
555
+ fnOrTable: () => Table,
556
+ foreignColumns: ['11', '12'],
557
+ options: {
558
+ name: 'second',
559
+ match: 'SIMPLE',
560
+ onUpdate: 'NO ACTION',
561
+ },
562
+ },
563
+ ],
564
+ };
565
+
566
+ it('should change foreignKeys', async () => {
567
+ asMock(fs.readFile)
568
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
569
+
570
+ export class Table extends BaseTable {
571
+ table = 'table';
572
+ columns = this.setColumns((t) => ({
573
+ ...t.foreignKey(
574
+ ['1'],
575
+ () => Table,
576
+ ['2'],
577
+ ),
578
+ ...t.foreignKey(
579
+ ['3', '4'],
580
+ 'table',
581
+ ['5', '6'],
582
+ {
583
+ name: 'foreignKeyName',
584
+ match: 'FULL',
585
+ onUpdate: 'CASCADE',
586
+ onDelete: 'CASCADE',
587
+ },
588
+ ),
589
+ }));
590
+ }`);
591
+
592
+ await updateTableFile({
593
+ ...params,
594
+ ast: {
595
+ ...ast.changeTable,
596
+ drop: {
597
+ ...tableData,
598
+ foreignKeys: [
599
+ {
600
+ columns: ['1'],
601
+ fnOrTable: () => Table,
602
+ foreignColumns: ['2'],
603
+ options: {},
604
+ },
605
+ {
606
+ columns: ['3', '4'],
607
+ fnOrTable: 'table',
608
+ foreignColumns: ['5', '6'],
609
+ options: {
610
+ name: 'foreignKeyName',
611
+ match: 'FULL',
612
+ onUpdate: 'CASCADE',
613
+ onDelete: 'CASCADE',
614
+ dropMode: 'CASCADE',
615
+ },
616
+ },
617
+ ],
618
+ },
619
+ add: add as TableData,
620
+ },
621
+ });
622
+
623
+ testWritten(result);
624
+ });
625
+
626
+ it('should add foreignKeys', async () => {
627
+ asMock(fs.readFile)
628
+ .mockResolvedValue(`import { BaseTable } from '../baseTable';
629
+
630
+ export class Table extends BaseTable {
631
+ table = 'table';
632
+ columns = this.setColumns((t) => ({
633
+ }));
634
+ }`);
635
+
636
+ await updateTableFile({
637
+ ...params,
638
+ ast: {
639
+ ...ast.changeTable,
640
+ add: add as TableData,
641
+ },
642
+ });
643
+
644
+ testWritten(result);
645
+ });
646
+ });
647
+ });