sonamu 0.2.48 → 0.2.50

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,879 @@
1
+ const require = (await import('module')).createRequire(import.meta.url);
2
+ import {
3
+ BaseModel,
4
+ EntityManager,
5
+ FixtureManager,
6
+ Migrator,
7
+ Sonamu,
8
+ isBelongsToOneRelationProp,
9
+ isEnumProp,
10
+ isHasManyRelationProp,
11
+ isManyToManyRelationProp,
12
+ isOneToOneRelationProp,
13
+ isRelationProp,
14
+ isVirtualProp
15
+ } from "../chunk-HEPO4HGK.mjs";
16
+ import {
17
+ __dirname
18
+ } from "../chunk-JXJTFHF7.mjs";
19
+
20
+ // src/bin/cli.ts
21
+ import chalk2 from "chalk";
22
+ import dotenv from "dotenv";
23
+ import path3 from "path";
24
+ import { tsicli } from "tsicli";
25
+ import { execSync } from "child_process";
26
+ import fs2 from "fs-extra";
27
+ import knex from "knex";
28
+ import inflection3 from "inflection";
29
+ import prettier from "prettier";
30
+
31
+ // src/smd/smd-manager.ts
32
+ import chalk from "chalk";
33
+ import glob from "glob";
34
+ import inflection2 from "inflection";
35
+ import path2 from "path";
36
+
37
+ // src/smd/smd.ts
38
+ import _ from "lodash";
39
+ import inflection from "inflection";
40
+ import path from "path";
41
+ import fs from "fs-extra";
42
+ var SMD = class {
43
+ constructor({
44
+ id,
45
+ parentId,
46
+ table,
47
+ title,
48
+ props,
49
+ indexes,
50
+ subsets
51
+ }) {
52
+ this.types = {};
53
+ this.enums = {};
54
+ this.enumLabels = {};
55
+ this.id = id;
56
+ this.parentId = parentId;
57
+ this.title = title ?? this.id;
58
+ this.table = table ?? inflection.underscore(inflection.pluralize(id));
59
+ if (props) {
60
+ this.props = props.map((prop) => {
61
+ if (isEnumProp(prop)) {
62
+ if (prop.id.includes("$Model")) {
63
+ prop.id = prop.id.replace("$Model", id);
64
+ }
65
+ }
66
+ return prop;
67
+ });
68
+ this.propsDict = props.reduce((result, prop) => {
69
+ return {
70
+ ...result,
71
+ [prop.name]: prop
72
+ };
73
+ }, {});
74
+ this.relations = props.filter((prop) => isRelationProp(prop)).reduce((result, prop) => {
75
+ return {
76
+ ...result,
77
+ [prop.name]: prop
78
+ };
79
+ }, {});
80
+ } else {
81
+ this.props = [];
82
+ this.propsDict = {};
83
+ this.relations = {};
84
+ }
85
+ this.indexes = indexes ?? [];
86
+ this.subsets = subsets ?? {};
87
+ this.names = {
88
+ fs: parentId === void 0 ? inflection.dasherize(inflection.underscore(id)).toLowerCase() : inflection.dasherize(parentId).toLowerCase(),
89
+ module: id
90
+ };
91
+ this.registerModulePaths();
92
+ this.registerTableSpecs();
93
+ }
94
+ /*
95
+ subset SELECT/JOIN/LOADER 결과 리턴
96
+ */
97
+ getSubsetQuery(subsetKey) {
98
+ const subset = this.subsets[subsetKey];
99
+ const result = this.resolveSubsetQuery("", subset);
100
+ return result;
101
+ }
102
+ /*
103
+ */
104
+ resolveSubsetQuery(prefix, fields, isAlreadyOuterJoined = false) {
105
+ prefix = prefix.replace(/\./g, "__");
106
+ const subsetGroup = _.groupBy(fields, (field) => {
107
+ if (field.includes(".")) {
108
+ const [rel] = field.split(".");
109
+ return rel;
110
+ } else {
111
+ return "";
112
+ }
113
+ });
114
+ const result = Object.keys(subsetGroup).reduce(
115
+ (r, groupKey) => {
116
+ const fields2 = subsetGroup[groupKey];
117
+ if (groupKey === "") {
118
+ const realFields = fields2.filter(
119
+ (field) => !isVirtualProp(this.propsDict[field])
120
+ );
121
+ const virtualFields = fields2.filter(
122
+ (field) => isVirtualProp(this.propsDict[field])
123
+ );
124
+ if (prefix === "") {
125
+ r.select = r.select.concat(
126
+ realFields.map((field) => `${this.table}.${field}`)
127
+ );
128
+ r.virtual = r.virtual.concat(virtualFields);
129
+ } else {
130
+ r.select = r.select.concat(
131
+ realFields.map(
132
+ (field) => `${prefix}.${field} as ${prefix}__${field}`
133
+ )
134
+ );
135
+ }
136
+ return r;
137
+ }
138
+ const relation = this.relations[groupKey];
139
+ if (relation === void 0) {
140
+ throw new Error(`\uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 relation \uCC38\uC870 ${groupKey}`);
141
+ }
142
+ const relSMD = SMDManager.get(relation.with);
143
+ if (isOneToOneRelationProp(relation) || isBelongsToOneRelationProp(relation)) {
144
+ const relFields = fields2.map(
145
+ (field) => field.split(".").slice(1).join(".")
146
+ );
147
+ if (relFields.length === 1 && relFields[0] === "id") {
148
+ if (prefix === "") {
149
+ r.select = r.select.concat(`${this.table}.${groupKey}_id`);
150
+ } else {
151
+ r.select = r.select.concat(
152
+ `${prefix}.${groupKey}_id as ${prefix}__${groupKey}_id`
153
+ );
154
+ }
155
+ return r;
156
+ }
157
+ const innerOrOuter = (() => {
158
+ if (isAlreadyOuterJoined) {
159
+ return "outer";
160
+ }
161
+ if (isOneToOneRelationProp(relation)) {
162
+ if (relation.hasJoinColumn === true && (relation.nullable ?? false) === false) {
163
+ return "inner";
164
+ } else {
165
+ return "outer";
166
+ }
167
+ } else {
168
+ if (relation.nullable) {
169
+ return "outer";
170
+ } else {
171
+ return "inner";
172
+ }
173
+ }
174
+ })();
175
+ const relSubsetQuery = relSMD.resolveSubsetQuery(
176
+ `${prefix !== "" ? prefix + "." : ""}${groupKey}`,
177
+ relFields,
178
+ innerOrOuter === "outer"
179
+ );
180
+ r.select = r.select.concat(relSubsetQuery.select);
181
+ r.virtual = r.virtual.concat(relSubsetQuery.virtual);
182
+ const joinAs = prefix === "" ? groupKey : prefix + "__" + groupKey;
183
+ const fromTable = prefix === "" ? this.table : prefix;
184
+ let joinClause;
185
+ if (relation.customJoinClause) {
186
+ joinClause = {
187
+ custom: relation.customJoinClause
188
+ };
189
+ } else {
190
+ let from, to;
191
+ if (isOneToOneRelationProp(relation)) {
192
+ if (relation.hasJoinColumn) {
193
+ from = `${fromTable}.${relation.name}_id`;
194
+ to = `${joinAs}.id`;
195
+ } else {
196
+ from = `${fromTable}.id`;
197
+ to = `${joinAs}.${inflection.underscore(
198
+ this.names.fs.replace(/\-/g, "_")
199
+ )}_id`;
200
+ }
201
+ } else {
202
+ from = `${fromTable}.${relation.name}_id`;
203
+ to = `${joinAs}.id`;
204
+ }
205
+ joinClause = {
206
+ from,
207
+ to
208
+ };
209
+ }
210
+ r.joins.push({
211
+ as: joinAs,
212
+ join: innerOrOuter,
213
+ table: relSMD.table,
214
+ ...joinClause
215
+ });
216
+ if (relSubsetQuery.loaders.length > 0) {
217
+ const convertedLoaders = relSubsetQuery.loaders.map((loader) => {
218
+ const newAs = [groupKey, loader.as].join("__");
219
+ return {
220
+ as: newAs,
221
+ table: loader.table,
222
+ manyJoin: loader.manyJoin,
223
+ oneJoins: loader.oneJoins,
224
+ select: loader.select
225
+ };
226
+ });
227
+ r.loaders = [...r.loaders, ...convertedLoaders];
228
+ }
229
+ r.joins = r.joins.concat(relSubsetQuery.joins);
230
+ } else if (isHasManyRelationProp(relation) || isManyToManyRelationProp(relation)) {
231
+ const relFields = fields2.map(
232
+ (field) => field.split(".").slice(1).join(".")
233
+ );
234
+ const relSubsetQuery = relSMD.resolveSubsetQuery("", relFields);
235
+ let manyJoin;
236
+ if (isHasManyRelationProp(relation)) {
237
+ manyJoin = {
238
+ fromTable: this.table,
239
+ fromCol: "id",
240
+ idField: prefix === "" ? `id` : `${prefix}__id`,
241
+ toTable: relSMD.table,
242
+ toCol: relation.joinColumn
243
+ };
244
+ } else if (isManyToManyRelationProp(relation)) {
245
+ const [table1, table2] = relation.joinTable.split("__");
246
+ manyJoin = {
247
+ fromTable: this.table,
248
+ fromCol: "id",
249
+ idField: prefix === "" ? `id` : `${prefix}__id`,
250
+ through: {
251
+ table: relation.joinTable,
252
+ fromCol: `${inflection.singularize(table1)}_id`,
253
+ toCol: `${inflection.singularize(table2)}_id`
254
+ },
255
+ toTable: relSMD.table,
256
+ toCol: "id"
257
+ };
258
+ } else {
259
+ throw new Error();
260
+ }
261
+ r.loaders.push({
262
+ as: groupKey,
263
+ table: relSMD.table,
264
+ manyJoin,
265
+ oneJoins: relSubsetQuery.joins,
266
+ select: relSubsetQuery.select,
267
+ loaders: relSubsetQuery.loaders
268
+ });
269
+ }
270
+ return r;
271
+ },
272
+ {
273
+ select: [],
274
+ virtual: [],
275
+ joins: [],
276
+ loaders: []
277
+ }
278
+ );
279
+ return result;
280
+ }
281
+ /*
282
+ FieldExpr[] 을 SMDPropNode[] 로 변환
283
+ */
284
+ fieldExprsToPropNodes(fieldExprs, smd = this) {
285
+ const groups = fieldExprs.reduce(
286
+ (result, fieldExpr) => {
287
+ let key, value, elseExpr;
288
+ if (fieldExpr.includes(".")) {
289
+ [key, ...elseExpr] = fieldExpr.split(".");
290
+ value = elseExpr.join(".");
291
+ } else {
292
+ key = "";
293
+ value = fieldExpr;
294
+ }
295
+ result[key] = (result[key] ?? []).concat(value);
296
+ return result;
297
+ },
298
+ {}
299
+ );
300
+ return Object.keys(groups).map((key) => {
301
+ const group = groups[key];
302
+ if (key === "") {
303
+ return group.map((propName) => {
304
+ if (propName === "uuid") {
305
+ return {
306
+ nodeType: "plain",
307
+ prop: {
308
+ type: "string",
309
+ name: "uuid",
310
+ length: 128
311
+ },
312
+ children: []
313
+ };
314
+ }
315
+ const prop2 = smd.propsDict[propName];
316
+ if (prop2 === void 0) {
317
+ throw new Error(`${this.id} -- \uC798\uBABB\uB41C FieldExpr ${propName}`);
318
+ }
319
+ return {
320
+ nodeType: "plain",
321
+ prop: prop2,
322
+ children: []
323
+ };
324
+ });
325
+ }
326
+ const prop = smd.propsDict[key];
327
+ if (!isRelationProp(prop)) {
328
+ throw new Error(`\uC798\uBABB\uB41C FieldExpr ${key}.${group[0]}`);
329
+ }
330
+ const relSMD = SMDManager.get(prop.with);
331
+ if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)) {
332
+ if (group.length == 1 && (group[0] === "id" || group[0] == "id?")) {
333
+ const idProp = relSMD.propsDict.id;
334
+ return {
335
+ nodeType: "plain",
336
+ prop: {
337
+ ...idProp,
338
+ name: key + "_id",
339
+ nullable: prop.nullable
340
+ },
341
+ children: []
342
+ };
343
+ }
344
+ }
345
+ const children = this.fieldExprsToPropNodes(group, relSMD);
346
+ const nodeType = isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop) ? "object" : "array";
347
+ return {
348
+ prop,
349
+ children,
350
+ nodeType
351
+ };
352
+ }).flat();
353
+ }
354
+ getFieldExprs(prefix = "", maxDepth = 3, froms = []) {
355
+ return this.props.map((prop) => {
356
+ const propName = [prefix, prop.name].filter((v) => v !== "").join(".");
357
+ if (propName === prefix) {
358
+ return null;
359
+ }
360
+ if (isRelationProp(prop)) {
361
+ if (maxDepth < 0) {
362
+ return null;
363
+ }
364
+ if (froms.includes(prop.with)) {
365
+ return null;
366
+ }
367
+ const relMd = SMDManager.get(prop.with);
368
+ return relMd.getFieldExprs(propName, maxDepth - 1, [
369
+ ...froms,
370
+ this.id
371
+ ]);
372
+ }
373
+ return propName;
374
+ }).flat().filter((f) => f !== null);
375
+ }
376
+ registerModulePaths() {
377
+ const basePath = `${this.names.fs}`;
378
+ SMDManager.setModulePath(
379
+ `${this.id}BaseSchema`,
380
+ `${basePath}/${this.names.fs}.generated`
381
+ );
382
+ if (Object.keys(this.subsets).length > 0) {
383
+ SMDManager.setModulePath(
384
+ `${this.id}SubsetKey`,
385
+ `${basePath}/${this.names.fs}.generated`
386
+ );
387
+ SMDManager.setModulePath(
388
+ `${this.id}SubsetMapping`,
389
+ `${basePath}/${this.names.fs}.generated`
390
+ );
391
+ Object.keys(this.subsets).map((subsetKey) => {
392
+ SMDManager.setModulePath(
393
+ `${this.id}Subset${subsetKey.toUpperCase()}`,
394
+ `${basePath}/${this.names.fs}.generated`
395
+ );
396
+ });
397
+ }
398
+ const typesModulePath = `${basePath}/${this.names.fs}.types`;
399
+ const typesFileDistPath = path.join(
400
+ Sonamu.apiRootPath,
401
+ `dist/application/${typesModulePath}.js`
402
+ );
403
+ if (fs.existsSync(typesFileDistPath)) {
404
+ const importPath = path.relative(__dirname, typesFileDistPath);
405
+ import(importPath).then((t) => {
406
+ this.types = Object.keys(t).reduce((result, key) => {
407
+ SMDManager.setModulePath(key, typesModulePath);
408
+ return {
409
+ ...result,
410
+ [key]: t[key]
411
+ };
412
+ }, {});
413
+ });
414
+ }
415
+ const enumsModulePath = `${basePath}/${this.names.fs}.enums`;
416
+ const enumsFileDistPath = path.join(
417
+ Sonamu.apiRootPath,
418
+ `/dist/application/${enumsModulePath}.js`
419
+ );
420
+ if (fs.existsSync(enumsFileDistPath)) {
421
+ const importPath = path.relative(__dirname, enumsFileDistPath);
422
+ import(importPath).then((t) => {
423
+ this.enums = Object.keys(t).reduce((result, key) => {
424
+ SMDManager.setModulePath(key, enumsModulePath);
425
+ if (key === inflection.underscore(this.id).toUpperCase()) {
426
+ this.enumLabels = t[key];
427
+ }
428
+ return {
429
+ ...result,
430
+ [key]: t[key]
431
+ };
432
+ }, {});
433
+ });
434
+ }
435
+ }
436
+ registerTableSpecs() {
437
+ const uniqueColumns = _.uniq(
438
+ this.indexes.filter((idx) => idx.type === "unique").map((idx) => idx.columns).flat()
439
+ );
440
+ SMDManager.setTableSpec({
441
+ name: this.table,
442
+ uniqueColumns
443
+ });
444
+ }
445
+ };
446
+
447
+ // src/smd/smd-manager.ts
448
+ var SMDManagerClass = class {
449
+ constructor() {
450
+ this.SMDs = /* @__PURE__ */ new Map();
451
+ this.modulePaths = /* @__PURE__ */ new Map();
452
+ this.tableSpecs = /* @__PURE__ */ new Map();
453
+ this.isAutoloaded = false;
454
+ }
455
+ // 경로 전달받아 모든 SMD 파일 로드
456
+ async autoload(doSilent = false) {
457
+ if (this.isAutoloaded) {
458
+ return;
459
+ }
460
+ const pathPattern = path2.join(
461
+ Sonamu.apiRootPath,
462
+ "/dist/application/**/*.smd.js"
463
+ );
464
+ !doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));
465
+ return new Promise((resolve) => {
466
+ glob.glob(path2.resolve(pathPattern), (_err, files) => {
467
+ const importPaths = files.map(
468
+ (filePath) => path2.relative(__dirname, filePath)
469
+ );
470
+ Promise.all(
471
+ importPaths.map(async (importPath) => {
472
+ const imported = await import(importPath);
473
+ Object.values(imported).map(
474
+ (smdInput) => this.register(smdInput)
475
+ );
476
+ return imported;
477
+ })
478
+ ).then(() => {
479
+ resolve("ok");
480
+ this.isAutoloaded = true;
481
+ });
482
+ });
483
+ });
484
+ }
485
+ register(smdInput) {
486
+ const smd = new SMD(smdInput);
487
+ this.SMDs.set(smdInput.id, smd);
488
+ }
489
+ get(smdId) {
490
+ const smd = this.SMDs.get(smdId);
491
+ if (smd === void 0) {
492
+ throw new Error(`\uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 SMD \uC694\uCCAD ${smdId}`);
493
+ }
494
+ return smd;
495
+ }
496
+ exists(smdId) {
497
+ const smd = this.SMDs.get(smdId);
498
+ return smd !== void 0;
499
+ }
500
+ getAllIds() {
501
+ return Array.from(SMDManager.SMDs.keys());
502
+ }
503
+ getAllParentIds() {
504
+ return this.getAllIds().filter((smdId) => {
505
+ const smd = this.get(smdId);
506
+ return smd.parentId === void 0;
507
+ });
508
+ }
509
+ getChildrenIds(parentId) {
510
+ return this.getAllIds().filter((smdId) => {
511
+ const smd = this.get(smdId);
512
+ return smd.parentId === parentId;
513
+ });
514
+ }
515
+ setModulePath(key, modulePath) {
516
+ this.modulePaths.set(key, modulePath);
517
+ }
518
+ getModulePath(key) {
519
+ const modulePath = this.modulePaths.get(key);
520
+ if (modulePath === void 0) {
521
+ throw new Error(`\uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uBAA8\uB4C8 \uD328\uC2A4 \uC694\uCCAD ${key}`);
522
+ }
523
+ return modulePath;
524
+ }
525
+ setTableSpec(tableSpec) {
526
+ this.tableSpecs.set(tableSpec.name, tableSpec);
527
+ }
528
+ getTableSpec(key) {
529
+ const tableSpec = this.tableSpecs.get(key);
530
+ if (tableSpec === void 0) {
531
+ throw new Error(`\uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uD14C\uC774\uBE14 \uC2A4\uD399 \uC694\uCCAD ${key}`);
532
+ }
533
+ return tableSpec;
534
+ }
535
+ getNamesFromId(smdId) {
536
+ const pluralized = inflection2.pluralize(smdId) === smdId ? `${smdId}List` : inflection2.pluralize(smdId);
537
+ return {
538
+ fs: inflection2.dasherize(inflection2.underscore(smdId)).toLowerCase(),
539
+ fsPlural: inflection2.dasherize(inflection2.underscore(pluralized)).toLowerCase(),
540
+ camel: inflection2.camelize(smdId, true),
541
+ camelPlural: inflection2.camelize(pluralized, true),
542
+ capital: smdId,
543
+ capitalPlural: pluralized,
544
+ upper: smdId.toUpperCase(),
545
+ constant: inflection2.underscore(smdId).toUpperCase()
546
+ };
547
+ }
548
+ };
549
+ var SMDManager = new SMDManagerClass();
550
+
551
+ // src/bin/cli.ts
552
+ import process from "process";
553
+ console.log(chalk2.bgBlue(`BEGIN ${/* @__PURE__ */ new Date()}`));
554
+ dotenv.config();
555
+ var migrator;
556
+ async function bootstrap() {
557
+ await Sonamu.init(false, false);
558
+ await tsicli(process.argv, {
559
+ types: {
560
+ "#entityId": {
561
+ type: "autocomplete",
562
+ name: "#entityId",
563
+ message: "Please input #entityId",
564
+ choices: EntityManager.getAllParentIds().map((entityId) => ({
565
+ title: entityId,
566
+ value: entityId
567
+ }))
568
+ },
569
+ "#recordIds": "number[]",
570
+ "#name": "string"
571
+ },
572
+ args: [
573
+ ["fixture", "init"],
574
+ ["fixture", "import", "#entityId", "#recordIds"],
575
+ ["fixture", "sync"],
576
+ ["migrate", "run"],
577
+ ["migrate", "check"],
578
+ ["migrate", "rollback"],
579
+ ["migrate", "reset"],
580
+ ["migrate", "clear"],
581
+ ["stub", "practice", "#name"],
582
+ ["stub", "entity", "#name"],
583
+ ["scaffold", "model", "#entityId"],
584
+ ["scaffold", "model_test", "#entityId"],
585
+ ["scaffold", "view_list", "#entityId"],
586
+ ["scaffold", "view_form", "#entityId"],
587
+ ["ui"],
588
+ ["smd_migration"]
589
+ ],
590
+ runners: {
591
+ migrate_run,
592
+ migrate_check,
593
+ migrate_rollback,
594
+ migrate_clear,
595
+ migrate_reset,
596
+ fixture_init,
597
+ fixture_import,
598
+ fixture_sync,
599
+ stub_practice,
600
+ stub_entity,
601
+ scaffold_model,
602
+ scaffold_model_test,
603
+ ui,
604
+ // scaffold_view_list,
605
+ // scaffold_view_form,
606
+ smd_migration
607
+ }
608
+ });
609
+ }
610
+ bootstrap().finally(async () => {
611
+ if (migrator) {
612
+ await migrator.destroy();
613
+ }
614
+ await FixtureManager.destory();
615
+ await BaseModel.destroy();
616
+ console.log(chalk2.bgBlue(`END ${/* @__PURE__ */ new Date()}
617
+ `));
618
+ });
619
+ async function setupMigrator() {
620
+ migrator = new Migrator({
621
+ mode: "dev"
622
+ });
623
+ }
624
+ async function setupFixtureManager() {
625
+ FixtureManager.init();
626
+ }
627
+ async function migrate_run() {
628
+ await setupMigrator();
629
+ await migrator.cleanUpDist();
630
+ await migrator.run();
631
+ }
632
+ async function migrate_check() {
633
+ await setupMigrator();
634
+ await migrator.cleanUpDist();
635
+ await migrator.check();
636
+ }
637
+ async function migrate_rollback() {
638
+ await setupMigrator();
639
+ await migrator.rollback();
640
+ }
641
+ async function migrate_clear() {
642
+ await setupMigrator();
643
+ await migrator.clearPendingList();
644
+ }
645
+ async function migrate_reset() {
646
+ await setupMigrator();
647
+ await migrator.resetAll();
648
+ }
649
+ async function fixture_init() {
650
+ const srcConfig = Sonamu.dbConfig.development_master;
651
+ const targets = [
652
+ {
653
+ label: "(REMOTE) Fixture DB",
654
+ config: Sonamu.dbConfig.fixture_remote
655
+ },
656
+ {
657
+ label: "(LOCAL) Fixture DB",
658
+ config: Sonamu.dbConfig.fixture_local,
659
+ toSkip: (() => {
660
+ const remoteConn = Sonamu.dbConfig.fixture_remote.connection;
661
+ const localConn = Sonamu.dbConfig.fixture_local.connection;
662
+ return remoteConn.host === localConn.host && remoteConn.database === localConn.database;
663
+ })()
664
+ },
665
+ {
666
+ label: "(LOCAL) Testing DB",
667
+ config: Sonamu.dbConfig.test
668
+ }
669
+ ];
670
+ console.log("DUMP...");
671
+ const dumpFilename = `/tmp/sonamu-fixture-init-${Date.now()}.sql`;
672
+ const srcConn = srcConfig.connection;
673
+ const migrationsDump = `/tmp/sonamu-fixture-init-migrations-${Date.now()}.sql`;
674
+ execSync(
675
+ `mysqldump -h${srcConn.host} -u${srcConn.user} -p${srcConn.password} --single-transaction -d --no-create-db --triggers ${srcConn.database} > ${dumpFilename}`
676
+ );
677
+ execSync(
678
+ `mysqldump -h${srcConn.host} -u${srcConn.user} -p${srcConn.password} --single-transaction --no-create-db --triggers ${srcConn.database} knex_migrations knex_migrations_lock > ${migrationsDump}`
679
+ );
680
+ for await (const { label, config, toSkip } of targets) {
681
+ const conn = config.connection;
682
+ if (toSkip === true) {
683
+ console.log(chalk2.red(`${label}: Skipped!`));
684
+ continue;
685
+ }
686
+ const db = knex({
687
+ ...config,
688
+ connection: {
689
+ ...config.connection ?? {},
690
+ database: void 0
691
+ }
692
+ });
693
+ const [[row]] = await db.raw(`SHOW DATABASES LIKE "${conn.database}"`);
694
+ if (row) {
695
+ console.log(
696
+ chalk2.yellow(`${label}: Database "${conn.database}" Already exists`)
697
+ );
698
+ await db.destroy();
699
+ continue;
700
+ }
701
+ console.log(`SYNC to ${label}...`);
702
+ const mysqlCmd = `mysql -h${conn.host} -u${conn.user} -p${conn.password}`;
703
+ execSync(`${mysqlCmd} -e 'DROP DATABASE IF EXISTS \`${conn.database}\`'`);
704
+ execSync(`${mysqlCmd} -e 'CREATE DATABASE \`${conn.database}\`'`);
705
+ execSync(`${mysqlCmd} ${conn.database} < ${dumpFilename}`);
706
+ execSync(`${mysqlCmd} ${conn.database} < ${migrationsDump}`);
707
+ await db.destroy();
708
+ }
709
+ }
710
+ async function fixture_import(entityId, recordIds) {
711
+ await setupFixtureManager();
712
+ await FixtureManager.importFixture(entityId, recordIds);
713
+ await FixtureManager.sync();
714
+ }
715
+ async function fixture_sync() {
716
+ await setupFixtureManager();
717
+ await FixtureManager.sync();
718
+ }
719
+ async function stub_practice(name) {
720
+ const practiceDir = path3.join(Sonamu.apiRootPath, "src", "practices");
721
+ const fileNames = fs2.readdirSync(practiceDir);
722
+ const maxSeqNo = (() => {
723
+ if (fs2.existsSync(practiceDir) === false) {
724
+ fs2.mkdirSync(practiceDir, { recursive: true });
725
+ }
726
+ const filteredSeqs = fileNames.filter(
727
+ (fileName2) => fileName2.startsWith("p") && fileName2.endsWith(".ts")
728
+ ).map((fileName2) => {
729
+ const [, seqNo] = fileName2.match(/^p([0-9]+)\-/) ?? ["0", "0"];
730
+ return parseInt(seqNo);
731
+ }).sort((a, b) => b - a);
732
+ if (filteredSeqs.length > 0) {
733
+ return filteredSeqs[0];
734
+ }
735
+ return 0;
736
+ })();
737
+ const currentSeqNo = maxSeqNo + 1;
738
+ const fileName = `p${currentSeqNo}-${name}.ts`;
739
+ const dstPath = path3.join(practiceDir, fileName);
740
+ const code = [
741
+ `import { BaseModel } from "sonamu";`,
742
+ "",
743
+ `console.clear();`,
744
+ `console.log("${fileName}");`,
745
+ "",
746
+ `async function bootstrap() {`,
747
+ ` // TODO`,
748
+ `}`,
749
+ `bootstrap().finally(async () => {`,
750
+ `await BaseModel.destroy();`,
751
+ `});`
752
+ ].join("\n");
753
+ fs2.writeFileSync(dstPath, code);
754
+ execSync(`code ${dstPath}`);
755
+ const runCode = `yarn node -r source-map-support/register dist/practices/${fileName.replace(
756
+ ".ts",
757
+ ".js"
758
+ )}`;
759
+ console.log(`${chalk2.blue(runCode)} copied to clipboard.`);
760
+ execSync(`echo "${runCode}" | pbcopy`);
761
+ }
762
+ async function stub_entity(entityId) {
763
+ await Sonamu.syncer.createEntity({ entityId });
764
+ }
765
+ async function scaffold_model(entityId) {
766
+ await Sonamu.syncer.generateTemplate("model", {
767
+ entityId
768
+ });
769
+ }
770
+ async function scaffold_model_test(entityId) {
771
+ await Sonamu.syncer.generateTemplate("model_test", {
772
+ entityId
773
+ });
774
+ }
775
+ async function ui() {
776
+ try {
777
+ const sonamuUI = await import("@sonamu-kit/ui");
778
+ sonamuUI.startServers(Sonamu.apiRootPath);
779
+ } catch (e) {
780
+ if (e instanceof Error && e.message.includes("isn't declared")) {
781
+ console.log(`You need to install ${chalk2.blue(`@sonamu-kit/ui`)} first.`);
782
+ return;
783
+ }
784
+ throw e;
785
+ }
786
+ }
787
+ async function smd_migration() {
788
+ await SMDManager.autoload();
789
+ const smdIds = SMDManager.getAllIds();
790
+ function enumLabelsToEntityEnums(entityId, enumLabels) {
791
+ return Object.fromEntries(
792
+ Object.entries(enumLabels).map(([enumLabelName, enumLabel]) => {
793
+ const enumName = entityId + inflection3.camelize(enumLabelName.toLowerCase(), false);
794
+ return [
795
+ enumName,
796
+ Object.fromEntries(
797
+ Object.entries(enumLabel).map(([name, { ko }]) => [name, ko])
798
+ )
799
+ ];
800
+ })
801
+ );
802
+ }
803
+ for await (const smdId of smdIds) {
804
+ const smd = SMDManager.get(smdId);
805
+ const entityJson = {
806
+ id: smd.id,
807
+ ...smd.parentId && { parentId: smd.parentId },
808
+ title: smd.title,
809
+ props: smd.props,
810
+ indexes: smd.indexes,
811
+ subsets: smd.subsets,
812
+ enums: enumLabelsToEntityEnums(smd.id, smd.enumLabels)
813
+ };
814
+ const parentNames = SMDManager.getNamesFromId(smd.parentId ?? smd.id);
815
+ const names = SMDManager.getNamesFromId(smd.id);
816
+ const dstPath = path3.join(
817
+ Sonamu.apiRootPath,
818
+ "src",
819
+ "application",
820
+ parentNames.fs,
821
+ `${names.fs}.entity.json`
822
+ );
823
+ const formatted = await prettier.format(JSON.stringify(entityJson), {
824
+ parser: "json"
825
+ });
826
+ fs2.writeFileSync(dstPath, formatted);
827
+ console.log(chalk2.blue(`CREATED: ${dstPath}`));
828
+ const srcSmdPath = path3.join(
829
+ Sonamu.apiRootPath,
830
+ "src",
831
+ "application",
832
+ parentNames.fs,
833
+ `${names.fs}.smd.ts`
834
+ );
835
+ const dstSmdPath = srcSmdPath.replace("/src/", "/dist/").replace(/\.ts$/, ".js");
836
+ const srcEnumsPath = path3.join(
837
+ Sonamu.apiRootPath,
838
+ "src",
839
+ "application",
840
+ parentNames.fs,
841
+ `${names.fs}.enums.ts`
842
+ );
843
+ const dstEnumsPath = srcEnumsPath.replace("/src/", "/dist/").replace(/\.ts$/, ".js");
844
+ const srcGeneratedPath = path3.join(
845
+ Sonamu.apiRootPath,
846
+ "src",
847
+ "application",
848
+ parentNames.fs,
849
+ `${names.fs}.generated.ts`
850
+ );
851
+ const dstGeneratedPath = srcGeneratedPath.replace("/src/", "/dist/").replace(/\.ts$/, ".js");
852
+ [
853
+ srcSmdPath,
854
+ dstSmdPath,
855
+ srcEnumsPath,
856
+ dstEnumsPath,
857
+ ...Sonamu.config.sync.targets.map(
858
+ (target) => srcEnumsPath.replace(Sonamu.apiRootPath, path3.join(Sonamu.appRootPath, target)).replace("/src/application/", "/src/services/")
859
+ ),
860
+ srcGeneratedPath,
861
+ dstGeneratedPath
862
+ ].map((p) => {
863
+ if (fs2.existsSync(p) === false) {
864
+ console.log(chalk2.yellow(`NOT FOUND: ${p}`));
865
+ return;
866
+ }
867
+ fs2.unlinkSync(p);
868
+ console.log(chalk2.red(`DELETED: ${p}`));
869
+ });
870
+ }
871
+ console.log("Entity\uB85C \uB2E4\uC2DC \uB85C\uB4DC\uD569\uB2C8\uB2E4.");
872
+ EntityManager.isAutoloaded = false;
873
+ await EntityManager.autoload();
874
+ const entityIds = EntityManager.getAllParentIds();
875
+ for await (const entityId of entityIds) {
876
+ await Sonamu.syncer.generateTemplate("generated", { entityId });
877
+ }
878
+ }
879
+ //# sourceMappingURL=cli.mjs.map