orchid-orm 1.5.11 → 1.5.12

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,736 @@
1
+ import { initOrchidORM } from './init';
2
+ import fs from 'fs/promises';
3
+ import { asMock } from '../codegen/testUtils';
4
+ import path from 'path';
5
+
6
+ jest.mock('https', () => ({
7
+ get(
8
+ this: { result: string },
9
+ _: string,
10
+ cb: (res: {
11
+ on(event: string, cb: (chunk?: string) => void): void;
12
+ }) => void,
13
+ ) {
14
+ cb({
15
+ on: (event: string, cb: (chunk?: string) => void) => {
16
+ if (event === 'data') {
17
+ cb(`{"version":"1.2.3"}`);
18
+ } else if (event === 'end') {
19
+ cb();
20
+ }
21
+ },
22
+ });
23
+ },
24
+ }));
25
+
26
+ jest.mock('fs/promises', () => ({
27
+ readFile: jest.fn(),
28
+ writeFile: jest.fn(),
29
+ mkdir: jest.fn(),
30
+ }));
31
+
32
+ class EnoentError extends Error {
33
+ code = 'ENOENT';
34
+ }
35
+
36
+ const packageJSONPath = path.resolve(process.cwd(), 'package.json');
37
+ const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json');
38
+ const envPath = path.resolve(process.cwd(), '.env');
39
+ const gitignorePath = path.resolve(process.cwd(), '.gitignore');
40
+ const dbDirPath = path.resolve(process.cwd(), 'src', 'db');
41
+ const baseTablePath = path.resolve(dbDirPath, 'baseTable.ts');
42
+ const tablesDir = path.resolve(dbDirPath, 'tables');
43
+ const postTablePath = path.resolve(tablesDir, 'post.table.ts');
44
+ const commentTablePath = path.resolve(tablesDir, 'comment.table.ts');
45
+ const configPath = path.join(dbDirPath, 'config.ts');
46
+ const dbPath = path.join(dbDirPath, 'db.ts');
47
+ const migrationScriptPath = path.join(dbDirPath, 'dbScripts.ts');
48
+ const migrationsPath = path.join(dbDirPath, 'migrations');
49
+
50
+ describe('initOrchidORM', () => {
51
+ beforeEach(jest.clearAllMocks);
52
+
53
+ it('should create db directory', async () => {
54
+ await initOrchidORM({});
55
+
56
+ expect(fs.mkdir).toBeCalledWith(dbDirPath, { recursive: true });
57
+ });
58
+
59
+ describe('package.json', () => {
60
+ const packageJSONWithoutAdditional = `{
61
+ "scripts": {
62
+ "db": "ts-node src/db/dbScripts.ts"
63
+ },
64
+ "dependencies": {
65
+ "dotenv": "^1.2.3",
66
+ "orchid-orm": "^1.2.3",
67
+ "pqb": "^1.2.3"
68
+ },
69
+ "devDependencies": {
70
+ "rake-db": "^1.2.3",
71
+ "@swc/core": "^1.2.3",
72
+ "@types/node": "^1.2.3",
73
+ "ts-node": "^1.2.3",
74
+ "typescript": "^1.2.3"
75
+ }
76
+ }
77
+ `;
78
+
79
+ const fullPackageJSON = `{
80
+ "scripts": {
81
+ "db": "ts-node src/db/dbScripts.ts"
82
+ },
83
+ "dependencies": {
84
+ "dotenv": "^1.2.3",
85
+ "orchid-orm": "^1.2.3",
86
+ "pqb": "^1.2.3",
87
+ "orchid-orm-schema-to-zod": "^1.2.3"
88
+ },
89
+ "devDependencies": {
90
+ "rake-db": "^1.2.3",
91
+ "orchid-orm-test-factory": "^1.2.3",
92
+ "@swc/core": "^1.2.3",
93
+ "@types/node": "^1.2.3",
94
+ "ts-node": "^1.2.3",
95
+ "typescript": "^1.2.3"
96
+ }
97
+ }
98
+ `;
99
+
100
+ it('should create package.json if not exist', async () => {
101
+ asMock(fs.readFile).mockImplementation((path: string) => {
102
+ if (path.endsWith('package.json')) {
103
+ throw new EnoentError();
104
+ }
105
+ });
106
+
107
+ await initOrchidORM({});
108
+
109
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
110
+ ([to]) => to === packageJSONPath,
111
+ );
112
+ expect(content).toBe(packageJSONWithoutAdditional);
113
+ });
114
+
115
+ it('should create package.json with additional deps if not exist', async () => {
116
+ asMock(fs.readFile).mockImplementation((path: string) => {
117
+ if (path.endsWith('package.json')) {
118
+ throw new EnoentError();
119
+ }
120
+ });
121
+
122
+ await initOrchidORM({
123
+ addSchemaToZod: true,
124
+ addTestFactory: true,
125
+ });
126
+
127
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
128
+ ([to]) => to === packageJSONPath,
129
+ );
130
+ expect(content).toBe(fullPackageJSON);
131
+ });
132
+
133
+ it('should add scripts, dependencies and devDependencies if they are not present in package.json', async () => {
134
+ asMock(fs.readFile).mockImplementation((path: string) => {
135
+ if (path.endsWith('package.json')) {
136
+ return '{}';
137
+ }
138
+ return;
139
+ });
140
+
141
+ await initOrchidORM({
142
+ addSchemaToZod: true,
143
+ addTestFactory: true,
144
+ });
145
+
146
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
147
+ ([to]) => to === packageJSONPath,
148
+ );
149
+ expect(content).toBe(fullPackageJSON);
150
+ });
151
+
152
+ it('should insert scripts and dependencies', async () => {
153
+ asMock(fs.readFile).mockImplementation((path: string) => {
154
+ if (path.endsWith('package.json')) {
155
+ return `{
156
+ "scripts": {
157
+ "ko": "ko"
158
+ },
159
+ "dependencies": {
160
+ "ko": "ko"
161
+ },
162
+ "devDependencies": {
163
+ "ko": "ko"
164
+ }
165
+ }`;
166
+ }
167
+ return;
168
+ });
169
+
170
+ await initOrchidORM({
171
+ addSchemaToZod: true,
172
+ addTestFactory: true,
173
+ });
174
+
175
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
176
+ ([to]) => to === packageJSONPath,
177
+ );
178
+ expect(content).toBe(
179
+ `{
180
+ "scripts": {
181
+ "ko": "ko",
182
+ "db": "ts-node src/db/dbScripts.ts"
183
+ },
184
+ "dependencies": {
185
+ "ko": "ko",
186
+ "dotenv": "^1.2.3",
187
+ "orchid-orm": "^1.2.3",
188
+ "pqb": "^1.2.3",
189
+ "orchid-orm-schema-to-zod": "^1.2.3"
190
+ },
191
+ "devDependencies": {
192
+ "ko": "ko",
193
+ "rake-db": "^1.2.3",
194
+ "orchid-orm-test-factory": "^1.2.3",
195
+ "@swc/core": "^1.2.3",
196
+ "@types/node": "^1.2.3",
197
+ "ts-node": "^1.2.3",
198
+ "typescript": "^1.2.3"
199
+ }
200
+ }
201
+ `,
202
+ );
203
+ });
204
+ });
205
+
206
+ describe('tsconfig.json', () => {
207
+ it('should create tsconfig.json if not not exist', async () => {
208
+ await initOrchidORM({});
209
+
210
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
211
+ ([to]) => to === tsConfigPath,
212
+ );
213
+ expect(content).toBe(`{
214
+ "ts-node": {
215
+ "swc": true
216
+ },
217
+ "compilerOptions": {
218
+ "strict": true
219
+ }
220
+ }
221
+ `);
222
+ });
223
+
224
+ it('should update tsconfig.json if it exists', async () => {
225
+ asMock(fs.readFile).mockImplementation((path: string) => {
226
+ if (path.endsWith('tsconfig.json')) {
227
+ return `{"compilerOptions":{"ko":"ko"}}`;
228
+ }
229
+ return;
230
+ });
231
+
232
+ await initOrchidORM({});
233
+
234
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
235
+ ([to]) => to === tsConfigPath,
236
+ );
237
+ expect(content).toBe(`{
238
+ "compilerOptions": {
239
+ "ko": "ko",
240
+ "strict": true
241
+ },
242
+ "ts-node": {
243
+ "swc": true
244
+ }
245
+ }
246
+ `);
247
+ });
248
+ });
249
+
250
+ describe('.env', () => {
251
+ it('should create .env if not exist', async () => {
252
+ asMock(fs.readFile).mockImplementation((path: string) => {
253
+ if (path.endsWith('.env')) {
254
+ throw new EnoentError();
255
+ }
256
+ });
257
+
258
+ await initOrchidORM({});
259
+
260
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
261
+ ([to]) => to === envPath,
262
+ );
263
+ expect(content)
264
+ .toBe(`DATABASE_URL=postgres://user:password@localhost:5432/dbname?ssl=false
265
+ `);
266
+ });
267
+
268
+ it('should append DATABASE_URL to existing .env', async () => {
269
+ asMock(fs.readFile).mockImplementation((path: string) => {
270
+ if (path.endsWith('.env')) {
271
+ return 'KO=KO';
272
+ }
273
+ return '';
274
+ });
275
+
276
+ await initOrchidORM({});
277
+
278
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
279
+ ([to]) => to === envPath,
280
+ );
281
+ expect(content).toBe(`KO=KO
282
+ DATABASE_URL=postgres://user:password@localhost:5432/dbname?ssl=false
283
+ `);
284
+ });
285
+
286
+ it('should append DATABASE_TEST_URL if testDatabase specified', async () => {
287
+ asMock(fs.readFile).mockImplementation((path: string) => {
288
+ if (path.endsWith('.env')) {
289
+ return 'KO=KO';
290
+ }
291
+ return '';
292
+ });
293
+
294
+ await initOrchidORM({
295
+ testDatabase: true,
296
+ });
297
+
298
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
299
+ ([to]) => to === envPath,
300
+ );
301
+ expect(content).toBe(`KO=KO
302
+ DATABASE_URL=postgres://user:password@localhost:5432/dbname?ssl=false
303
+ DATABASE_TEST_URL=postgres://user:password@localhost:5432/dbname-test?ssl=false
304
+ `);
305
+ });
306
+ });
307
+
308
+ describe('.gitignore', () => {
309
+ it('should create .gitignore if not exists', async () => {
310
+ asMock(fs.readFile).mockImplementation((path: string) => {
311
+ if (path.endsWith('.gitignore')) {
312
+ throw new EnoentError();
313
+ }
314
+ });
315
+
316
+ await initOrchidORM({});
317
+
318
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
319
+ ([to]) => to === gitignorePath,
320
+ );
321
+ expect(content).toBe(`node_modules
322
+ .env
323
+ `);
324
+ });
325
+
326
+ it('should append missing entries if .gitignore exists', async () => {
327
+ asMock(fs.readFile).mockImplementation((path: string) => {
328
+ if (path.endsWith('.gitignore')) {
329
+ return 'node_modules/\nko';
330
+ }
331
+ return;
332
+ });
333
+
334
+ await initOrchidORM({});
335
+
336
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
337
+ ([to]) => to === gitignorePath,
338
+ );
339
+ expect(content).toBe(`node_modules/
340
+ ko
341
+ .env
342
+ `);
343
+ });
344
+ });
345
+
346
+ describe('baseTable', () => {
347
+ it('should create base table', async () => {
348
+ await initOrchidORM({});
349
+
350
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
351
+ ([to]) => to === baseTablePath,
352
+ );
353
+ expect(content).toBe(`import { createBaseTable } from 'orchid-orm';
354
+
355
+ export const BaseTable = createBaseTable({
356
+ columnTypes: (t) => ({
357
+ text: (min: 0, max: Infinity) => t.text(min, max),
358
+ }),
359
+ });
360
+ `);
361
+ });
362
+
363
+ it('should create base table with timestamp as date', async () => {
364
+ await initOrchidORM({
365
+ timestamp: 'date',
366
+ });
367
+
368
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
369
+ ([to]) => to === baseTablePath,
370
+ );
371
+ expect(content).toBe(`import { createBaseTable } from 'orchid-orm';
372
+
373
+ export const BaseTable = createBaseTable({
374
+ columnTypes: (t) => ({
375
+ text: (min: 0, max: Infinity) => t.text(min, max),
376
+ timestamp: <P extends number>(precision?: P) => t.timestamp<P>(precision).asDate(),
377
+ }),
378
+ });
379
+ `);
380
+ });
381
+
382
+ it('should create base table with timestamp as number', async () => {
383
+ await initOrchidORM({
384
+ timestamp: 'number',
385
+ });
386
+
387
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
388
+ ([to]) => to === baseTablePath,
389
+ );
390
+ expect(content).toBe(`import { createBaseTable } from 'orchid-orm';
391
+
392
+ export const BaseTable = createBaseTable({
393
+ columnTypes: (t) => ({
394
+ text: (min: 0, max: Infinity) => t.text(min, max),
395
+ timestamp: <P extends number>(precision?: P) => t.timestamp<P>(precision).asNumber(),
396
+ }),
397
+ });
398
+ `);
399
+ });
400
+ });
401
+
402
+ describe('tables', () => {
403
+ it('should do nothing if demoTables is not specified', async () => {
404
+ await initOrchidORM({});
405
+
406
+ expect(fs.mkdir).not.toBeCalledWith(tablesDir, { recursive: true });
407
+ });
408
+
409
+ it('should create tables dir', async () => {
410
+ await initOrchidORM({
411
+ demoTables: true,
412
+ });
413
+
414
+ expect(fs.mkdir).toBeCalledWith(tablesDir, { recursive: true });
415
+ });
416
+
417
+ it('should create post table', async () => {
418
+ await initOrchidORM({
419
+ demoTables: true,
420
+ });
421
+
422
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
423
+ ([to]) => to === postTablePath,
424
+ );
425
+ expect(content).toBe(`import { BaseTable } from '../baseTable';
426
+ import { CommentTable } from './comment.table';
427
+
428
+ export type Post = PostTable['columns']['type'];
429
+ class PostTable extends BaseTable {
430
+ table = 'post';
431
+ columns = this.setColumns((t) => ({
432
+ id: t.serial().primaryKey(),
433
+ title: t.text(3, 100),
434
+ text: t.text(20, 10000),
435
+ ...t.timestamps(),
436
+ }));
437
+
438
+ relations = {
439
+ comments: this.hasMany(() => CommentTable, {
440
+ primaryKey: 'id',
441
+ foreignKey: 'postId',
442
+ }),
443
+ }
444
+ }
445
+ `);
446
+ });
447
+
448
+ it('should create post table with zod schema', async () => {
449
+ await initOrchidORM({
450
+ demoTables: true,
451
+ addSchemaToZod: true,
452
+ });
453
+
454
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
455
+ ([to]) => to === postTablePath,
456
+ );
457
+ expect(content).toBe(`import { BaseTable } from '../baseTable';
458
+ import { CommentTable } from './comment.table';
459
+ import { tableToZod } from 'orchid-orm-schema-to-zod';
460
+
461
+ export type Post = PostTable['columns']['type'];
462
+ class PostTable extends BaseTable {
463
+ table = 'post';
464
+ columns = this.setColumns((t) => ({
465
+ id: t.serial().primaryKey(),
466
+ title: t.text(3, 100),
467
+ text: t.text(20, 10000),
468
+ ...t.timestamps(),
469
+ }));
470
+
471
+ relations = {
472
+ comments: this.hasMany(() => CommentTable, {
473
+ primaryKey: 'id',
474
+ foreignKey: 'postId',
475
+ }),
476
+ }
477
+ }
478
+
479
+ export const postSchema = tableToZod(PostTable);
480
+ `);
481
+ });
482
+
483
+ it('should create comment table', async () => {
484
+ await initOrchidORM({
485
+ demoTables: true,
486
+ });
487
+
488
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
489
+ ([to]) => to === commentTablePath,
490
+ );
491
+ expect(content).toBe(`import { BaseTable } from '../baseTable';
492
+ import { PostTable } from './post.table';
493
+
494
+ export type Comment = CommentTable['columns']['type'];
495
+ class CommentTable extends BaseTable {
496
+ table = 'comment';
497
+ columns = this.setColumns((t) => ({
498
+ id: t.serial().primaryKey(),
499
+ postId: t.integer().foreignKey(() => PostTable, 'id').index(),
500
+ text: t.text(5, 1000),
501
+ ...t.timestamps(),
502
+ }));
503
+
504
+ relations = {
505
+ post: this.belongsTo(() => PostTable, {
506
+ primaryKey: 'id',
507
+ foreignKey: 'postId',
508
+ }),
509
+ }
510
+ }
511
+ `);
512
+ });
513
+
514
+ it('should create post table with zod schema', async () => {
515
+ await initOrchidORM({
516
+ demoTables: true,
517
+ addSchemaToZod: true,
518
+ });
519
+
520
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
521
+ ([to]) => to === commentTablePath,
522
+ );
523
+ expect(content).toBe(`import { BaseTable } from '../baseTable';
524
+ import { PostTable } from './post.table';
525
+ import { tableToZod } from 'orchid-orm-schema-to-zod';
526
+
527
+ export type Comment = CommentTable['columns']['type'];
528
+ class CommentTable extends BaseTable {
529
+ table = 'comment';
530
+ columns = this.setColumns((t) => ({
531
+ id: t.serial().primaryKey(),
532
+ postId: t.integer().foreignKey(() => PostTable, 'id').index(),
533
+ text: t.text(5, 1000),
534
+ ...t.timestamps(),
535
+ }));
536
+
537
+ relations = {
538
+ post: this.belongsTo(() => PostTable, {
539
+ primaryKey: 'id',
540
+ foreignKey: 'postId',
541
+ }),
542
+ }
543
+ }
544
+
545
+ export const commentSchema = tableToZod(CommentTable);
546
+ `);
547
+ });
548
+ });
549
+
550
+ describe('config', () => {
551
+ it('should create config file', async () => {
552
+ await initOrchidORM({});
553
+
554
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
555
+ ([to]) => to === configPath,
556
+ );
557
+ expect(content).toBe(`import 'dotenv/config';
558
+
559
+ const database = {
560
+ databaseURL: process.env.DATABASE_URL,
561
+ };
562
+ if (!database.databaseURL) throw new Error('DATABASE_URL is missing in .env');
563
+
564
+ export const config = {
565
+ database,
566
+ }
567
+ `);
568
+ });
569
+
570
+ it('should add test database config if specified', async () => {
571
+ await initOrchidORM({
572
+ testDatabase: true,
573
+ });
574
+
575
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
576
+ ([to]) => to === configPath,
577
+ );
578
+ expect(content).toBe(`import 'dotenv/config';
579
+
580
+ const database = {
581
+ databaseURL: process.env.DATABASE_URL,
582
+ };
583
+ if (!database.databaseURL) throw new Error('DATABASE_URL is missing in .env');
584
+
585
+ const testDatabase = {
586
+ databaseURL: process.env.DATABASE_TEST_URL,
587
+ };
588
+
589
+ const allDatabases = [database];
590
+
591
+ if (testDatabase.databaseURL) {
592
+ allDatabases.push(testDatabase);
593
+ }
594
+
595
+ export const config = {
596
+ allDatabases,
597
+ database: process.env.NODE_ENV === 'test' ? testDatabase : database,
598
+ }
599
+ `);
600
+ });
601
+ });
602
+
603
+ describe('db.ts', () => {
604
+ it('should create db.ts', async () => {
605
+ await initOrchidORM({});
606
+
607
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
608
+ ([to]) => to === dbPath,
609
+ );
610
+ expect(content).toBe(`import { orchidORM } from 'orchid-orm';
611
+ import { config } from './config';
612
+
613
+ export const db = orchidORM(
614
+ config.database,
615
+ {
616
+ }
617
+ );
618
+ `);
619
+ });
620
+
621
+ it('should create db.ts with demo tables', async () => {
622
+ await initOrchidORM({
623
+ demoTables: true,
624
+ });
625
+
626
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
627
+ ([to]) => to === dbPath,
628
+ );
629
+ expect(content).toBe(`import { orchidORM } from 'orchid-orm';
630
+ import { config } from './config';
631
+ import { Post } from './tables/post.table';
632
+ import { Comment } from './tables/comment.table';
633
+
634
+ export const db = orchidORM(
635
+ config.database,
636
+ {
637
+ post: Post,
638
+ comment: Comment,
639
+ }
640
+ );
641
+ `);
642
+ });
643
+ });
644
+
645
+ describe('migrationScript', () => {
646
+ it('should create script', async () => {
647
+ await initOrchidORM({});
648
+
649
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
650
+ ([to]) => to === migrationScriptPath,
651
+ );
652
+ expect(content).toBe(`import { rakeDb } from 'rake-db';
653
+ import { config } from './config';
654
+ import { appCodeUpdater } from 'orchid-orm';
655
+
656
+ rakeDb(config.database, {
657
+ migrationsPath: 'src/db/migrations',
658
+ appCodeUpdater: appCodeUpdater({
659
+ tablePath: (tableName) => \`src/db/tables/\${tableName}.ts\`,
660
+ baseTablePath: 'src/lib/baseTable.ts',
661
+ baseTableName: 'BaseTable',
662
+ mainFilePath: 'src/db.ts',
663
+ }),
664
+ });
665
+ `);
666
+ });
667
+
668
+ it('should create script with multiple databases', async () => {
669
+ await initOrchidORM({
670
+ testDatabase: true,
671
+ });
672
+
673
+ const [, content] = asMock(fs.writeFile).mock.calls.find(
674
+ ([to]) => to === migrationScriptPath,
675
+ );
676
+ expect(content).toBe(`import { rakeDb } from 'rake-db';
677
+ import { config } from './config';
678
+ import { appCodeUpdater } from 'orchid-orm';
679
+
680
+ rakeDb(config.allDatabases, {
681
+ migrationsPath: 'src/db/migrations',
682
+ appCodeUpdater: appCodeUpdater({
683
+ tablePath: (tableName) => \`src/db/tables/\${tableName}.ts\`,
684
+ baseTablePath: 'src/lib/baseTable.ts',
685
+ baseTableName: 'BaseTable',
686
+ mainFilePath: 'src/db.ts',
687
+ }),
688
+ });
689
+ `);
690
+ });
691
+ });
692
+
693
+ describe('migrations', () => {
694
+ it('should create migrations directory', async () => {
695
+ await initOrchidORM({});
696
+
697
+ expect(fs.mkdir).toBeCalledWith(migrationsPath);
698
+ });
699
+
700
+ it('should create migrations if demoTables specified', async () => {
701
+ await initOrchidORM({
702
+ demoTables: true,
703
+ });
704
+
705
+ const [, post] = asMock(fs.writeFile).mock.calls.find(([to]) =>
706
+ to.endsWith('createPost.ts'),
707
+ );
708
+ expect(post).toBe(`import { change } from 'rake-db';
709
+
710
+ change(async (db) => {
711
+ await db.createTable('post', (t) => ({
712
+ id: t.serial().primaryKey(),
713
+ title: t.text(),
714
+ text: t.text(),
715
+ ...t.timestamps(),
716
+ }));
717
+ });
718
+ `);
719
+
720
+ const [, comment] = asMock(fs.writeFile).mock.calls.find(([to]) =>
721
+ to.endsWith('createComment.ts'),
722
+ );
723
+ expect(comment).toBe(`import { change } from 'rake-db';
724
+
725
+ change(async (db) => {
726
+ await db.createTable('comment', (t) => ({
727
+ id: t.serial().primaryKey(),
728
+ postId: t.integer().foreignKey('post', 'id').index(),
729
+ text: t.text(),
730
+ ...t.timestamps(),
731
+ }));
732
+ });
733
+ `);
734
+ });
735
+ });
736
+ });