orchid-orm 1.5.28 → 1.5.30

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.
Files changed (57) hide show
  1. package/dist/index.js +10 -10
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +10 -10
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +13 -22
  6. package/.env.example +0 -1
  7. package/.turbo/turbo-test.log +0 -26
  8. package/.turbo/turbo-test:ci.log +0 -26
  9. package/CHANGELOG.md +0 -375
  10. package/coverage/coverage-summary.json +0 -28
  11. package/jest-setup.ts +0 -11
  12. package/rollup.config.js +0 -18
  13. package/src/bin/bin.ts +0 -3
  14. package/src/bin/init.test.ts +0 -810
  15. package/src/bin/init.ts +0 -529
  16. package/src/codegen/appCodeUpdater.test.ts +0 -75
  17. package/src/codegen/appCodeUpdater.ts +0 -53
  18. package/src/codegen/createBaseTableFile.test.ts +0 -53
  19. package/src/codegen/createBaseTableFile.ts +0 -31
  20. package/src/codegen/fileChanges.ts +0 -41
  21. package/src/codegen/testUtils.ts +0 -56
  22. package/src/codegen/tsUtils.ts +0 -180
  23. package/src/codegen/updateMainFile.test.ts +0 -253
  24. package/src/codegen/updateMainFile.ts +0 -210
  25. package/src/codegen/updateTableFile/changeTable.test.ts +0 -804
  26. package/src/codegen/updateTableFile/changeTable.ts +0 -536
  27. package/src/codegen/updateTableFile/createTable.test.ts +0 -139
  28. package/src/codegen/updateTableFile/createTable.ts +0 -51
  29. package/src/codegen/updateTableFile/renameTable.test.ts +0 -124
  30. package/src/codegen/updateTableFile/renameTable.ts +0 -67
  31. package/src/codegen/updateTableFile/updateTableFile.ts +0 -22
  32. package/src/codegen/utils.ts +0 -13
  33. package/src/index.ts +0 -5
  34. package/src/orm.test.ts +0 -92
  35. package/src/orm.ts +0 -98
  36. package/src/relations/belongsTo.test.ts +0 -1122
  37. package/src/relations/belongsTo.ts +0 -352
  38. package/src/relations/hasAndBelongsToMany.test.ts +0 -1335
  39. package/src/relations/hasAndBelongsToMany.ts +0 -472
  40. package/src/relations/hasMany.test.ts +0 -2616
  41. package/src/relations/hasMany.ts +0 -401
  42. package/src/relations/hasOne.test.ts +0 -1701
  43. package/src/relations/hasOne.ts +0 -351
  44. package/src/relations/relations.test.ts +0 -37
  45. package/src/relations/relations.ts +0 -363
  46. package/src/relations/utils.ts +0 -162
  47. package/src/repo.test.ts +0 -200
  48. package/src/repo.ts +0 -119
  49. package/src/table.test.ts +0 -121
  50. package/src/table.ts +0 -184
  51. package/src/test-utils/test-db.ts +0 -32
  52. package/src/test-utils/test-tables.ts +0 -194
  53. package/src/test-utils/test-utils.ts +0 -119
  54. package/src/transaction.test.ts +0 -47
  55. package/src/transaction.ts +0 -27
  56. package/src/utils.ts +0 -9
  57. package/tsconfig.json +0 -14
@@ -1,536 +0,0 @@
1
- import { RakeDbAst } from 'rake-db';
2
- import fs from 'fs/promises';
3
- import { FileChanges } from '../fileChanges';
4
- import { ts } from '../tsUtils';
5
- import { toPascalCase } from '../../utils';
6
- import {
7
- CallExpression,
8
- Expression,
9
- NodeArray,
10
- ObjectLiteralElementLike,
11
- ObjectLiteralExpression,
12
- PropertyAssignment,
13
- Statement,
14
- } from 'typescript';
15
- import {
16
- addCode,
17
- Code,
18
- codeToString,
19
- columnDefaultArgumentToCode,
20
- columnForeignKeysToCode,
21
- columnIndexesToCode,
22
- ColumnType,
23
- ForeignKey,
24
- foreignKeyToCode,
25
- IndexColumnOptions,
26
- indexToCode,
27
- primaryKeyToCode,
28
- quoteObjectKey,
29
- singleQuote,
30
- TableData,
31
- } from 'pqb';
32
- import { UpdateTableFileParams } from './updateTableFile';
33
-
34
- export const changeTable = async ({
35
- ast,
36
- ...params
37
- }: UpdateTableFileParams & { ast: RakeDbAst.ChangeTable }) => {
38
- const tablePath = params.tablePath(ast.name);
39
- const content = await fs.readFile(tablePath, 'utf-8').catch(() => undefined);
40
- if (!content) return;
41
-
42
- const changes = new FileChanges(content);
43
- const statements = ts.getStatements(content);
44
- const className = toPascalCase(ast.name) + 'Table';
45
-
46
- for (const { t, object } of iterateColumnsShapes(statements, className)) {
47
- const context = makeChangeContext(changes, ast, content, object, t);
48
-
49
- prependSpaces(context);
50
- applySchemaChanges(context);
51
- appendTrailingComma(context);
52
- addColumns(context);
53
- addTableData(context);
54
- }
55
-
56
- await fs.writeFile(tablePath, changes.apply());
57
- };
58
-
59
- function* iterateColumnsShapes(
60
- statements: NodeArray<Statement>,
61
- className: string,
62
- ) {
63
- for (const node of ts.class.iterate(statements)) {
64
- if (node.name?.escapedText !== className) continue;
65
-
66
- for (const member of node.members) {
67
- const name = ts.prop.getName(member);
68
- const { initializer: call } = member as unknown as {
69
- initializer?: Expression;
70
- };
71
-
72
- if (name !== 'columns' || !call || !ts.is.call(call)) continue;
73
-
74
- const { expression } = call;
75
- if (
76
- !ts.is.propertyAccess(expression) ||
77
- !ts.is.this(expression.expression) ||
78
- expression.name.escapedText !== 'setColumns'
79
- )
80
- continue;
81
-
82
- const [arg] = call.arguments;
83
- if (!ts.is.arrowFunction(arg)) continue;
84
-
85
- const { parameters, body } = arg;
86
- const param = parameters[0]?.name;
87
- if (!ts.is.identifier(param) || !ts.is.parenthesizedExpression(body))
88
- continue;
89
-
90
- const { expression: object } = body;
91
- if (!ts.is.objectLiteral(object)) continue;
92
-
93
- yield { t: param.escapedText.toString(), object };
94
- }
95
- }
96
- }
97
-
98
- type ChangeContext = {
99
- changes: FileChanges;
100
- props: NodeArray<ObjectLiteralElementLike>;
101
- shape: {
102
- add: Record<string, ColumnType>;
103
- drop: Record<string, true>;
104
- change: Record<string, RakeDbAst.ChangeTableItem.Change>;
105
- };
106
- t: string;
107
- spaces: string;
108
- object: Expression;
109
- drop: TableData;
110
- add: TableData;
111
- };
112
-
113
- const makeChangeContext = (
114
- changes: FileChanges,
115
- ast: RakeDbAst.ChangeTable,
116
- content: string,
117
- object: ObjectLiteralExpression,
118
- t: string,
119
- ): ChangeContext => {
120
- const add: ChangeContext['shape']['add'] = {};
121
- const drop: ChangeContext['shape']['drop'] = {};
122
- const change: ChangeContext['shape']['change'] = {};
123
-
124
- const { properties: props } = object;
125
- const existingColumns = getExistingColumns(props);
126
-
127
- for (const key in ast.shape) {
128
- const item = ast.shape[key];
129
- if (item.type === 'add' && !existingColumns[key]) {
130
- add[key] = item.item;
131
- }
132
-
133
- if (!existingColumns[key]) continue;
134
-
135
- if (item.type === 'drop' && existingColumns[key]) {
136
- drop[key] = true;
137
- } else if (item.type === 'change' && existingColumns[key]) {
138
- change[key] = item;
139
- }
140
- }
141
-
142
- const spaces = ts.spaces.getAtLine(content, object.end);
143
-
144
- const shape = { add, drop, change };
145
- return {
146
- changes,
147
- props,
148
- shape,
149
- spaces,
150
- t,
151
- object,
152
- add: ast.add,
153
- drop: ast.drop,
154
- };
155
- };
156
-
157
- const getExistingColumns = (props: NodeArray<ObjectLiteralElementLike>) => {
158
- const existingColumns: Record<string, true> = {};
159
- props
160
- .map((prop) => ts.is.propertyAssignment(prop) && ts.prop.getName(prop))
161
- .filter((name): name is string => !!name)
162
- .forEach((name) => (existingColumns[name] = true));
163
-
164
- for (const prop of props) {
165
- if (!ts.is.propertyAssignment(prop)) continue;
166
- const name = ts.prop.getName(prop);
167
- if (name) existingColumns[name] = true;
168
- }
169
-
170
- return existingColumns;
171
- };
172
-
173
- const prependSpaces = ({
174
- props,
175
- shape: { add },
176
- changes,
177
- spaces,
178
- }: ChangeContext) => {
179
- if (Object.keys(add).length && props.pos === props.end) {
180
- changes.add(props.pos, `\n${spaces}`);
181
- }
182
- };
183
-
184
- const applySchemaChanges = (context: ChangeContext) => {
185
- const {
186
- props,
187
- shape: { drop: dropColumns, change: changeColumns },
188
- add,
189
- drop,
190
- } = context;
191
-
192
- props.forEach((prop, i) => {
193
- if (ts.is.spreadAssignment(prop)) {
194
- const call = prop.expression;
195
- if (!ts.is.call(call)) return;
196
-
197
- const access = call.expression;
198
- if (!ts.is.propertyAccess(access)) return;
199
-
200
- const name = access.name.escapedText.toString();
201
- if (name === 'primaryKey') {
202
- if (drop.primaryKey || add.primaryKey) {
203
- removeProp(context, prop, i);
204
- }
205
- } else if (name === 'index') {
206
- dropMatchingIndexes(context, prop, i, call, drop.indexes);
207
- } else if (name === 'foreignKey') {
208
- dropMatchingForeignKey(context, prop, i, call, drop.foreignKeys);
209
- }
210
- } else if (ts.is.propertyAssignment(prop)) {
211
- const name = ts.prop.getName(prop);
212
- if (!name) return;
213
-
214
- if (dropColumns[name]) {
215
- removeProp(context, prop, i);
216
- } else {
217
- const changeItem = changeColumns[name];
218
- if (changeItem) {
219
- changeColumn(context, changeItem, prop);
220
- }
221
- }
222
- }
223
- });
224
- };
225
-
226
- const removeProp = (
227
- { props, changes }: ChangeContext,
228
- prop: ObjectLiteralElementLike,
229
- i: number,
230
- ) => {
231
- const end = props[i + 1]?.pos || props.end;
232
- changes.remove(prop.pos, end);
233
- };
234
-
235
- const changeColumn = (
236
- { changes, t, spaces }: ChangeContext,
237
- changeItem: RakeDbAst.ChangeTableItem.Change,
238
- prop: PropertyAssignment,
239
- ) => {
240
- const { from, to } = changeItem;
241
- if (from.type !== to.type && to.column) {
242
- changes.replace(
243
- prop.initializer.pos,
244
- prop.end,
245
- ` ${codeToString(to.column.toCode(t), spaces + ' ', ' ').trim()}`,
246
- );
247
- return;
248
- }
249
-
250
- const items: CallExpression[] = [];
251
- let chain: Expression | undefined = prop.initializer;
252
- while (ts.is.call(chain) && ts.is.propertyAccess(chain.expression)) {
253
- items.push(chain);
254
- chain = chain.expression.expression;
255
- }
256
-
257
- type Key = keyof RakeDbAst.ChangeTableItem.Change['to'];
258
- const propsToChange: Partial<Record<Key, true>> = {};
259
-
260
- for (const key in from) {
261
- if (to[key as Key] !== from[key as Key]) {
262
- propsToChange[key as Key] = true;
263
- }
264
- }
265
-
266
- for (const key in to) {
267
- if (to[key as Key] !== from[key as Key]) {
268
- propsToChange[key as Key] = true;
269
- }
270
- }
271
-
272
- const changedProps: Partial<Record<Key, true>> = {};
273
- const replaced: Record<string, true> = {};
274
- for (const item of items.reverse()) {
275
- if (!ts.is.propertyAccess(item.expression)) continue;
276
-
277
- const { name } = item.expression;
278
- let key = name.escapedText.toString();
279
- if (key === 'index') key = 'indexes';
280
- else if (key === 'foreignKey') key = 'foreignKeys';
281
-
282
- if (!propsToChange[key as Key]) continue;
283
-
284
- let remove = true;
285
- if (!replaced[key]) {
286
- const code = getColumnMethodArgs(to, key as Key);
287
- if (code) {
288
- changes.replace(
289
- item.expression.expression.end,
290
- item.end,
291
- codeToString(code, spaces + ' ', ' ').trim(),
292
- );
293
- replaced[key] = true;
294
- remove = false;
295
- }
296
- }
297
-
298
- if (remove) {
299
- changes.remove(item.expression.expression.end, item.end);
300
- }
301
-
302
- changedProps[key as Key] = true;
303
- }
304
-
305
- let append = '';
306
- for (const key in propsToChange) {
307
- if (changedProps[key as Key]) continue;
308
-
309
- const code = getColumnMethodArgs(to, key as Key);
310
- if (code) {
311
- append += codeToString(code, spaces + ' ', ' ').trim();
312
- }
313
- }
314
-
315
- if (append) {
316
- changes.add(prop.end, append);
317
- }
318
- };
319
-
320
- const appendTrailingComma = ({ props, changes }: ChangeContext) => {
321
- if (!props.hasTrailingComma) {
322
- const last = props[props.length - 1];
323
- if (last) {
324
- changes.add(last.end, ',');
325
- }
326
- }
327
- };
328
-
329
- const addColumns = ({
330
- shape: { add },
331
- changes,
332
- object,
333
- t,
334
- spaces,
335
- }: ChangeContext) => {
336
- const end = object.end - 1;
337
- for (const key in add) {
338
- const code = codeToString(add[key].toCode(t), spaces + ' ', ' ');
339
- changes.add(end, ` ${quoteObjectKey(key)}: ${code.trim()},\n${spaces}`);
340
- }
341
- };
342
-
343
- const addTableData = ({ add, changes, object, t, spaces }: ChangeContext) => {
344
- const end = object.end - 1;
345
- if (add.primaryKey) {
346
- const code = codeToString(
347
- primaryKeyToCode(add.primaryKey, t),
348
- spaces,
349
- ' ',
350
- );
351
- changes.add(end, ` ${code.trim()}\n${spaces}`);
352
- }
353
- for (const item of add.indexes) {
354
- const code = codeToString(indexToCode(item, t), spaces + ' ', ' ');
355
- changes.add(end, ` ${code.trim()}\n${spaces}`);
356
- }
357
- for (const item of add.foreignKeys) {
358
- const code = codeToString(foreignKeyToCode(item, t), spaces + ' ', ' ');
359
- changes.add(end, ` ${code.trim()}\n${spaces}`);
360
- }
361
- };
362
-
363
- const getColumnMethodArgs = (
364
- to: RakeDbAst.ChangeTableItem.Change['to'],
365
- key: keyof RakeDbAst.ChangeTableItem.Change['to'],
366
- ): Code[] | undefined => {
367
- const value = to[key];
368
- if (!value) return;
369
-
370
- if (key === 'indexes') {
371
- return columnIndexesToCode(value as IndexColumnOptions[]);
372
- }
373
-
374
- if (key === 'foreignKeys') {
375
- return columnForeignKeysToCode(value as ForeignKey<string, string[]>[]);
376
- }
377
-
378
- const code = [`.${key}(`];
379
-
380
- if (key === 'collate' || key === 'compression') {
381
- addCode(code, singleQuote(value as string));
382
- } else if (key === 'default') {
383
- addCode(code, columnDefaultArgumentToCode(value));
384
- } else if (key !== 'nullable' && key !== 'primaryKey') {
385
- return;
386
- }
387
-
388
- addCode(code, ')');
389
- return code;
390
- };
391
-
392
- const dropMatchingIndexes = (
393
- context: ChangeContext,
394
- prop: ObjectLiteralElementLike,
395
- i: number,
396
- call: CallExpression,
397
- items: TableData.Index[],
398
- ) => {
399
- if (!items.length) return;
400
-
401
- const [columnsNode, optionsNode] = call.arguments;
402
- const columns: Record<string, string | number>[] = [];
403
- if (ts.is.stringLiteral(columnsNode)) {
404
- columns.push({ column: columnsNode.text });
405
- } else if (ts.is.arrayLiteral(columnsNode)) {
406
- for (const node of columnsNode.elements) {
407
- if (ts.is.stringLiteral(node)) {
408
- columns.push({ column: node.text });
409
- } else if (ts.is.objectLiteral(node)) {
410
- const object = collectObjectFromCode(node);
411
- if (!object) return;
412
- columns.push(object);
413
- }
414
- }
415
- } else {
416
- return;
417
- }
418
-
419
- const options =
420
- (ts.is.objectLiteral(optionsNode) && collectObjectFromCode(optionsNode)) ||
421
- {};
422
-
423
- for (const item of items) {
424
- if (
425
- deepCompare(columns, item.columns) &&
426
- deepCompare(options, item.options)
427
- ) {
428
- removeProp(context, prop, i);
429
- }
430
- }
431
- };
432
-
433
- const dropMatchingForeignKey = (
434
- context: ChangeContext,
435
- prop: ObjectLiteralElementLike,
436
- i: number,
437
- call: CallExpression,
438
- items: TableData.ForeignKey[],
439
- ) => {
440
- if (!items.length) return;
441
-
442
- const { arguments: args } = call;
443
-
444
- const columns = collectStringArrayFromCode(args[0]);
445
- if (!columns) return;
446
-
447
- const fnOrTableNode = args[1];
448
- let fnOrTable: string;
449
- if (ts.is.stringLiteral(fnOrTableNode)) {
450
- fnOrTable = fnOrTableNode.text;
451
- } else if (ts.is.arrowFunction(fnOrTableNode)) {
452
- fnOrTable = context.changes.content
453
- .slice(fnOrTableNode.pos, fnOrTableNode.end)
454
- .replaceAll(/\s/g, '');
455
- } else {
456
- return;
457
- }
458
-
459
- const foreignColumns = collectStringArrayFromCode(args[2]);
460
- if (!foreignColumns) return;
461
-
462
- const options =
463
- (ts.is.objectLiteral(args[3]) && collectObjectFromCode(args[3])) || {};
464
-
465
- for (const item of items) {
466
- const itemOptions = item.options;
467
- delete itemOptions.dropMode;
468
-
469
- if (
470
- deepCompare(columns, item.columns) &&
471
- deepCompare(fnOrTable, item.fnOrTable.toString()) &&
472
- deepCompare(foreignColumns, item.foreignColumns) &&
473
- deepCompare(options, itemOptions)
474
- ) {
475
- removeProp(context, prop, i);
476
- }
477
- }
478
- };
479
-
480
- const collectStringArrayFromCode = (node: Expression) => {
481
- if (!ts.is.arrayLiteral(node)) return;
482
-
483
- const result = node.elements
484
- .filter(ts.is.stringLiteral)
485
- .map((item) => item.text);
486
-
487
- return result.length === node.elements.length ? result : undefined;
488
- };
489
-
490
- const collectObjectFromCode = (node: ObjectLiteralExpression) => {
491
- const object: Record<string, string | number> = {};
492
- for (const prop of node.properties) {
493
- if (!ts.is.propertyAssignment(prop)) return;
494
- const name = ts.prop.getName(prop);
495
- if (!name) return;
496
-
497
- const init = prop.initializer;
498
- if (ts.is.stringLiteral(init)) {
499
- object[name] = init.text;
500
- } else if (ts.is.numericLiteral(init)) {
501
- object[name] = parseFloat(init.text);
502
- } else {
503
- return;
504
- }
505
- }
506
- return object;
507
- };
508
-
509
- const deepCompare = (a: unknown, b: unknown): boolean => {
510
- if (typeof a !== typeof b) return false;
511
- if (a === b) return true;
512
- if (typeof a === 'object') {
513
- if (a === null) return b === null;
514
-
515
- if (Array.isArray(a)) {
516
- if (!Array.isArray(b) || a.length !== b.length) return false;
517
-
518
- return a.every((item, i) => deepCompare(item, b[i]));
519
- }
520
-
521
- for (const key in a) {
522
- if (
523
- !deepCompare(
524
- (a as Record<string, unknown>)[key],
525
- (b as Record<string, unknown>)[key],
526
- )
527
- )
528
- return false;
529
- }
530
-
531
- for (const key in b as Record<string, unknown>) {
532
- if (!(key in a)) return false;
533
- }
534
- }
535
- return true;
536
- };
@@ -1,139 +0,0 @@
1
- import { updateTableFile } from './updateTableFile';
2
- import { asMock, ast, makeTestWritten, tablePath } from '../testUtils';
3
- import path from 'path';
4
- import fs from 'fs/promises';
5
-
6
- jest.mock('fs/promises', () => ({
7
- readFile: jest.fn(),
8
- writeFile: jest.fn(),
9
- mkdir: jest.fn(),
10
- }));
11
-
12
- const baseTablePath = path.resolve('baseTable.ts');
13
- const baseTableName = 'BaseTable';
14
- const params = { baseTablePath, baseTableName, tablePath };
15
-
16
- const testWritten = makeTestWritten(tablePath('some'));
17
-
18
- const template = ({
19
- schema,
20
- columns,
21
- noPrimaryKey,
22
- }: {
23
- schema?: string;
24
- columns: string;
25
- noPrimaryKey?: boolean;
26
- }) => `import { BaseTable } from '../baseTable';
27
-
28
- export class SomeTable extends BaseTable {
29
- ${schema ? `schema = '${schema}';\n ` : ''}table = 'some';${
30
- noPrimaryKey ? '\n noPrimaryKey = true;' : ''
31
- }
32
- columns = this.setColumns((t) => (${columns}));
33
- }
34
- `;
35
-
36
- describe('createTable', () => {
37
- beforeEach(() => {
38
- jest.resetAllMocks();
39
- });
40
-
41
- it('should add table', async () => {
42
- await updateTableFile({
43
- ...params,
44
- ast: {
45
- ...ast.addTable,
46
- schema: 'schema',
47
- shape: {},
48
- },
49
- });
50
-
51
- expect(asMock(fs.mkdir)).toBeCalledWith(path.dirname(tablePath('some')), {
52
- recursive: true,
53
- });
54
-
55
- testWritten(
56
- template({
57
- schema: 'schema',
58
- columns: `{
59
-
60
- }`,
61
- }),
62
- );
63
- });
64
-
65
- it('should add table', async () => {
66
- await updateTableFile({
67
- ...params,
68
- ast: {
69
- ...ast.addTable,
70
- primaryKey: {
71
- columns: ['one', 'two'],
72
- options: { name: 'name' },
73
- },
74
- indexes: [
75
- {
76
- columns: [{ column: 'one' }, { column: 'two' }],
77
- options: { name: 'indexName', unique: true },
78
- },
79
- ],
80
- foreignKeys: [
81
- {
82
- columns: ['one', 'two'],
83
- fnOrTable: 'some',
84
- foreignColumns: ['three', 'four'],
85
- options: { name: 'foreignKeyName' },
86
- },
87
- ],
88
- },
89
- });
90
-
91
- testWritten(
92
- template({
93
- columns: `{
94
- id: t.serial().primaryKey(),
95
- ...t.primaryKey(['one', 'two'], { name: 'name' }),
96
- ...t.index(['one', 'two'], {
97
- name: 'indexName',
98
- unique: true,
99
- }),
100
- ...t.foreignKey(
101
- ['one', 'two'],
102
- 'some',
103
- ['three', 'four'],
104
- {
105
- name: 'foreignKeyName',
106
- },
107
- ),
108
- }`,
109
- }),
110
- );
111
- });
112
-
113
- it('should add noPrimaryKey prop when noPrimaryKey is `ignore` in ast', async () => {
114
- await updateTableFile({
115
- ...params,
116
- ast: { ...ast.addTable, noPrimaryKey: 'ignore' },
117
- });
118
-
119
- testWritten(
120
- template({
121
- noPrimaryKey: true,
122
- columns: `{
123
- id: t.serial().primaryKey(),
124
- }`,
125
- }),
126
- );
127
- });
128
-
129
- it('should create file with wx flag', async () => {
130
- asMock(fs.writeFile).mockRejectedValue(
131
- Object.assign(new Error(), { code: 'EEXIST' }),
132
- );
133
-
134
- await updateTableFile({ ...params, ast: ast.addTable });
135
-
136
- const [, , options] = asMock(fs.writeFile).mock.calls[0];
137
- expect(options).toEqual({ flag: 'wx' });
138
- });
139
- });
@@ -1,51 +0,0 @@
1
- import { RakeDbAst } from 'rake-db';
2
- import { getImportPath } from '../utils';
3
- import { Code, codeToString, columnsShapeToCode, singleQuote } from 'pqb';
4
- import { toPascalCase } from '../../utils';
5
- import fs from 'fs/promises';
6
- import { UpdateTableFileParams } from './updateTableFile';
7
- import path from 'path';
8
-
9
- export const createTable = async ({
10
- ast,
11
- ...params
12
- }: UpdateTableFileParams & { ast: RakeDbAst.Table }) => {
13
- const tablePath = params.tablePath(ast.name);
14
- const baseTablePath = getImportPath(tablePath, params.baseTablePath);
15
-
16
- const props: Code[] = [];
17
-
18
- if (ast.schema) {
19
- props.push(`schema = ${singleQuote(ast.schema)};`);
20
- }
21
-
22
- props.push(`table = ${singleQuote(ast.name)};`);
23
-
24
- if (ast.noPrimaryKey === 'ignore') {
25
- props.push('noPrimaryKey = true;');
26
- }
27
-
28
- props.push(
29
- 'columns = this.setColumns((t) => ({',
30
- columnsShapeToCode(ast.shape, ast, 't'),
31
- '}));',
32
- );
33
-
34
- const code: Code[] = [
35
- `import { ${params.baseTableName} } from '${baseTablePath}';\n`,
36
- `export class ${toPascalCase(ast.name)}Table extends ${
37
- params.baseTableName
38
- } {`,
39
- props,
40
- '}\n',
41
- ];
42
-
43
- await fs.mkdir(path.dirname(tablePath), { recursive: true });
44
- try {
45
- await fs.writeFile(tablePath, codeToString(code, '', ' '), { flag: 'wx' });
46
- } catch (err) {
47
- if ((err as unknown as { code: string }).code !== 'EEXIST') {
48
- throw err;
49
- }
50
- }
51
- };