sasat 0.21.1 → 0.21.3
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/cli/cli.cjs +334 -280
- package/dist/cli/cli.mjs +331 -277
- package/package.json +1 -1
package/dist/cli/cli.cjs
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const cac = require('cac');
|
|
5
|
-
const erDiagram = require('cli/commands/erDiagram');
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
5
|
const error = require('../shared/sasat.f544328b.cjs');
|
|
9
6
|
require('pluralize');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
10
9
|
const chalk = require('chalk');
|
|
11
10
|
const console$1 = require('console');
|
|
12
11
|
const esbuild = require('esbuild');
|
|
@@ -14,7 +13,6 @@ const fs$1 = require('fs-extra');
|
|
|
14
13
|
require('js-yaml');
|
|
15
14
|
const prettier = require('prettier');
|
|
16
15
|
const typescript = require('typescript');
|
|
17
|
-
const getCurrentStore = require('cli/commands/getCurrentStore');
|
|
18
16
|
require('sqlstring');
|
|
19
17
|
require('mysql2');
|
|
20
18
|
require('util');
|
|
@@ -33,8 +31,8 @@ function _interopNamespaceCompat(e) {
|
|
|
33
31
|
return n;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
|
|
37
34
|
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
35
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
|
|
38
36
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
39
37
|
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
40
38
|
const chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
|
|
@@ -44,233 +42,6 @@ const fs__default$1 = /*#__PURE__*/_interopDefaultCompat(fs$1);
|
|
|
44
42
|
const prettier__namespace = /*#__PURE__*/_interopNamespaceCompat(prettier);
|
|
45
43
|
const typescript__default = /*#__PURE__*/_interopDefaultCompat(typescript);
|
|
46
44
|
|
|
47
|
-
const capitalizeFirstLetter = (str) => str.slice(0, 1).toUpperCase() + str.slice(1);
|
|
48
|
-
const lowercaseFirstLetter = (str) => str.slice(0, 1).toLowerCase() + str.slice(1);
|
|
49
|
-
const camelize = (str) => str.replace(
|
|
50
|
-
/(?:^\w|[A-Z]|_\w|\b\w)/g,
|
|
51
|
-
(word, index) => index == 0 ? word.toLowerCase() : word.toUpperCase()
|
|
52
|
-
).replace(/\s|_|-+/g, "");
|
|
53
|
-
|
|
54
|
-
const Console = {
|
|
55
|
-
success: (msg) => {
|
|
56
|
-
console__namespace.log(chalk__default.green(msg));
|
|
57
|
-
},
|
|
58
|
-
error: (msg) => {
|
|
59
|
-
console__namespace.error(chalk__default.bold.red(msg));
|
|
60
|
-
},
|
|
61
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
-
log: (msg) => {
|
|
63
|
-
console__namespace.log(msg);
|
|
64
|
-
},
|
|
65
|
-
debug: (msg) => {
|
|
66
|
-
console__namespace.debug("debug:: " + msg);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const getMigrationFile = (className) => `import { SasatMigration, MigrationStore } from "sasat";
|
|
71
|
-
|
|
72
|
-
export default class ${capitalizeFirstLetter(
|
|
73
|
-
className
|
|
74
|
-
)} implements SasatMigration {
|
|
75
|
-
|
|
76
|
-
up: (store: MigrationStore) => void = store => {
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
down: (store: MigrationStore) => void = store => {
|
|
81
|
-
throw new Error('Down is not implemented on ${className}');
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
`;
|
|
85
|
-
const createMigrationFile = (migrationName) => {
|
|
86
|
-
const date = /* @__PURE__ */ new Date();
|
|
87
|
-
const pad = (val) => val.toString().padStart(2, "0");
|
|
88
|
-
const now = date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + `_` + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
89
|
-
const fileName = now + migrationName;
|
|
90
|
-
const outDir = path.join(error.config().migration.dir);
|
|
91
|
-
error.mkDirIfNotExist(outDir);
|
|
92
|
-
fs__namespace.writeFileSync(
|
|
93
|
-
path.join(outDir, fileName) + ".ts",
|
|
94
|
-
getMigrationFile(migrationName)
|
|
95
|
-
);
|
|
96
|
-
return fileName;
|
|
97
|
-
};
|
|
98
|
-
const createMigration = (args) => {
|
|
99
|
-
if (!args) {
|
|
100
|
-
Console.error("missing argument migration name");
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (!/^[$A-Za-z_][0-9A-Za-z_]+$/.test(args)) {
|
|
104
|
-
Console.error("migration name should be match /^[$A-Za-z_][0-9A-Za-z_]+$/");
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
Console.success(createMigrationFile(args) + " Successfully created");
|
|
108
|
-
return;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const getMigrationFileDir = () => {
|
|
112
|
-
return path__default.join(process.cwd(), error.config().migration.dir);
|
|
113
|
-
};
|
|
114
|
-
const getMigrationFileNames = () => {
|
|
115
|
-
return fs__default.readdirSync(getMigrationFileDir()).filter((it) => it.split(".").pop() === "ts");
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
var Direction = /* @__PURE__ */ ((Direction2) => {
|
|
119
|
-
Direction2["Up"] = "up";
|
|
120
|
-
Direction2["Down"] = "down";
|
|
121
|
-
return Direction2;
|
|
122
|
-
})(Direction || {});
|
|
123
|
-
const calcRunMigrationFileNames = (records) => {
|
|
124
|
-
const result = [];
|
|
125
|
-
records.forEach((it) => {
|
|
126
|
-
if (it.direction === "down" /* Down */) {
|
|
127
|
-
if (result[result.length] !== it.name)
|
|
128
|
-
throw new Error(
|
|
129
|
-
"Invalid migration history: `down` migration must be the same migration as the last `up` migration "
|
|
130
|
-
);
|
|
131
|
-
result.pop();
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
result.push(it.name);
|
|
135
|
-
});
|
|
136
|
-
return result;
|
|
137
|
-
};
|
|
138
|
-
const getCurrentMigration = async (options) => {
|
|
139
|
-
const migrationTable = error.SqlString.escapeId(error.config().migration.table);
|
|
140
|
-
const files = getMigrationFileNames();
|
|
141
|
-
const client = error.getDbClient();
|
|
142
|
-
const query = `CREATE TABLE IF NOT EXISTS ${migrationTable} (id int auto_increment primary key , name varchar(100) not null,direction enum('up', 'down') not null, migrated_at timestamp default current_timestamp)`;
|
|
143
|
-
if (!options.silent) {
|
|
144
|
-
Console.log(
|
|
145
|
-
`creating migration table: ${migrationTable} :: ${Buffer.from(
|
|
146
|
-
migrationTable
|
|
147
|
-
).toString("base64")}`
|
|
148
|
-
);
|
|
149
|
-
Console.log(query);
|
|
150
|
-
}
|
|
151
|
-
await client.rawQuery(query);
|
|
152
|
-
const q = `SELECT name, direction FROM ${migrationTable} ORDER BY id ASC`;
|
|
153
|
-
if (!options.silent) {
|
|
154
|
-
Console.debug(q);
|
|
155
|
-
}
|
|
156
|
-
const result = await client.rawQuery(q);
|
|
157
|
-
console.debug(result);
|
|
158
|
-
if (!result.length)
|
|
159
|
-
return;
|
|
160
|
-
const runs = calcRunMigrationFileNames(
|
|
161
|
-
result
|
|
162
|
-
);
|
|
163
|
-
if (runs.length === 0)
|
|
164
|
-
return;
|
|
165
|
-
runs.forEach((run, i) => {
|
|
166
|
-
if (files[i] !== run)
|
|
167
|
-
throw new Error(`Invalid migration order: Migration must be performed in the same order
|
|
168
|
-
Found : ${files[i]}
|
|
169
|
-
in migration history: ${run}`);
|
|
170
|
-
});
|
|
171
|
-
return runs[runs.length - 1];
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
const changeExtTsToJs = (fileName) => fileName.slice(0, -3) + ".mjs";
|
|
175
|
-
const compileMigrationFiles = () => {
|
|
176
|
-
const tsFiles = getMigrationFileNames();
|
|
177
|
-
const compiles = tsFiles.map(async (fileName) => {
|
|
178
|
-
const filePath = path__default.join(getMigrationFileDir(), fileName);
|
|
179
|
-
const r = await esbuild__namespace.build({
|
|
180
|
-
entryPoints: [filePath],
|
|
181
|
-
bundle: true,
|
|
182
|
-
// loader: 'ts',
|
|
183
|
-
outfile: changeExtTsToJs(filePath),
|
|
184
|
-
platform: "node",
|
|
185
|
-
format: "esm",
|
|
186
|
-
outExtension: {
|
|
187
|
-
".js": ".mjs"
|
|
188
|
-
},
|
|
189
|
-
banner: {
|
|
190
|
-
js: `
|
|
191
|
-
import { createRequire as topLevelCreateRequire } from 'module';
|
|
192
|
-
const require = topLevelCreateRequire(import.meta.url);
|
|
193
|
-
`
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
if (r.errors.length !== 0) {
|
|
197
|
-
throw r.errors;
|
|
198
|
-
}
|
|
199
|
-
return fileName;
|
|
200
|
-
});
|
|
201
|
-
return Promise.all(compiles);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
const readMigration = async (store, tsFileName, direction) => {
|
|
205
|
-
const file = path__default.join(
|
|
206
|
-
process.cwd(),
|
|
207
|
-
error.config().migration.dir,
|
|
208
|
-
changeExtTsToJs(tsFileName)
|
|
209
|
-
);
|
|
210
|
-
const module = await import(file);
|
|
211
|
-
const instance = new module.default();
|
|
212
|
-
if (direction === Direction.Up) {
|
|
213
|
-
if (instance.beforeUp)
|
|
214
|
-
await instance.beforeUp();
|
|
215
|
-
await instance.up(store);
|
|
216
|
-
if (instance.afterUp)
|
|
217
|
-
await instance.afterUp();
|
|
218
|
-
} else {
|
|
219
|
-
if (instance.beforeDown)
|
|
220
|
-
await instance.beforeDown();
|
|
221
|
-
await instance.down(store);
|
|
222
|
-
if (instance.afterDown)
|
|
223
|
-
await instance.afterDown();
|
|
224
|
-
}
|
|
225
|
-
return store;
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
const runMigration = async (store, migrationName, direction, options) => {
|
|
229
|
-
const sqls = store.getSql();
|
|
230
|
-
store.resetQueue();
|
|
231
|
-
if (!options.silent) {
|
|
232
|
-
sqls.forEach(Console.log);
|
|
233
|
-
}
|
|
234
|
-
if (options.dry) {
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
const transaction = await error.getDbClient().transaction();
|
|
238
|
-
try {
|
|
239
|
-
for (const sql of sqls) {
|
|
240
|
-
await transaction.rawQuery(sql).catch((e) => {
|
|
241
|
-
Console.error(`ERROR ON ${migrationName}`);
|
|
242
|
-
Console.error(`SQL: ${sql}`);
|
|
243
|
-
Console.error(`MESSAGE: ${e.message}`);
|
|
244
|
-
process.exit(1);
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
await transaction.query`insert into ${() => error.config().migration.table} (name, direction) values (${[
|
|
248
|
-
migrationName,
|
|
249
|
-
direction
|
|
250
|
-
]})`;
|
|
251
|
-
return await transaction.commit();
|
|
252
|
-
} catch (e) {
|
|
253
|
-
await transaction.rollback();
|
|
254
|
-
throw e;
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const getMigrationTargets = (files, current) => {
|
|
259
|
-
const currentIndex = current ? files.indexOf(current) + 1 : 0;
|
|
260
|
-
const targetIndex = files.indexOf(error.config().migration.target || files[files.length - 1]) + 1;
|
|
261
|
-
if (currentIndex === -1 || targetIndex === -1)
|
|
262
|
-
throw new Error("migration target not found");
|
|
263
|
-
if (targetIndex >= currentIndex)
|
|
264
|
-
return {
|
|
265
|
-
direction: Direction.Up,
|
|
266
|
-
files: files.slice(currentIndex, targetIndex)
|
|
267
|
-
};
|
|
268
|
-
return {
|
|
269
|
-
direction: Direction.Down,
|
|
270
|
-
files: files.slice(targetIndex, currentIndex).reverse()
|
|
271
|
-
};
|
|
272
|
-
};
|
|
273
|
-
|
|
274
45
|
var DBColumnTypes = /* @__PURE__ */ ((DBColumnTypes2) => {
|
|
275
46
|
DBColumnTypes2["char"] = "char";
|
|
276
47
|
DBColumnTypes2["varchar"] = "varchar";
|
|
@@ -518,6 +289,13 @@ const assembleColumn = (data, table) => {
|
|
|
518
289
|
return new NormalColumn(data, table);
|
|
519
290
|
};
|
|
520
291
|
|
|
292
|
+
const capitalizeFirstLetter = (str) => str.slice(0, 1).toUpperCase() + str.slice(1);
|
|
293
|
+
const lowercaseFirstLetter = (str) => str.slice(0, 1).toLowerCase() + str.slice(1);
|
|
294
|
+
const camelize = (str) => str.replace(
|
|
295
|
+
/(?:^\w|[A-Z]|_\w|\b\w)/g,
|
|
296
|
+
(word, index) => index == 0 ? word.toLowerCase() : word.toUpperCase()
|
|
297
|
+
).replace(/\s|_|-+/g, "");
|
|
298
|
+
|
|
521
299
|
class EntityName {
|
|
522
300
|
constructor(name) {
|
|
523
301
|
this.name = name;
|
|
@@ -1404,7 +1182,140 @@ class StoreMigrator {
|
|
|
1404
1182
|
tables: this.tables.map((it) => it.serialize())
|
|
1405
1183
|
};
|
|
1406
1184
|
}
|
|
1407
|
-
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
const getMigrationFileDir = () => {
|
|
1188
|
+
return path__default.join(process.cwd(), error.config().migration.dir);
|
|
1189
|
+
};
|
|
1190
|
+
const getMigrationFileNames = () => {
|
|
1191
|
+
return fs__default.readdirSync(getMigrationFileDir()).filter((it) => it.split(".").pop() === "ts");
|
|
1192
|
+
};
|
|
1193
|
+
|
|
1194
|
+
const Console = {
|
|
1195
|
+
success: (msg) => {
|
|
1196
|
+
console__namespace.log(chalk__default.green(msg));
|
|
1197
|
+
},
|
|
1198
|
+
error: (msg) => {
|
|
1199
|
+
console__namespace.error(chalk__default.bold.red(msg));
|
|
1200
|
+
},
|
|
1201
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1202
|
+
log: (msg) => {
|
|
1203
|
+
console__namespace.log(msg);
|
|
1204
|
+
},
|
|
1205
|
+
debug: (msg) => {
|
|
1206
|
+
console__namespace.debug("debug:: " + msg);
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
|
|
1210
|
+
var Direction = /* @__PURE__ */ ((Direction2) => {
|
|
1211
|
+
Direction2["Up"] = "up";
|
|
1212
|
+
Direction2["Down"] = "down";
|
|
1213
|
+
return Direction2;
|
|
1214
|
+
})(Direction || {});
|
|
1215
|
+
const calcRunMigrationFileNames = (records) => {
|
|
1216
|
+
const result = [];
|
|
1217
|
+
records.forEach((it) => {
|
|
1218
|
+
if (it.direction === "down" /* Down */) {
|
|
1219
|
+
if (result[result.length] !== it.name)
|
|
1220
|
+
throw new Error(
|
|
1221
|
+
"Invalid migration history: `down` migration must be the same migration as the last `up` migration "
|
|
1222
|
+
);
|
|
1223
|
+
result.pop();
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
result.push(it.name);
|
|
1227
|
+
});
|
|
1228
|
+
return result;
|
|
1229
|
+
};
|
|
1230
|
+
const getCurrentMigration = async (options) => {
|
|
1231
|
+
const migrationTable = error.SqlString.escapeId(error.config().migration.table);
|
|
1232
|
+
const files = getMigrationFileNames();
|
|
1233
|
+
const client = error.getDbClient();
|
|
1234
|
+
const query = `CREATE TABLE IF NOT EXISTS ${migrationTable} (id int auto_increment primary key , name varchar(100) not null,direction enum('up', 'down') not null, migrated_at timestamp default current_timestamp)`;
|
|
1235
|
+
if (!options.silent) {
|
|
1236
|
+
Console.log(
|
|
1237
|
+
`creating migration table: ${migrationTable} :: ${Buffer.from(
|
|
1238
|
+
migrationTable
|
|
1239
|
+
).toString("base64")}`
|
|
1240
|
+
);
|
|
1241
|
+
Console.log(query);
|
|
1242
|
+
}
|
|
1243
|
+
await client.rawQuery(query);
|
|
1244
|
+
const q = `SELECT name, direction FROM ${migrationTable} ORDER BY id ASC`;
|
|
1245
|
+
if (!options.silent) {
|
|
1246
|
+
Console.debug(q);
|
|
1247
|
+
}
|
|
1248
|
+
const result = await client.rawQuery(q);
|
|
1249
|
+
console.debug(result);
|
|
1250
|
+
if (!result.length)
|
|
1251
|
+
return;
|
|
1252
|
+
const runs = calcRunMigrationFileNames(
|
|
1253
|
+
result
|
|
1254
|
+
);
|
|
1255
|
+
if (runs.length === 0)
|
|
1256
|
+
return;
|
|
1257
|
+
runs.forEach((run, i) => {
|
|
1258
|
+
if (files[i] !== run)
|
|
1259
|
+
throw new Error(`Invalid migration order: Migration must be performed in the same order
|
|
1260
|
+
Found : ${files[i]}
|
|
1261
|
+
in migration history: ${run}`);
|
|
1262
|
+
});
|
|
1263
|
+
return runs[runs.length - 1];
|
|
1264
|
+
};
|
|
1265
|
+
|
|
1266
|
+
const changeExtTsToJs = (fileName) => fileName.slice(0, -3) + ".mjs";
|
|
1267
|
+
const compileMigrationFiles = () => {
|
|
1268
|
+
const tsFiles = getMigrationFileNames();
|
|
1269
|
+
const compiles = tsFiles.map(async (fileName) => {
|
|
1270
|
+
const filePath = path__default.join(getMigrationFileDir(), fileName);
|
|
1271
|
+
const r = await esbuild__namespace.build({
|
|
1272
|
+
entryPoints: [filePath],
|
|
1273
|
+
bundle: true,
|
|
1274
|
+
// loader: 'ts',
|
|
1275
|
+
outfile: changeExtTsToJs(filePath),
|
|
1276
|
+
platform: "node",
|
|
1277
|
+
format: "esm",
|
|
1278
|
+
outExtension: {
|
|
1279
|
+
".js": ".mjs"
|
|
1280
|
+
},
|
|
1281
|
+
banner: {
|
|
1282
|
+
js: `
|
|
1283
|
+
import { createRequire as topLevelCreateRequire } from 'module';
|
|
1284
|
+
const require = topLevelCreateRequire(import.meta.url);
|
|
1285
|
+
`
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
if (r.errors.length !== 0) {
|
|
1289
|
+
throw r.errors;
|
|
1290
|
+
}
|
|
1291
|
+
return fileName;
|
|
1292
|
+
});
|
|
1293
|
+
return Promise.all(compiles);
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1296
|
+
const readMigration = async (store, tsFileName, direction) => {
|
|
1297
|
+
const file = path__default.join(
|
|
1298
|
+
process.cwd(),
|
|
1299
|
+
error.config().migration.dir,
|
|
1300
|
+
changeExtTsToJs(tsFileName)
|
|
1301
|
+
);
|
|
1302
|
+
const module = await import(file);
|
|
1303
|
+
const instance = new module.default();
|
|
1304
|
+
if (direction === Direction.Up) {
|
|
1305
|
+
if (instance.beforeUp)
|
|
1306
|
+
await instance.beforeUp();
|
|
1307
|
+
await instance.up(store);
|
|
1308
|
+
if (instance.afterUp)
|
|
1309
|
+
await instance.afterUp();
|
|
1310
|
+
} else {
|
|
1311
|
+
if (instance.beforeDown)
|
|
1312
|
+
await instance.beforeDown();
|
|
1313
|
+
await instance.down(store);
|
|
1314
|
+
if (instance.afterDown)
|
|
1315
|
+
await instance.afterDown();
|
|
1316
|
+
}
|
|
1317
|
+
return store;
|
|
1318
|
+
};
|
|
1408
1319
|
|
|
1409
1320
|
const createCurrentMigrationDataStore = async (targetMigrationName) => {
|
|
1410
1321
|
const allFiles = getMigrationFileNames();
|
|
@@ -1419,28 +1330,38 @@ const createCurrentMigrationDataStore = async (targetMigrationName) => {
|
|
|
1419
1330
|
return store;
|
|
1420
1331
|
};
|
|
1421
1332
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
let store = await createCurrentMigrationDataStore(currentMigration);
|
|
1428
|
-
const target = getMigrationTargets(fileNames, currentMigration);
|
|
1429
|
-
for (const tsFileName of target.files) {
|
|
1430
|
-
if (!options.silent) {
|
|
1431
|
-
Console.log("---------\n" + tsFileName);
|
|
1432
|
-
}
|
|
1433
|
-
store = await readMigration(store, tsFileName, target.direction);
|
|
1434
|
-
await runMigration(store, tsFileName, target.direction, options);
|
|
1435
|
-
store.resetQueue();
|
|
1436
|
-
}
|
|
1437
|
-
return {
|
|
1438
|
-
store: store.serialize(),
|
|
1439
|
-
currentMigration: error.config().migration.target || fileNames[fileNames.length - 1]
|
|
1440
|
-
};
|
|
1441
|
-
}
|
|
1333
|
+
async function getCurrentStore() {
|
|
1334
|
+
await compileMigrationFiles();
|
|
1335
|
+
const files = getMigrationFileNames();
|
|
1336
|
+
const targetFile = files.find((it) => it === error.config().migration.target) || files[files.length - 1];
|
|
1337
|
+
return (await createCurrentMigrationDataStore(targetFile)).serialize();
|
|
1442
1338
|
}
|
|
1443
1339
|
|
|
1340
|
+
const GeneratedDirName = "__generated__";
|
|
1341
|
+
const EntityDirName = "entities";
|
|
1342
|
+
const DataSourceDirName = "dataSources";
|
|
1343
|
+
const relative = (from, to) => {
|
|
1344
|
+
const result = path__namespace.posix.relative(from, to);
|
|
1345
|
+
if (result.startsWith("../"))
|
|
1346
|
+
return result;
|
|
1347
|
+
return "./" + result;
|
|
1348
|
+
};
|
|
1349
|
+
const GENERATED_PATH = `/${GeneratedDirName}/`;
|
|
1350
|
+
const paths = {
|
|
1351
|
+
BASE: "/",
|
|
1352
|
+
GENERATED: GENERATED_PATH,
|
|
1353
|
+
ENTITIES: `${GENERATED_PATH}${EntityDirName}/`,
|
|
1354
|
+
DATA_SOURCES: `/${DataSourceDirName}/db/`,
|
|
1355
|
+
GENERATED_DS: `${GENERATED_PATH}${DataSourceDirName}/db/`
|
|
1356
|
+
};
|
|
1357
|
+
const resolve = (from, source, fileName) => {
|
|
1358
|
+
return relative(paths[from], paths[source] + fileName);
|
|
1359
|
+
};
|
|
1360
|
+
const Directory = {
|
|
1361
|
+
paths,
|
|
1362
|
+
resolve
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1444
1365
|
var __defProp$k = Object.defineProperty;
|
|
1445
1366
|
var __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1446
1367
|
var __publicField$k = (obj, key, value) => {
|
|
@@ -1472,6 +1393,164 @@ class DataStoreHandler {
|
|
|
1472
1393
|
}
|
|
1473
1394
|
}
|
|
1474
1395
|
|
|
1396
|
+
const writeDiagram = async () => {
|
|
1397
|
+
try {
|
|
1398
|
+
const store = new DataStoreHandler(await getCurrentStore());
|
|
1399
|
+
const entities = store.tables.map((it) => processTable(store, it));
|
|
1400
|
+
const result = `erDiagram
|
|
1401
|
+
${entities.join("\n")}
|
|
1402
|
+
`;
|
|
1403
|
+
console.log();
|
|
1404
|
+
fs__default.writeFileSync(
|
|
1405
|
+
path__default.join(
|
|
1406
|
+
error.config().migration.out,
|
|
1407
|
+
Directory.paths.GENERATED,
|
|
1408
|
+
"er-diagram.mermaid"
|
|
1409
|
+
),
|
|
1410
|
+
result
|
|
1411
|
+
);
|
|
1412
|
+
} catch (e) {
|
|
1413
|
+
Console.error(e.message);
|
|
1414
|
+
throw e;
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
function getRefType(parent, rel) {
|
|
1418
|
+
const left = parent.isNullable() ? "|o" : "||";
|
|
1419
|
+
const getRight = () => {
|
|
1420
|
+
switch (rel) {
|
|
1421
|
+
case "One":
|
|
1422
|
+
return "||";
|
|
1423
|
+
case "Many":
|
|
1424
|
+
return "o{";
|
|
1425
|
+
case "OneOrZero":
|
|
1426
|
+
return "|o";
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
return `${left} -- ${getRight()}`;
|
|
1430
|
+
}
|
|
1431
|
+
function processTable(store, table) {
|
|
1432
|
+
const rel = table.columns.filter((it) => it.isReference()).map((it) => {
|
|
1433
|
+
const rel2 = it;
|
|
1434
|
+
const ref = rel2.data.reference;
|
|
1435
|
+
const parent = store.table(ref.parentTable).column(ref.parentColumn);
|
|
1436
|
+
return `${ref.parentTable} ${getRefType(parent, ref.relation)} ${table.tableName} : ${ref.relationName}`;
|
|
1437
|
+
});
|
|
1438
|
+
return `${table.tableName} {
|
|
1439
|
+
${table.columns.map((it) => ` ${it.columnName()} ${it.dataType()}`).join("\n")}
|
|
1440
|
+
}
|
|
1441
|
+
${rel.join("\n")}
|
|
1442
|
+
`;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
const getMigrationFile = (className) => `import { SasatMigration, MigrationStore } from "sasat";
|
|
1446
|
+
|
|
1447
|
+
export default class ${capitalizeFirstLetter(
|
|
1448
|
+
className
|
|
1449
|
+
)} implements SasatMigration {
|
|
1450
|
+
|
|
1451
|
+
up: (store: MigrationStore) => void = store => {
|
|
1452
|
+
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1455
|
+
down: (store: MigrationStore) => void = store => {
|
|
1456
|
+
throw new Error('Down is not implemented on ${className}');
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
`;
|
|
1460
|
+
const createMigrationFile = (migrationName) => {
|
|
1461
|
+
const date = /* @__PURE__ */ new Date();
|
|
1462
|
+
const pad = (val) => val.toString().padStart(2, "0");
|
|
1463
|
+
const now = date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + `_` + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
1464
|
+
const fileName = now + migrationName;
|
|
1465
|
+
const outDir = path.join(error.config().migration.dir);
|
|
1466
|
+
error.mkDirIfNotExist(outDir);
|
|
1467
|
+
fs__namespace.writeFileSync(
|
|
1468
|
+
path.join(outDir, fileName) + ".ts",
|
|
1469
|
+
getMigrationFile(migrationName)
|
|
1470
|
+
);
|
|
1471
|
+
return fileName;
|
|
1472
|
+
};
|
|
1473
|
+
const createMigration = (args) => {
|
|
1474
|
+
if (!args) {
|
|
1475
|
+
Console.error("missing argument migration name");
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
if (!/^[$A-Za-z_][0-9A-Za-z_]+$/.test(args)) {
|
|
1479
|
+
Console.error("migration name should be match /^[$A-Za-z_][0-9A-Za-z_]+$/");
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
Console.success(createMigrationFile(args) + " Successfully created");
|
|
1483
|
+
return;
|
|
1484
|
+
};
|
|
1485
|
+
|
|
1486
|
+
const runMigration = async (store, migrationName, direction, options) => {
|
|
1487
|
+
const sqls = store.getSql();
|
|
1488
|
+
store.resetQueue();
|
|
1489
|
+
if (!options.silent) {
|
|
1490
|
+
sqls.forEach(Console.log);
|
|
1491
|
+
}
|
|
1492
|
+
if (options.dry) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
const transaction = await error.getDbClient().transaction();
|
|
1496
|
+
try {
|
|
1497
|
+
for (const sql of sqls) {
|
|
1498
|
+
await transaction.rawQuery(sql).catch((e) => {
|
|
1499
|
+
Console.error(`ERROR ON ${migrationName}`);
|
|
1500
|
+
Console.error(`SQL: ${sql}`);
|
|
1501
|
+
Console.error(`MESSAGE: ${e.message}`);
|
|
1502
|
+
process.exit(1);
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
await transaction.query`insert into ${() => error.config().migration.table} (name, direction) values (${[
|
|
1506
|
+
migrationName,
|
|
1507
|
+
direction
|
|
1508
|
+
]})`;
|
|
1509
|
+
return await transaction.commit();
|
|
1510
|
+
} catch (e) {
|
|
1511
|
+
await transaction.rollback();
|
|
1512
|
+
throw e;
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
const getMigrationTargets = (files, current) => {
|
|
1517
|
+
const currentIndex = current ? files.indexOf(current) + 1 : 0;
|
|
1518
|
+
const targetIndex = files.indexOf(error.config().migration.target || files[files.length - 1]) + 1;
|
|
1519
|
+
if (currentIndex === -1 || targetIndex === -1)
|
|
1520
|
+
throw new Error("migration target not found");
|
|
1521
|
+
if (targetIndex >= currentIndex)
|
|
1522
|
+
return {
|
|
1523
|
+
direction: Direction.Up,
|
|
1524
|
+
files: files.slice(currentIndex, targetIndex)
|
|
1525
|
+
};
|
|
1526
|
+
return {
|
|
1527
|
+
direction: Direction.Down,
|
|
1528
|
+
files: files.slice(targetIndex, currentIndex).reverse()
|
|
1529
|
+
};
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1532
|
+
class MigrationController {
|
|
1533
|
+
async migrate(options) {
|
|
1534
|
+
const fileNames = getMigrationFileNames();
|
|
1535
|
+
const currentMigration = await getCurrentMigration(options);
|
|
1536
|
+
Console.log("--current migration--: " + currentMigration);
|
|
1537
|
+
let store = await createCurrentMigrationDataStore(currentMigration);
|
|
1538
|
+
const target = getMigrationTargets(fileNames, currentMigration);
|
|
1539
|
+
for (const tsFileName of target.files) {
|
|
1540
|
+
if (!options.silent) {
|
|
1541
|
+
Console.log("---------\n" + tsFileName);
|
|
1542
|
+
}
|
|
1543
|
+
store = await readMigration(store, tsFileName, target.direction);
|
|
1544
|
+
await runMigration(store, tsFileName, target.direction, options);
|
|
1545
|
+
store.resetQueue();
|
|
1546
|
+
}
|
|
1547
|
+
return {
|
|
1548
|
+
store: store.serialize(),
|
|
1549
|
+
currentMigration: error.config().migration.target || fileNames[fileNames.length - 1]
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1475
1554
|
class ImportDeclaration {
|
|
1476
1555
|
constructor(types, module) {
|
|
1477
1556
|
this.types = types;
|
|
@@ -2792,31 +2871,6 @@ const makeSubscription = (subscriptions) => {
|
|
|
2792
2871
|
);
|
|
2793
2872
|
};
|
|
2794
2873
|
|
|
2795
|
-
const GeneratedDirName = "__generated__";
|
|
2796
|
-
const EntityDirName = "entities";
|
|
2797
|
-
const DataSourceDirName = "dataSources";
|
|
2798
|
-
const relative = (from, to) => {
|
|
2799
|
-
const result = path__namespace.posix.relative(from, to);
|
|
2800
|
-
if (result.startsWith("../"))
|
|
2801
|
-
return result;
|
|
2802
|
-
return "./" + result;
|
|
2803
|
-
};
|
|
2804
|
-
const GENERATED_PATH = `/${GeneratedDirName}/`;
|
|
2805
|
-
const paths = {
|
|
2806
|
-
BASE: "/",
|
|
2807
|
-
GENERATED: GENERATED_PATH,
|
|
2808
|
-
ENTITIES: `${GENERATED_PATH}${EntityDirName}/`,
|
|
2809
|
-
DATA_SOURCES: `/${DataSourceDirName}/db/`,
|
|
2810
|
-
GENERATED_DS: `${GENERATED_PATH}${DataSourceDirName}/db/`
|
|
2811
|
-
};
|
|
2812
|
-
const resolve = (from, source, fileName) => {
|
|
2813
|
-
return relative(paths[from], paths[source] + fileName);
|
|
2814
|
-
};
|
|
2815
|
-
const Directory = {
|
|
2816
|
-
paths,
|
|
2817
|
-
resolve
|
|
2818
|
-
};
|
|
2819
|
-
|
|
2820
2874
|
const typeRefs = {
|
|
2821
2875
|
entity: {
|
|
2822
2876
|
name: (entity) => entity.name,
|
|
@@ -5239,7 +5293,7 @@ const generate = async () => {
|
|
|
5239
5293
|
await compileMigrationFiles();
|
|
5240
5294
|
const files = getMigrationFileNames();
|
|
5241
5295
|
const targetFile = files.find((it) => it === error.config().migration.target) || files[files.length - 1];
|
|
5242
|
-
const store = await getCurrentStore
|
|
5296
|
+
const store = await getCurrentStore();
|
|
5243
5297
|
const storeHandler = new DataStoreHandler(store);
|
|
5244
5298
|
error.writeCurrentSchema(store);
|
|
5245
5299
|
await new CodeGen_v2(storeHandler).generate();
|
|
@@ -5805,7 +5859,7 @@ try {
|
|
|
5805
5859
|
});
|
|
5806
5860
|
cli.command("migration:build", "compile migration files").action(migrationBuild);
|
|
5807
5861
|
cli.command("generate", "generate files").action(generate);
|
|
5808
|
-
cli.command("generate:er", "generate mermaid er diagram").action(
|
|
5862
|
+
cli.command("generate:er", "generate mermaid er diagram").action(writeDiagram);
|
|
5809
5863
|
cli.command("migration:create [name]", "generate new migration file").action(createMigration);
|
|
5810
5864
|
cli.command("dump-db", "dump database schema").action(dumpDB);
|
|
5811
5865
|
cli.command("init").action(init);
|
package/dist/cli/cli.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cac } from 'cac';
|
|
3
|
-
import {
|
|
3
|
+
import { S as SqlString, a as SasatError, c as config, r as readInitialSchema, g as getDbClient, m as mkDirIfNotExist, n as nonNullable, u as unique, C as Conditions, w as writeFileIfNotExist, b as writeCurrentSchema, d as writeYmlFile, e as defaultConf } from '../shared/sasat.01289068.mjs';
|
|
4
|
+
import 'pluralize';
|
|
4
5
|
import * as fs from 'fs';
|
|
5
6
|
import fs__default from 'fs';
|
|
6
7
|
import * as path from 'path';
|
|
7
8
|
import path__default, { join } from 'path';
|
|
8
|
-
import { c as config, m as mkDirIfNotExist, S as SqlString, g as getDbClient, a as SasatError, r as readInitialSchema, n as nonNullable, u as unique, C as Conditions, w as writeFileIfNotExist, b as writeCurrentSchema, d as writeYmlFile, e as defaultConf } from '../shared/sasat.01289068.mjs';
|
|
9
|
-
import 'pluralize';
|
|
10
9
|
import chalk from 'chalk';
|
|
11
10
|
import * as console$1 from 'console';
|
|
12
11
|
import * as esbuild from 'esbuild';
|
|
@@ -14,238 +13,10 @@ import fs$1 from 'fs-extra';
|
|
|
14
13
|
import 'js-yaml';
|
|
15
14
|
import * as prettier from 'prettier';
|
|
16
15
|
import typescript from 'typescript';
|
|
17
|
-
import { getCurrentStore } from 'cli/commands/getCurrentStore';
|
|
18
16
|
import 'sqlstring';
|
|
19
17
|
import 'mysql2';
|
|
20
18
|
import 'util';
|
|
21
19
|
|
|
22
|
-
const capitalizeFirstLetter = (str) => str.slice(0, 1).toUpperCase() + str.slice(1);
|
|
23
|
-
const lowercaseFirstLetter = (str) => str.slice(0, 1).toLowerCase() + str.slice(1);
|
|
24
|
-
const camelize = (str) => str.replace(
|
|
25
|
-
/(?:^\w|[A-Z]|_\w|\b\w)/g,
|
|
26
|
-
(word, index) => index == 0 ? word.toLowerCase() : word.toUpperCase()
|
|
27
|
-
).replace(/\s|_|-+/g, "");
|
|
28
|
-
|
|
29
|
-
const Console = {
|
|
30
|
-
success: (msg) => {
|
|
31
|
-
console$1.log(chalk.green(msg));
|
|
32
|
-
},
|
|
33
|
-
error: (msg) => {
|
|
34
|
-
console$1.error(chalk.bold.red(msg));
|
|
35
|
-
},
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
-
log: (msg) => {
|
|
38
|
-
console$1.log(msg);
|
|
39
|
-
},
|
|
40
|
-
debug: (msg) => {
|
|
41
|
-
console$1.debug("debug:: " + msg);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const getMigrationFile = (className) => `import { SasatMigration, MigrationStore } from "sasat";
|
|
46
|
-
|
|
47
|
-
export default class ${capitalizeFirstLetter(
|
|
48
|
-
className
|
|
49
|
-
)} implements SasatMigration {
|
|
50
|
-
|
|
51
|
-
up: (store: MigrationStore) => void = store => {
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
down: (store: MigrationStore) => void = store => {
|
|
56
|
-
throw new Error('Down is not implemented on ${className}');
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
`;
|
|
60
|
-
const createMigrationFile = (migrationName) => {
|
|
61
|
-
const date = /* @__PURE__ */ new Date();
|
|
62
|
-
const pad = (val) => val.toString().padStart(2, "0");
|
|
63
|
-
const now = date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + `_` + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
64
|
-
const fileName = now + migrationName;
|
|
65
|
-
const outDir = join(config().migration.dir);
|
|
66
|
-
mkDirIfNotExist(outDir);
|
|
67
|
-
fs.writeFileSync(
|
|
68
|
-
join(outDir, fileName) + ".ts",
|
|
69
|
-
getMigrationFile(migrationName)
|
|
70
|
-
);
|
|
71
|
-
return fileName;
|
|
72
|
-
};
|
|
73
|
-
const createMigration = (args) => {
|
|
74
|
-
if (!args) {
|
|
75
|
-
Console.error("missing argument migration name");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
if (!/^[$A-Za-z_][0-9A-Za-z_]+$/.test(args)) {
|
|
79
|
-
Console.error("migration name should be match /^[$A-Za-z_][0-9A-Za-z_]+$/");
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
Console.success(createMigrationFile(args) + " Successfully created");
|
|
83
|
-
return;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const getMigrationFileDir = () => {
|
|
87
|
-
return path__default.join(process.cwd(), config().migration.dir);
|
|
88
|
-
};
|
|
89
|
-
const getMigrationFileNames = () => {
|
|
90
|
-
return fs__default.readdirSync(getMigrationFileDir()).filter((it) => it.split(".").pop() === "ts");
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
var Direction = /* @__PURE__ */ ((Direction2) => {
|
|
94
|
-
Direction2["Up"] = "up";
|
|
95
|
-
Direction2["Down"] = "down";
|
|
96
|
-
return Direction2;
|
|
97
|
-
})(Direction || {});
|
|
98
|
-
const calcRunMigrationFileNames = (records) => {
|
|
99
|
-
const result = [];
|
|
100
|
-
records.forEach((it) => {
|
|
101
|
-
if (it.direction === "down" /* Down */) {
|
|
102
|
-
if (result[result.length] !== it.name)
|
|
103
|
-
throw new Error(
|
|
104
|
-
"Invalid migration history: `down` migration must be the same migration as the last `up` migration "
|
|
105
|
-
);
|
|
106
|
-
result.pop();
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
result.push(it.name);
|
|
110
|
-
});
|
|
111
|
-
return result;
|
|
112
|
-
};
|
|
113
|
-
const getCurrentMigration = async (options) => {
|
|
114
|
-
const migrationTable = SqlString.escapeId(config().migration.table);
|
|
115
|
-
const files = getMigrationFileNames();
|
|
116
|
-
const client = getDbClient();
|
|
117
|
-
const query = `CREATE TABLE IF NOT EXISTS ${migrationTable} (id int auto_increment primary key , name varchar(100) not null,direction enum('up', 'down') not null, migrated_at timestamp default current_timestamp)`;
|
|
118
|
-
if (!options.silent) {
|
|
119
|
-
Console.log(
|
|
120
|
-
`creating migration table: ${migrationTable} :: ${Buffer.from(
|
|
121
|
-
migrationTable
|
|
122
|
-
).toString("base64")}`
|
|
123
|
-
);
|
|
124
|
-
Console.log(query);
|
|
125
|
-
}
|
|
126
|
-
await client.rawQuery(query);
|
|
127
|
-
const q = `SELECT name, direction FROM ${migrationTable} ORDER BY id ASC`;
|
|
128
|
-
if (!options.silent) {
|
|
129
|
-
Console.debug(q);
|
|
130
|
-
}
|
|
131
|
-
const result = await client.rawQuery(q);
|
|
132
|
-
console.debug(result);
|
|
133
|
-
if (!result.length)
|
|
134
|
-
return;
|
|
135
|
-
const runs = calcRunMigrationFileNames(
|
|
136
|
-
result
|
|
137
|
-
);
|
|
138
|
-
if (runs.length === 0)
|
|
139
|
-
return;
|
|
140
|
-
runs.forEach((run, i) => {
|
|
141
|
-
if (files[i] !== run)
|
|
142
|
-
throw new Error(`Invalid migration order: Migration must be performed in the same order
|
|
143
|
-
Found : ${files[i]}
|
|
144
|
-
in migration history: ${run}`);
|
|
145
|
-
});
|
|
146
|
-
return runs[runs.length - 1];
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const changeExtTsToJs = (fileName) => fileName.slice(0, -3) + ".mjs";
|
|
150
|
-
const compileMigrationFiles = () => {
|
|
151
|
-
const tsFiles = getMigrationFileNames();
|
|
152
|
-
const compiles = tsFiles.map(async (fileName) => {
|
|
153
|
-
const filePath = path__default.join(getMigrationFileDir(), fileName);
|
|
154
|
-
const r = await esbuild.build({
|
|
155
|
-
entryPoints: [filePath],
|
|
156
|
-
bundle: true,
|
|
157
|
-
// loader: 'ts',
|
|
158
|
-
outfile: changeExtTsToJs(filePath),
|
|
159
|
-
platform: "node",
|
|
160
|
-
format: "esm",
|
|
161
|
-
outExtension: {
|
|
162
|
-
".js": ".mjs"
|
|
163
|
-
},
|
|
164
|
-
banner: {
|
|
165
|
-
js: `
|
|
166
|
-
import { createRequire as topLevelCreateRequire } from 'module';
|
|
167
|
-
const require = topLevelCreateRequire(import.meta.url);
|
|
168
|
-
`
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
if (r.errors.length !== 0) {
|
|
172
|
-
throw r.errors;
|
|
173
|
-
}
|
|
174
|
-
return fileName;
|
|
175
|
-
});
|
|
176
|
-
return Promise.all(compiles);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const readMigration = async (store, tsFileName, direction) => {
|
|
180
|
-
const file = path__default.join(
|
|
181
|
-
process.cwd(),
|
|
182
|
-
config().migration.dir,
|
|
183
|
-
changeExtTsToJs(tsFileName)
|
|
184
|
-
);
|
|
185
|
-
const module = await import(file);
|
|
186
|
-
const instance = new module.default();
|
|
187
|
-
if (direction === Direction.Up) {
|
|
188
|
-
if (instance.beforeUp)
|
|
189
|
-
await instance.beforeUp();
|
|
190
|
-
await instance.up(store);
|
|
191
|
-
if (instance.afterUp)
|
|
192
|
-
await instance.afterUp();
|
|
193
|
-
} else {
|
|
194
|
-
if (instance.beforeDown)
|
|
195
|
-
await instance.beforeDown();
|
|
196
|
-
await instance.down(store);
|
|
197
|
-
if (instance.afterDown)
|
|
198
|
-
await instance.afterDown();
|
|
199
|
-
}
|
|
200
|
-
return store;
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const runMigration = async (store, migrationName, direction, options) => {
|
|
204
|
-
const sqls = store.getSql();
|
|
205
|
-
store.resetQueue();
|
|
206
|
-
if (!options.silent) {
|
|
207
|
-
sqls.forEach(Console.log);
|
|
208
|
-
}
|
|
209
|
-
if (options.dry) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const transaction = await getDbClient().transaction();
|
|
213
|
-
try {
|
|
214
|
-
for (const sql of sqls) {
|
|
215
|
-
await transaction.rawQuery(sql).catch((e) => {
|
|
216
|
-
Console.error(`ERROR ON ${migrationName}`);
|
|
217
|
-
Console.error(`SQL: ${sql}`);
|
|
218
|
-
Console.error(`MESSAGE: ${e.message}`);
|
|
219
|
-
process.exit(1);
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
await transaction.query`insert into ${() => config().migration.table} (name, direction) values (${[
|
|
223
|
-
migrationName,
|
|
224
|
-
direction
|
|
225
|
-
]})`;
|
|
226
|
-
return await transaction.commit();
|
|
227
|
-
} catch (e) {
|
|
228
|
-
await transaction.rollback();
|
|
229
|
-
throw e;
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
const getMigrationTargets = (files, current) => {
|
|
234
|
-
const currentIndex = current ? files.indexOf(current) + 1 : 0;
|
|
235
|
-
const targetIndex = files.indexOf(config().migration.target || files[files.length - 1]) + 1;
|
|
236
|
-
if (currentIndex === -1 || targetIndex === -1)
|
|
237
|
-
throw new Error("migration target not found");
|
|
238
|
-
if (targetIndex >= currentIndex)
|
|
239
|
-
return {
|
|
240
|
-
direction: Direction.Up,
|
|
241
|
-
files: files.slice(currentIndex, targetIndex)
|
|
242
|
-
};
|
|
243
|
-
return {
|
|
244
|
-
direction: Direction.Down,
|
|
245
|
-
files: files.slice(targetIndex, currentIndex).reverse()
|
|
246
|
-
};
|
|
247
|
-
};
|
|
248
|
-
|
|
249
20
|
var DBColumnTypes = /* @__PURE__ */ ((DBColumnTypes2) => {
|
|
250
21
|
DBColumnTypes2["char"] = "char";
|
|
251
22
|
DBColumnTypes2["varchar"] = "varchar";
|
|
@@ -493,6 +264,13 @@ const assembleColumn = (data, table) => {
|
|
|
493
264
|
return new NormalColumn(data, table);
|
|
494
265
|
};
|
|
495
266
|
|
|
267
|
+
const capitalizeFirstLetter = (str) => str.slice(0, 1).toUpperCase() + str.slice(1);
|
|
268
|
+
const lowercaseFirstLetter = (str) => str.slice(0, 1).toLowerCase() + str.slice(1);
|
|
269
|
+
const camelize = (str) => str.replace(
|
|
270
|
+
/(?:^\w|[A-Z]|_\w|\b\w)/g,
|
|
271
|
+
(word, index) => index == 0 ? word.toLowerCase() : word.toUpperCase()
|
|
272
|
+
).replace(/\s|_|-+/g, "");
|
|
273
|
+
|
|
496
274
|
class EntityName {
|
|
497
275
|
constructor(name) {
|
|
498
276
|
this.name = name;
|
|
@@ -1379,7 +1157,140 @@ class StoreMigrator {
|
|
|
1379
1157
|
tables: this.tables.map((it) => it.serialize())
|
|
1380
1158
|
};
|
|
1381
1159
|
}
|
|
1382
|
-
}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
const getMigrationFileDir = () => {
|
|
1163
|
+
return path__default.join(process.cwd(), config().migration.dir);
|
|
1164
|
+
};
|
|
1165
|
+
const getMigrationFileNames = () => {
|
|
1166
|
+
return fs__default.readdirSync(getMigrationFileDir()).filter((it) => it.split(".").pop() === "ts");
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
const Console = {
|
|
1170
|
+
success: (msg) => {
|
|
1171
|
+
console$1.log(chalk.green(msg));
|
|
1172
|
+
},
|
|
1173
|
+
error: (msg) => {
|
|
1174
|
+
console$1.error(chalk.bold.red(msg));
|
|
1175
|
+
},
|
|
1176
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1177
|
+
log: (msg) => {
|
|
1178
|
+
console$1.log(msg);
|
|
1179
|
+
},
|
|
1180
|
+
debug: (msg) => {
|
|
1181
|
+
console$1.debug("debug:: " + msg);
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
|
|
1185
|
+
var Direction = /* @__PURE__ */ ((Direction2) => {
|
|
1186
|
+
Direction2["Up"] = "up";
|
|
1187
|
+
Direction2["Down"] = "down";
|
|
1188
|
+
return Direction2;
|
|
1189
|
+
})(Direction || {});
|
|
1190
|
+
const calcRunMigrationFileNames = (records) => {
|
|
1191
|
+
const result = [];
|
|
1192
|
+
records.forEach((it) => {
|
|
1193
|
+
if (it.direction === "down" /* Down */) {
|
|
1194
|
+
if (result[result.length] !== it.name)
|
|
1195
|
+
throw new Error(
|
|
1196
|
+
"Invalid migration history: `down` migration must be the same migration as the last `up` migration "
|
|
1197
|
+
);
|
|
1198
|
+
result.pop();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
result.push(it.name);
|
|
1202
|
+
});
|
|
1203
|
+
return result;
|
|
1204
|
+
};
|
|
1205
|
+
const getCurrentMigration = async (options) => {
|
|
1206
|
+
const migrationTable = SqlString.escapeId(config().migration.table);
|
|
1207
|
+
const files = getMigrationFileNames();
|
|
1208
|
+
const client = getDbClient();
|
|
1209
|
+
const query = `CREATE TABLE IF NOT EXISTS ${migrationTable} (id int auto_increment primary key , name varchar(100) not null,direction enum('up', 'down') not null, migrated_at timestamp default current_timestamp)`;
|
|
1210
|
+
if (!options.silent) {
|
|
1211
|
+
Console.log(
|
|
1212
|
+
`creating migration table: ${migrationTable} :: ${Buffer.from(
|
|
1213
|
+
migrationTable
|
|
1214
|
+
).toString("base64")}`
|
|
1215
|
+
);
|
|
1216
|
+
Console.log(query);
|
|
1217
|
+
}
|
|
1218
|
+
await client.rawQuery(query);
|
|
1219
|
+
const q = `SELECT name, direction FROM ${migrationTable} ORDER BY id ASC`;
|
|
1220
|
+
if (!options.silent) {
|
|
1221
|
+
Console.debug(q);
|
|
1222
|
+
}
|
|
1223
|
+
const result = await client.rawQuery(q);
|
|
1224
|
+
console.debug(result);
|
|
1225
|
+
if (!result.length)
|
|
1226
|
+
return;
|
|
1227
|
+
const runs = calcRunMigrationFileNames(
|
|
1228
|
+
result
|
|
1229
|
+
);
|
|
1230
|
+
if (runs.length === 0)
|
|
1231
|
+
return;
|
|
1232
|
+
runs.forEach((run, i) => {
|
|
1233
|
+
if (files[i] !== run)
|
|
1234
|
+
throw new Error(`Invalid migration order: Migration must be performed in the same order
|
|
1235
|
+
Found : ${files[i]}
|
|
1236
|
+
in migration history: ${run}`);
|
|
1237
|
+
});
|
|
1238
|
+
return runs[runs.length - 1];
|
|
1239
|
+
};
|
|
1240
|
+
|
|
1241
|
+
const changeExtTsToJs = (fileName) => fileName.slice(0, -3) + ".mjs";
|
|
1242
|
+
const compileMigrationFiles = () => {
|
|
1243
|
+
const tsFiles = getMigrationFileNames();
|
|
1244
|
+
const compiles = tsFiles.map(async (fileName) => {
|
|
1245
|
+
const filePath = path__default.join(getMigrationFileDir(), fileName);
|
|
1246
|
+
const r = await esbuild.build({
|
|
1247
|
+
entryPoints: [filePath],
|
|
1248
|
+
bundle: true,
|
|
1249
|
+
// loader: 'ts',
|
|
1250
|
+
outfile: changeExtTsToJs(filePath),
|
|
1251
|
+
platform: "node",
|
|
1252
|
+
format: "esm",
|
|
1253
|
+
outExtension: {
|
|
1254
|
+
".js": ".mjs"
|
|
1255
|
+
},
|
|
1256
|
+
banner: {
|
|
1257
|
+
js: `
|
|
1258
|
+
import { createRequire as topLevelCreateRequire } from 'module';
|
|
1259
|
+
const require = topLevelCreateRequire(import.meta.url);
|
|
1260
|
+
`
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
if (r.errors.length !== 0) {
|
|
1264
|
+
throw r.errors;
|
|
1265
|
+
}
|
|
1266
|
+
return fileName;
|
|
1267
|
+
});
|
|
1268
|
+
return Promise.all(compiles);
|
|
1269
|
+
};
|
|
1270
|
+
|
|
1271
|
+
const readMigration = async (store, tsFileName, direction) => {
|
|
1272
|
+
const file = path__default.join(
|
|
1273
|
+
process.cwd(),
|
|
1274
|
+
config().migration.dir,
|
|
1275
|
+
changeExtTsToJs(tsFileName)
|
|
1276
|
+
);
|
|
1277
|
+
const module = await import(file);
|
|
1278
|
+
const instance = new module.default();
|
|
1279
|
+
if (direction === Direction.Up) {
|
|
1280
|
+
if (instance.beforeUp)
|
|
1281
|
+
await instance.beforeUp();
|
|
1282
|
+
await instance.up(store);
|
|
1283
|
+
if (instance.afterUp)
|
|
1284
|
+
await instance.afterUp();
|
|
1285
|
+
} else {
|
|
1286
|
+
if (instance.beforeDown)
|
|
1287
|
+
await instance.beforeDown();
|
|
1288
|
+
await instance.down(store);
|
|
1289
|
+
if (instance.afterDown)
|
|
1290
|
+
await instance.afterDown();
|
|
1291
|
+
}
|
|
1292
|
+
return store;
|
|
1293
|
+
};
|
|
1383
1294
|
|
|
1384
1295
|
const createCurrentMigrationDataStore = async (targetMigrationName) => {
|
|
1385
1296
|
const allFiles = getMigrationFileNames();
|
|
@@ -1394,28 +1305,38 @@ const createCurrentMigrationDataStore = async (targetMigrationName) => {
|
|
|
1394
1305
|
return store;
|
|
1395
1306
|
};
|
|
1396
1307
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
let store = await createCurrentMigrationDataStore(currentMigration);
|
|
1403
|
-
const target = getMigrationTargets(fileNames, currentMigration);
|
|
1404
|
-
for (const tsFileName of target.files) {
|
|
1405
|
-
if (!options.silent) {
|
|
1406
|
-
Console.log("---------\n" + tsFileName);
|
|
1407
|
-
}
|
|
1408
|
-
store = await readMigration(store, tsFileName, target.direction);
|
|
1409
|
-
await runMigration(store, tsFileName, target.direction, options);
|
|
1410
|
-
store.resetQueue();
|
|
1411
|
-
}
|
|
1412
|
-
return {
|
|
1413
|
-
store: store.serialize(),
|
|
1414
|
-
currentMigration: config().migration.target || fileNames[fileNames.length - 1]
|
|
1415
|
-
};
|
|
1416
|
-
}
|
|
1308
|
+
async function getCurrentStore() {
|
|
1309
|
+
await compileMigrationFiles();
|
|
1310
|
+
const files = getMigrationFileNames();
|
|
1311
|
+
const targetFile = files.find((it) => it === config().migration.target) || files[files.length - 1];
|
|
1312
|
+
return (await createCurrentMigrationDataStore(targetFile)).serialize();
|
|
1417
1313
|
}
|
|
1418
1314
|
|
|
1315
|
+
const GeneratedDirName = "__generated__";
|
|
1316
|
+
const EntityDirName = "entities";
|
|
1317
|
+
const DataSourceDirName = "dataSources";
|
|
1318
|
+
const relative = (from, to) => {
|
|
1319
|
+
const result = path.posix.relative(from, to);
|
|
1320
|
+
if (result.startsWith("../"))
|
|
1321
|
+
return result;
|
|
1322
|
+
return "./" + result;
|
|
1323
|
+
};
|
|
1324
|
+
const GENERATED_PATH = `/${GeneratedDirName}/`;
|
|
1325
|
+
const paths = {
|
|
1326
|
+
BASE: "/",
|
|
1327
|
+
GENERATED: GENERATED_PATH,
|
|
1328
|
+
ENTITIES: `${GENERATED_PATH}${EntityDirName}/`,
|
|
1329
|
+
DATA_SOURCES: `/${DataSourceDirName}/db/`,
|
|
1330
|
+
GENERATED_DS: `${GENERATED_PATH}${DataSourceDirName}/db/`
|
|
1331
|
+
};
|
|
1332
|
+
const resolve = (from, source, fileName) => {
|
|
1333
|
+
return relative(paths[from], paths[source] + fileName);
|
|
1334
|
+
};
|
|
1335
|
+
const Directory = {
|
|
1336
|
+
paths,
|
|
1337
|
+
resolve
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1419
1340
|
var __defProp$k = Object.defineProperty;
|
|
1420
1341
|
var __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1421
1342
|
var __publicField$k = (obj, key, value) => {
|
|
@@ -1447,6 +1368,164 @@ class DataStoreHandler {
|
|
|
1447
1368
|
}
|
|
1448
1369
|
}
|
|
1449
1370
|
|
|
1371
|
+
const writeDiagram = async () => {
|
|
1372
|
+
try {
|
|
1373
|
+
const store = new DataStoreHandler(await getCurrentStore());
|
|
1374
|
+
const entities = store.tables.map((it) => processTable(store, it));
|
|
1375
|
+
const result = `erDiagram
|
|
1376
|
+
${entities.join("\n")}
|
|
1377
|
+
`;
|
|
1378
|
+
console.log();
|
|
1379
|
+
fs__default.writeFileSync(
|
|
1380
|
+
path__default.join(
|
|
1381
|
+
config().migration.out,
|
|
1382
|
+
Directory.paths.GENERATED,
|
|
1383
|
+
"er-diagram.mermaid"
|
|
1384
|
+
),
|
|
1385
|
+
result
|
|
1386
|
+
);
|
|
1387
|
+
} catch (e) {
|
|
1388
|
+
Console.error(e.message);
|
|
1389
|
+
throw e;
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
function getRefType(parent, rel) {
|
|
1393
|
+
const left = parent.isNullable() ? "|o" : "||";
|
|
1394
|
+
const getRight = () => {
|
|
1395
|
+
switch (rel) {
|
|
1396
|
+
case "One":
|
|
1397
|
+
return "||";
|
|
1398
|
+
case "Many":
|
|
1399
|
+
return "o{";
|
|
1400
|
+
case "OneOrZero":
|
|
1401
|
+
return "|o";
|
|
1402
|
+
}
|
|
1403
|
+
};
|
|
1404
|
+
return `${left} -- ${getRight()}`;
|
|
1405
|
+
}
|
|
1406
|
+
function processTable(store, table) {
|
|
1407
|
+
const rel = table.columns.filter((it) => it.isReference()).map((it) => {
|
|
1408
|
+
const rel2 = it;
|
|
1409
|
+
const ref = rel2.data.reference;
|
|
1410
|
+
const parent = store.table(ref.parentTable).column(ref.parentColumn);
|
|
1411
|
+
return `${ref.parentTable} ${getRefType(parent, ref.relation)} ${table.tableName} : ${ref.relationName}`;
|
|
1412
|
+
});
|
|
1413
|
+
return `${table.tableName} {
|
|
1414
|
+
${table.columns.map((it) => ` ${it.columnName()} ${it.dataType()}`).join("\n")}
|
|
1415
|
+
}
|
|
1416
|
+
${rel.join("\n")}
|
|
1417
|
+
`;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
const getMigrationFile = (className) => `import { SasatMigration, MigrationStore } from "sasat";
|
|
1421
|
+
|
|
1422
|
+
export default class ${capitalizeFirstLetter(
|
|
1423
|
+
className
|
|
1424
|
+
)} implements SasatMigration {
|
|
1425
|
+
|
|
1426
|
+
up: (store: MigrationStore) => void = store => {
|
|
1427
|
+
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
down: (store: MigrationStore) => void = store => {
|
|
1431
|
+
throw new Error('Down is not implemented on ${className}');
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
`;
|
|
1435
|
+
const createMigrationFile = (migrationName) => {
|
|
1436
|
+
const date = /* @__PURE__ */ new Date();
|
|
1437
|
+
const pad = (val) => val.toString().padStart(2, "0");
|
|
1438
|
+
const now = date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + `_` + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
1439
|
+
const fileName = now + migrationName;
|
|
1440
|
+
const outDir = join(config().migration.dir);
|
|
1441
|
+
mkDirIfNotExist(outDir);
|
|
1442
|
+
fs.writeFileSync(
|
|
1443
|
+
join(outDir, fileName) + ".ts",
|
|
1444
|
+
getMigrationFile(migrationName)
|
|
1445
|
+
);
|
|
1446
|
+
return fileName;
|
|
1447
|
+
};
|
|
1448
|
+
const createMigration = (args) => {
|
|
1449
|
+
if (!args) {
|
|
1450
|
+
Console.error("missing argument migration name");
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
if (!/^[$A-Za-z_][0-9A-Za-z_]+$/.test(args)) {
|
|
1454
|
+
Console.error("migration name should be match /^[$A-Za-z_][0-9A-Za-z_]+$/");
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
Console.success(createMigrationFile(args) + " Successfully created");
|
|
1458
|
+
return;
|
|
1459
|
+
};
|
|
1460
|
+
|
|
1461
|
+
const runMigration = async (store, migrationName, direction, options) => {
|
|
1462
|
+
const sqls = store.getSql();
|
|
1463
|
+
store.resetQueue();
|
|
1464
|
+
if (!options.silent) {
|
|
1465
|
+
sqls.forEach(Console.log);
|
|
1466
|
+
}
|
|
1467
|
+
if (options.dry) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
const transaction = await getDbClient().transaction();
|
|
1471
|
+
try {
|
|
1472
|
+
for (const sql of sqls) {
|
|
1473
|
+
await transaction.rawQuery(sql).catch((e) => {
|
|
1474
|
+
Console.error(`ERROR ON ${migrationName}`);
|
|
1475
|
+
Console.error(`SQL: ${sql}`);
|
|
1476
|
+
Console.error(`MESSAGE: ${e.message}`);
|
|
1477
|
+
process.exit(1);
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
await transaction.query`insert into ${() => config().migration.table} (name, direction) values (${[
|
|
1481
|
+
migrationName,
|
|
1482
|
+
direction
|
|
1483
|
+
]})`;
|
|
1484
|
+
return await transaction.commit();
|
|
1485
|
+
} catch (e) {
|
|
1486
|
+
await transaction.rollback();
|
|
1487
|
+
throw e;
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
|
|
1491
|
+
const getMigrationTargets = (files, current) => {
|
|
1492
|
+
const currentIndex = current ? files.indexOf(current) + 1 : 0;
|
|
1493
|
+
const targetIndex = files.indexOf(config().migration.target || files[files.length - 1]) + 1;
|
|
1494
|
+
if (currentIndex === -1 || targetIndex === -1)
|
|
1495
|
+
throw new Error("migration target not found");
|
|
1496
|
+
if (targetIndex >= currentIndex)
|
|
1497
|
+
return {
|
|
1498
|
+
direction: Direction.Up,
|
|
1499
|
+
files: files.slice(currentIndex, targetIndex)
|
|
1500
|
+
};
|
|
1501
|
+
return {
|
|
1502
|
+
direction: Direction.Down,
|
|
1503
|
+
files: files.slice(targetIndex, currentIndex).reverse()
|
|
1504
|
+
};
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
class MigrationController {
|
|
1508
|
+
async migrate(options) {
|
|
1509
|
+
const fileNames = getMigrationFileNames();
|
|
1510
|
+
const currentMigration = await getCurrentMigration(options);
|
|
1511
|
+
Console.log("--current migration--: " + currentMigration);
|
|
1512
|
+
let store = await createCurrentMigrationDataStore(currentMigration);
|
|
1513
|
+
const target = getMigrationTargets(fileNames, currentMigration);
|
|
1514
|
+
for (const tsFileName of target.files) {
|
|
1515
|
+
if (!options.silent) {
|
|
1516
|
+
Console.log("---------\n" + tsFileName);
|
|
1517
|
+
}
|
|
1518
|
+
store = await readMigration(store, tsFileName, target.direction);
|
|
1519
|
+
await runMigration(store, tsFileName, target.direction, options);
|
|
1520
|
+
store.resetQueue();
|
|
1521
|
+
}
|
|
1522
|
+
return {
|
|
1523
|
+
store: store.serialize(),
|
|
1524
|
+
currentMigration: config().migration.target || fileNames[fileNames.length - 1]
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1450
1529
|
class ImportDeclaration {
|
|
1451
1530
|
constructor(types, module) {
|
|
1452
1531
|
this.types = types;
|
|
@@ -2767,31 +2846,6 @@ const makeSubscription = (subscriptions) => {
|
|
|
2767
2846
|
);
|
|
2768
2847
|
};
|
|
2769
2848
|
|
|
2770
|
-
const GeneratedDirName = "__generated__";
|
|
2771
|
-
const EntityDirName = "entities";
|
|
2772
|
-
const DataSourceDirName = "dataSources";
|
|
2773
|
-
const relative = (from, to) => {
|
|
2774
|
-
const result = path.posix.relative(from, to);
|
|
2775
|
-
if (result.startsWith("../"))
|
|
2776
|
-
return result;
|
|
2777
|
-
return "./" + result;
|
|
2778
|
-
};
|
|
2779
|
-
const GENERATED_PATH = `/${GeneratedDirName}/`;
|
|
2780
|
-
const paths = {
|
|
2781
|
-
BASE: "/",
|
|
2782
|
-
GENERATED: GENERATED_PATH,
|
|
2783
|
-
ENTITIES: `${GENERATED_PATH}${EntityDirName}/`,
|
|
2784
|
-
DATA_SOURCES: `/${DataSourceDirName}/db/`,
|
|
2785
|
-
GENERATED_DS: `${GENERATED_PATH}${DataSourceDirName}/db/`
|
|
2786
|
-
};
|
|
2787
|
-
const resolve = (from, source, fileName) => {
|
|
2788
|
-
return relative(paths[from], paths[source] + fileName);
|
|
2789
|
-
};
|
|
2790
|
-
const Directory = {
|
|
2791
|
-
paths,
|
|
2792
|
-
resolve
|
|
2793
|
-
};
|
|
2794
|
-
|
|
2795
2849
|
const typeRefs = {
|
|
2796
2850
|
entity: {
|
|
2797
2851
|
name: (entity) => entity.name,
|