sonamu 0.0.40 → 0.0.42

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/src/bin/cli.ts CHANGED
@@ -14,6 +14,7 @@ import { tsicli } from "tsicli";
14
14
  import { execSync } from "child_process";
15
15
  import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
16
16
  import { Sonamu } from "../api";
17
+ import knex, { Knex } from "knex";
17
18
 
18
19
  let migrator: Migrator;
19
20
 
@@ -35,6 +36,7 @@ async function bootstrap() {
35
36
  "#name": "string",
36
37
  },
37
38
  args: [
39
+ ["fixture", "init"],
38
40
  ["fixture", "import", "#smdId", "#recordIds"],
39
41
  ["fixture", "sync"],
40
42
  ["migrate", "run"],
@@ -48,6 +50,7 @@ async function bootstrap() {
48
50
  ["scaffold", "model_test", "#smdId"],
49
51
  ["scaffold", "view_list", "#smdId"],
50
52
  ["scaffold", "view_form", "#smdId"],
53
+ ["ui"],
51
54
  ],
52
55
  runners: {
53
56
  migrate_run,
@@ -55,12 +58,14 @@ async function bootstrap() {
55
58
  migrate_rollback,
56
59
  migrate_clear,
57
60
  migrate_reset,
61
+ fixture_init,
58
62
  fixture_import,
59
63
  fixture_sync,
60
64
  stub_practice,
61
65
  stub_smd,
62
66
  scaffold_model,
63
67
  scaffold_model_test,
68
+ ui,
64
69
  // scaffold_view_list,
65
70
  // scaffold_view_form,
66
71
  },
@@ -120,6 +125,80 @@ async function migrate_reset() {
120
125
  await migrator.resetAll();
121
126
  }
122
127
 
128
+ async function fixture_init() {
129
+ const srcConfig = Sonamu.dbConfig.development_master;
130
+ const targets = [
131
+ {
132
+ label: "(REMOTE) Fixture DB",
133
+ config: Sonamu.dbConfig.fixture_remote,
134
+ },
135
+ {
136
+ label: "(LOCAL) Fixture DB",
137
+ config: Sonamu.dbConfig.fixture_local,
138
+ toSkip: (() => {
139
+ const remoteConn = Sonamu.dbConfig.fixture_remote
140
+ .connection as Knex.ConnectionConfig;
141
+ const localConn = Sonamu.dbConfig.fixture_local
142
+ .connection as Knex.ConnectionConfig;
143
+ return (
144
+ remoteConn.host === localConn.host &&
145
+ remoteConn.database === localConn.database
146
+ );
147
+ })(),
148
+ },
149
+ {
150
+ label: "(LOCAL) Testing DB",
151
+ config: Sonamu.dbConfig.test,
152
+ },
153
+ ] as {
154
+ label: string;
155
+ config: Knex.Config;
156
+ toSkip?: boolean;
157
+ }[];
158
+
159
+ // 1. 기준DB 스키마를 덤프
160
+ console.log("DUMP...");
161
+ const dumpFilename = `/tmp/sonamu-fixture-init-${Date.now()}.sql`;
162
+ const srcConn = srcConfig.connection as Knex.ConnectionConfig;
163
+ execSync(
164
+ `mysqldump -h${srcConn.host} -u${srcConn.user} -p${srcConn.password} --single-transaction -d --no-create-db --triggers ${srcConn.database} > ${dumpFilename}`
165
+ );
166
+
167
+ // 2. 대상DB 각각에 대하여 존재여부 확인 후 붓기
168
+ for await (const { label, config, toSkip } of targets) {
169
+ const conn = config.connection as Knex.ConnectionConfig;
170
+
171
+ if (toSkip === true) {
172
+ console.log(chalk.red(`${label}: Skipped!`));
173
+ continue;
174
+ }
175
+
176
+ const db = knex({
177
+ ...config,
178
+ connection: {
179
+ ...((config.connection ?? {}) as Knex.ConnectionConfig),
180
+ database: undefined,
181
+ },
182
+ });
183
+ const [[row]] = await db.raw(`SHOW DATABASES LIKE "${conn.database}"`);
184
+ if (row) {
185
+ console.log(
186
+ chalk.yellow(`${label}: Database "${conn.database} Already exists`)
187
+ );
188
+ await db.destroy();
189
+ continue;
190
+ }
191
+
192
+ console.log(`SYNC to ${label}...`);
193
+ const mysqlCmd = `mysql -h${conn.host} -u${conn.user} -p${conn.password}`;
194
+ execSync(`${mysqlCmd} -e 'DROP DATABASE IF EXISTS ${conn.database}'`);
195
+ execSync(`${mysqlCmd} -e 'CREATE DATABASE ${conn.database}'`);
196
+ execSync(`${mysqlCmd} ${conn.database} < ${dumpFilename}`);
197
+
198
+ await db.destroy();
199
+ }
200
+ }
201
+
123
202
  async function fixture_import(smdId: string, recordIds: number[]) {
124
203
  await setupFixtureManager();
125
204
 
@@ -205,3 +284,16 @@ async function scaffold_model_test(smdId: string) {
205
284
  smdId,
206
285
  });
207
286
  }
287
+
288
+ async function ui() {
289
+ try {
290
+ const sonamuUI = await import("@sonamu-kit/ui" as any);
291
+ sonamuUI.startServers(Sonamu.appRootPath);
292
+ } catch (e: unknown) {
293
+ if (e instanceof Error && e.message.includes("isn't declared")) {
294
+ console.log(`You need to install ${chalk.blue(`@sonamu-kit/ui`)} first.`);
295
+ return;
296
+ }
297
+ throw e;
298
+ }
299
+ }
@@ -478,20 +478,22 @@ export class Migrator {
478
478
  );
479
479
  }
480
480
  } else {
481
- const smdForeigns = sortBy(smdSet.foreigns, (a) =>
482
- [a.to, ...a.columns].join("-")
483
- ).map((smdForeign) => {
481
+ const replaceNoActionOnMySQL = (f: MigrationForeign) => {
484
482
  // MySQL에서 RESTRICT와 NO ACTION은 동일함
485
- const { onDelete, onUpdate } = smdForeign;
483
+ const { onDelete, onUpdate } = f;
486
484
  return {
487
- ...smdForeign,
485
+ ...f,
488
486
  onUpdate: onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
489
487
  onDelete: onDelete === "RESTRICT" ? "NO ACTION" : onDelete,
490
488
  };
491
- });
489
+ };
490
+
491
+ const smdForeigns = sortBy(smdSet.foreigns, (a) =>
492
+ [a.to, ...a.columns].join("-")
493
+ ).map((f) => replaceNoActionOnMySQL(f));
492
494
  const dbForeigns = sortBy(dbSet.foreigns, (a) =>
493
495
  [a.to, ...a.columns].join("-")
494
- );
496
+ ).map((f) => replaceNoActionOnMySQL(f));
495
497
 
496
498
  if (equal(smdForeigns, dbForeigns) === false) {
497
499
  console.dir({ smdForeigns, dbForeigns }, { depth: null });
@@ -212,10 +212,7 @@ function enums(
212
212
  }
213
213
  function virtual(
214
214
  name: string,
215
- option: Omit<
216
- VirtualProp,
217
- "name" | "type" | "index" | "unique" | "dbDefault" | "toFilter"
218
- >
215
+ option: Omit<VirtualProp, "name" | "type" | "dbDefault" | "toFilter">
219
216
  ): VirtualProp {
220
217
  return {
221
218
  name,
package/src/smd/smd.ts CHANGED
@@ -208,8 +208,28 @@ export class SMD {
208
208
  }
209
209
 
210
210
  // innerOrOuter
211
- const innerOrOuter =
212
- isAlreadyOuterJoined || relation.nullable ? "outer" : "inner";
211
+ const innerOrOuter = (() => {
212
+ if (isAlreadyOuterJoined) {
213
+ return "outer";
214
+ }
215
+
216
+ if (isOneToOneRelationProp(relation)) {
217
+ if (
218
+ relation.hasJoinColumn === true &&
219
+ (relation.nullable ?? false) === false
220
+ ) {
221
+ return "inner";
222
+ } else {
223
+ return "outer";
224
+ }
225
+ } else {
226
+ if (relation.nullable) {
227
+ return "outer";
228
+ } else {
229
+ return "inner";
230
+ }
231
+ }
232
+ })();
213
233
  const relSubsetQuery = relSMD.resolveSubsetQuery(
214
234
  `${prefix !== "" ? prefix + "." : ""}${groupKey}`,
215
235
  relFields,
@@ -1,5 +1,4 @@
1
1
  import chalk from "chalk";
2
- import { execSync } from "child_process";
3
2
  import knex, { Knex } from "knex";
4
3
  import { uniq } from "lodash";
5
4
  import { Sonamu } from "../api";
@@ -44,10 +43,14 @@ export class FixtureManagerClass {
44
43
  const pConn = Sonamu.dbConfig.production_master
45
44
  .connection as Knex.ConnectionConfig & { port?: number };
46
45
  if (
47
- `${tConn.host ?? "localhost"}:${tConn.port ?? 3306}` ===
48
- `${pConn.host ?? "localhost"}:${pConn.port ?? 3306}`
46
+ `${tConn.host ?? "localhost"}:${tConn.port ?? 3306}/${
47
+ tConn.database
48
+ }` ===
49
+ `${pConn.host ?? "localhost"}:${pConn.port ?? 3306}/${pConn.database}`
49
50
  ) {
50
- throw new Error("테스트DB와 프로덕션DB의 접속 정보가 동일합니다.");
51
+ throw new Error(
52
+ `테스트DB와 프로덕션DB에 동일한 데이터베이스가 사용되었습니다.`
53
+ );
51
54
  }
52
55
  }
53
56
 
@@ -102,50 +105,6 @@ export class FixtureManagerClass {
102
105
  // console.timeEnd("FIXTURE-CleanAndSeed");
103
106
  }
104
107
 
105
- // TODO: 추후 작업
106
- async initFixtureDB() {
107
- const connectArgs = `-uDB_USER -pDB_PASS`;
108
-
109
- console.log("DUMP...");
110
- execSync(
111
- `mysqldump -hwdb.closedshops.com ${connectArgs} --single-transaction -d --no-create-db --triggers --ignore-table=closedshops.pm_backup closedshops > /tmp/closedshops_scheme.sql`
112
- );
113
- console.log("SYNC to (TESTING) LOCAL closedshops...");
114
- execSync(
115
- `mysql -hlocal.closedshops.com ${connectArgs} -e 'DROP DATABASE closedshops'`
116
- );
117
- execSync(
118
- `mysql -hlocal.closedshops.com ${connectArgs} -e 'CREATE DATABASE closedshops'`
119
- );
120
- execSync(
121
- `mysql -hlocal.closedshops.com ${connectArgs} closedshops < /tmp/closedshops_scheme.sql;`
122
- );
123
- console.log("SED database names...");
124
- execSync(
125
- `sed -i'' -e 's/\`closedshops\`/\`closedshops_fixture\`/g' /tmp/closedshops_scheme.sql`
126
- );
127
- console.log("SYNC to (REMOTE FIXTURE) REMOTE closedshops_fixture...");
128
- execSync(
129
- `mysql -hwdb.closedshops.com ${connectArgs} -e 'DROP DATABASE closedshops_fixture'`
130
- );
131
- execSync(
132
- `mysql -hwdb.closedshops.com ${connectArgs} -e 'CREATE DATABASE closedshops_fixture'`
133
- );
134
- execSync(
135
- `mysql -hwdb.closedshops.com ${connectArgs} closedshops_fixture < /tmp/closedshops_scheme.sql;`
136
- );
137
- console.log("SYNC to (LOCAL FIXTURE) closedshops_fixture...");
138
- execSync(
139
- `mysql -hlocal.closedshops.com ${connectArgs} -e 'DROP DATABASE closedshops_fixture'`
140
- );
141
- execSync(
142
- `mysql -hlocal.closedshops.com ${connectArgs} -e 'CREATE DATABASE closedshops_fixture'`
143
- );
144
- execSync(
145
- `mysql -hlocal.closedshops.com ${connectArgs} closedshops_fixture < /tmp/closedshops_scheme.sql;`
146
- );
147
- }
148
-
149
108
  async getChecksum(db: Knex, tableName: string) {
150
109
  const [[checksumRow]] = await db.raw(`CHECKSUM TABLE ${tableName}`);
151
110
  return checksumRow.Checksum;
@@ -39,8 +39,6 @@ export type DistributiveOmit<T, K extends keyof any> = T extends any
39
39
  export type CommonProp = {
40
40
  name: string;
41
41
  nullable?: boolean;
42
- index?: true | string[];
43
- unique?: true | string[];
44
42
  toFilter?: true;
45
43
  desc?: string;
46
44
  dbDefault?: string | number | { raw: string };