@simplysm/sd-cli 12.9.18 → 12.9.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/entry/sd-cli-cordova.d.ts +2 -2
  2. package/dist/entry/sd-cli-cordova.js +12 -12
  3. package/dist/entry/sd-cli-cordova.js.map +1 -1
  4. package/dist/entry/sd-cli-electron.d.ts +6 -1
  5. package/dist/entry/sd-cli-electron.js +85 -142
  6. package/dist/entry/sd-cli-electron.js.map +1 -1
  7. package/dist/entry/sd-cli-project.js +1 -1
  8. package/dist/entry/sd-cli-project.js.map +1 -1
  9. package/dist/fix/convert-ecma-private-to-ts-private.d.ts +1 -0
  10. package/dist/fix/{convert-private.js → convert-ecma-private-to-ts-private.js} +7 -8
  11. package/dist/fix/convert-ecma-private-to-ts-private.js.map +1 -0
  12. package/dist/fix/convert-ordering-interface.d.ts +1 -0
  13. package/dist/fix/convert-ordering-interface.js +46 -0
  14. package/dist/fix/convert-ordering-interface.js.map +1 -0
  15. package/dist/fix/convert-sd-sheet-bindings-inInline-template.d.ts +1 -0
  16. package/dist/fix/convert-sd-sheet-bindings-inInline-template.js +49 -0
  17. package/dist/fix/convert-sd-sheet-bindings-inInline-template.js.map +1 -0
  18. package/dist/fix/core/get-ts-morph-source-files.d.ts +1 -0
  19. package/dist/fix/core/get-ts-morph-source-files.js +8 -0
  20. package/dist/fix/core/get-ts-morph-source-files.js.map +1 -0
  21. package/dist/fix/prefix-underscore-for-access-modifiers.d.ts +1 -0
  22. package/dist/fix/{convert-private-underscore.js → prefix-underscore-for-access-modifiers.js} +13 -10
  23. package/dist/fix/prefix-underscore-for-access-modifiers.js.map +1 -0
  24. package/dist/pkg-builders/client/sd-client.build-runner.js +1 -1
  25. package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
  26. package/dist/sd-cli-entry.js +12 -5
  27. package/dist/sd-cli-entry.js.map +1 -1
  28. package/dist/ts-compiler/create-model-rewrite.transformer.d.ts +2 -0
  29. package/dist/ts-compiler/create-model-rewrite.transformer.js +52 -0
  30. package/dist/ts-compiler/create-model-rewrite.transformer.js.map +1 -0
  31. package/dist/ts-compiler/sd-ts-compiler.js +2 -0
  32. package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
  33. package/package.json +8 -8
  34. package/src/entry/sd-cli-cordova.ts +17 -13
  35. package/src/entry/sd-cli-electron.ts +115 -179
  36. package/src/entry/sd-cli-project.ts +4 -1
  37. package/src/fix/{convert-private.ts → convert-ecma-private-to-ts-private.ts} +5 -8
  38. package/src/fix/convert-ordering-interface.ts +56 -0
  39. package/src/fix/convert-sd-sheet-bindings-inInline-template.ts +62 -0
  40. package/src/fix/core/get-ts-morph-source-files.ts +9 -0
  41. package/src/fix/{convert-private-underscore.ts → prefix-underscore-for-access-modifiers.ts} +12 -13
  42. package/src/pkg-builders/client/sd-client.build-runner.ts +1 -1
  43. package/src/sd-cli-entry.ts +14 -5
  44. package/src/ts-compiler/create-model-rewrite.transformer.ts +119 -0
  45. package/src/ts-compiler/sd-ts-compiler.ts +2 -0
  46. package/dist/fix/convert-private-underscore.d.ts +0 -1
  47. package/dist/fix/convert-private-underscore.js.map +0 -1
  48. package/dist/fix/convert-private.d.ts +0 -1
  49. package/dist/fix/convert-private.js.map +0 -1
@@ -4,66 +4,24 @@ import electronBuilder from "electron-builder";
4
4
  import { ISdClientBuilderElectronConfig } from "../types/config.types";
5
5
  import { INpmConfig } from "../types/common-configs.types";
6
6
  import { loadProjConfAsync } from "./utils/loadProjConfAsync";
7
+ import os from "os";
8
+ import fs from "node:fs";
7
9
 
8
10
  export class SdCliElectron {
11
+ private static _logger = SdLogger.get(["simplysm", "sd-cli", "SdCliElectron"]);
12
+
9
13
  static async runAsync(opt: {
10
14
  package: string
11
15
  config: string;
12
16
  options?: string[];
13
17
  }) {
14
- const logger = SdLogger.get(["simplysm", "sd-cli", "SdCliElectron", "runAsync"]);
15
-
16
- const pkgPath = path.resolve(process.cwd(), `packages/${opt.package}`);
17
- const electronPath = path.resolve(pkgPath, "dist/electron");
18
-
19
- logger.log("설정 가져오기...");
20
- const projConf = await loadProjConfAsync(process.cwd(), true, opt);
21
- const pkgConf = projConf.packages[opt.package];
22
- if (pkgConf?.type !== "client" || pkgConf.builder?.electron === undefined) {
23
- throw new Error();
24
- }
25
-
26
- logger.log("package.json 파일 쓰기...");
27
- const npmConfig = FsUtils.readJson(path.resolve(pkgPath, `package.json`)) as INpmConfig;
28
-
29
- const reinstallPkgNames = pkgConf.builder.electron.reinstallDependencies ?? [];
30
-
31
- FsUtils.writeJson(path.resolve(electronPath, `package.json`), {
32
- name: npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
33
- version: npmConfig.version,
34
- description: npmConfig.description,
35
- main: "electron-main.js",
36
- ...(pkgConf.builder.electron.postInstallScript !== undefined
37
- ? {
38
- scripts: {
39
- postinstall: pkgConf.builder.electron.postInstallScript,
40
- },
41
- }
42
- : {}),
43
- dependencies: reinstallPkgNames.toObject(
44
- (item) => item,
45
- (item) => npmConfig.dependencies![item],
46
- ),
47
- });
48
-
49
- logger.log("npm install...");
50
- await SdProcess.spawnAsync(`npm install`, { cwd: electronPath }, true);
18
+ this._logger.log("설정 가져오기...");
19
+ const { pkgPath, electronPath, electronConfig } = await this._loadDevConfig(opt);
51
20
 
52
- logger.log(`electron rebuild`);
53
- await SdProcess.spawnAsync(`npx electron-rebuild`, { cwd: electronPath }, true);
21
+ this._logger.log("준비...");
22
+ await this._prepareAsync({ pkgPath, electronPath, electronConfig });
54
23
 
55
- /*for (const reinstallPkgName of reinstallPkgNames) {
56
- if (FsUtil.exists(path.resolve(electronPath, "node_modules", reinstallPkgName, "binding.gyp"))) {
57
- logger.log(`electron rebuild (${reinstallPkgName})...`);
58
- await SdProcess.spawnAsync(
59
- `electron-rebuild -m ./node_modules/${reinstallPkgName}`,
60
- { cwd: electronPath },
61
- true,
62
- );
63
- }
64
- }*/
65
-
66
- logger.log("electron...");
24
+ this._logger.log("실행...");
67
25
  await SdProcess.spawnAsync(`npx electron .`, { cwd: electronPath }, true);
68
26
  }
69
27
 
@@ -72,123 +30,74 @@ export class SdCliElectron {
72
30
  config: string;
73
31
  options?: string[];
74
32
  }) {
75
- const logger = SdLogger.get(["simplysm", "sd-cli", "SdCliElectron", "buildForDevAsync"]);
33
+ this._logger.log("설정 가져오기...");
34
+ const { pkgPath, electronPath, electronConfig } = await this._loadDevConfig(opt);
76
35
 
77
- const pkgPath = path.resolve(process.cwd(), `packages/${opt.package}`);
78
- const electronPath = path.resolve(pkgPath, "dist/electron");
36
+ this._logger.log("준비...");
37
+ const { npmConfig } = await this._prepareAsync({ pkgPath, electronPath, electronConfig });
38
+
39
+ this._logger.log("빌드...");
79
40
  const electronDistPath = path.resolve(pkgPath, ".electron/dist");
41
+ await this._buildAsync({ pkgPath, electronPath, electronDistPath, npmConfig, electronConfig });
42
+ }
43
+
44
+ static async buildAsync(opt: {
45
+ pkgPath: string;
46
+ electronConfig: ISdClientBuilderElectronConfig
47
+ }) {
48
+ this._logger.log("준비...");
49
+ const electronPath = path.resolve(opt.pkgPath, ".electron/src");
50
+ const { npmConfig } = await this._prepareAsync({ ...opt, electronPath });
80
51
 
81
- logger.log("설정 가져오기...");
52
+ this._logger.log("빌드...");
53
+ const electronDistPath = path.resolve(opt.pkgPath, ".electron/dist");
54
+ await this._buildAsync({
55
+ pkgPath: opt.pkgPath,
56
+ electronPath,
57
+ electronDistPath,
58
+ npmConfig,
59
+ electronConfig: opt.electronConfig,
60
+ });
61
+ }
62
+
63
+ private static async _loadDevConfig(opt: {
64
+ package: string
65
+ config: string;
66
+ options?: string[];
67
+ }) {
82
68
  const projConf = await loadProjConfAsync(process.cwd(), true, opt);
83
69
  const pkgConf = projConf.packages[opt.package];
84
70
  if (pkgConf?.type !== "client" || pkgConf.builder?.electron === undefined) {
85
71
  throw new Error();
86
72
  }
73
+ const pkgPath = path.resolve(process.cwd(), `packages/${opt.package}`);
74
+ const electronPath = path.resolve(pkgPath, "dist/electron");
87
75
 
88
- logger.log("package.json 파일 쓰기...");
89
- const npmConfig = FsUtils.readJson(path.resolve(pkgPath, `package.json`)) as INpmConfig;
90
-
91
- const reinstallPkgNames = pkgConf.builder.electron.reinstallDependencies ?? [];
92
-
93
- FsUtils.writeJson(path.resolve(electronPath, `package.json`), {
94
- name: npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
95
- version: npmConfig.version,
96
- description: npmConfig.description,
97
- main: "electron-main.js",
98
- ...(pkgConf.builder.electron.postInstallScript !== undefined
99
- ? {
100
- scripts: {
101
- postinstall: pkgConf.builder.electron.postInstallScript,
102
- },
103
- }
104
- : {}),
105
- dependencies: reinstallPkgNames.toObject(
106
- (item) => item,
107
- (item) => npmConfig.dependencies![item],
108
- ),
109
- });
110
-
111
- logger.log("npm install...");
112
- await SdProcess.spawnAsync(`npm install`, { cwd: electronPath }, true);
113
-
114
- logger.log(`electron rebuild`);
115
- await SdProcess.spawnAsync(`npx electron-rebuild`, { cwd: electronPath }, true);
116
-
117
- /*for (const reinstallPkgName of reinstallPkgNames) {
118
- if (FsUtils.exists(path.resolve(electronPath, "node_modules", reinstallPkgName, "binding.gyp"))) {
119
- logger.log(`electron rebuild (${reinstallPkgName})...`);
120
- await SdProcess.spawnAsync(
121
- `electron-rebuild -m ./node_modules/${reinstallPkgName}`,
122
- { cwd: electronPath },
123
- true,
124
- );
125
- }
126
- }*/
127
-
128
- logger.log("build...");
129
-
130
- await electronBuilder.build({
131
- targets: electronBuilder.Platform.WINDOWS.createTarget(),
132
- config: {
133
- appId: pkgConf.builder.electron.appId,
134
- productName: npmConfig.description,
135
- asar: false,
136
- win: {
137
- target: pkgConf.builder.electron.portable ? "portable" : "nsis",
138
- },
139
- nsis: {},
140
- directories: {
141
- app: electronPath,
142
- output: electronDistPath,
143
- },
144
- ...(pkgConf.builder.electron.installerIcon !== undefined
145
- ? {
146
- icon: path.resolve(pkgPath, pkgConf.builder.electron.installerIcon),
147
- }
148
- : {}),
149
- removePackageScripts: false,
150
- },
151
- });
152
-
153
- FsUtils.copy(
154
- path.resolve(
155
- electronDistPath,
156
- `${npmConfig.description} ${pkgConf.builder.electron.portable
157
- ? ""
158
- : "Setup "}${npmConfig.version}.exe`,
159
- ),
160
- path.resolve(
161
- pkgPath,
162
- `dist/electron/${npmConfig.description}${pkgConf.builder.electron.portable
163
- ? "-portable"
164
- : ""}-dev.exe`,
165
- ),
166
- );
76
+ return {
77
+ pkgPath,
78
+ electronPath,
79
+ electronConfig: pkgConf.builder.electron,
80
+ };
167
81
  }
168
82
 
169
- static async buildAsync(opt: {
83
+ private static async _prepareAsync(opt: {
170
84
  pkgPath: string;
171
- config: ISdClientBuilderElectronConfig
85
+ electronPath: string;
86
+ electronConfig: ISdClientBuilderElectronConfig;
172
87
  }) {
173
- const logger = SdLogger.get(["simplysm", "sd-cli", "SdCliElectron", "buildAsync"]);
174
-
175
- const electronSrcPath = path.resolve(opt.pkgPath, ".electron/src");
176
- const electronDistPath = path.resolve(opt.pkgPath, ".electron/dist");
177
-
178
- logger.log("package.json 파일 쓰기...");
179
88
  const npmConfig = FsUtils.readJson(path.resolve(opt.pkgPath, `package.json`)) as INpmConfig;
180
89
 
181
- const reinstallPkgNames = opt.config.reinstallDependencies ?? [];
90
+ const reinstallPkgNames = opt.electronConfig.reinstallDependencies ?? [];
182
91
 
183
- FsUtils.writeJson(path.resolve(electronSrcPath, `package.json`), {
92
+ FsUtils.writeJson(path.resolve(opt.electronPath, `package.json`), {
184
93
  name: npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
185
94
  version: npmConfig.version,
186
95
  description: npmConfig.description,
187
96
  main: "electron-main.js",
188
- ...(opt.config.postInstallScript !== undefined
97
+ ...(opt.electronConfig.postInstallScript !== undefined
189
98
  ? {
190
99
  scripts: {
191
- postinstall: opt.config.postInstallScript,
100
+ postinstall: opt.electronConfig.postInstallScript,
192
101
  },
193
102
  }
194
103
  : {}),
@@ -198,60 +107,59 @@ export class SdCliElectron {
198
107
  ),
199
108
  });
200
109
 
201
- logger.log("npm install...");
202
- await SdProcess.spawnAsync(`npm install`, { cwd: electronSrcPath }, true);
110
+ await SdProcess.spawnAsync(`npm install`, { cwd: opt.electronPath }, true);
111
+
112
+ await SdProcess.spawnAsync(`npx electron-rebuild`, { cwd: opt.electronPath }, true);
203
113
 
204
- logger.log(`electron rebuild`);
205
- await SdProcess.spawnAsync(`npx electron-rebuild`, { cwd: electronSrcPath }, true);
114
+ return { npmConfig };
115
+ }
206
116
 
207
- /*for (const reinstallPkgName of reinstallPkgNames) {
208
- if (FsUtils.exists(path.resolve(
209
- electronSrcPath,
210
- "node_modules",
211
- reinstallPkgName,
212
- "binding.gyp",
213
- ))) {
214
- logger.log(`electron rebuild (${reinstallPkgName})...`);
215
- await SdProcess.spawnAsync(
216
- `electron-rebuild -m ./node_modules/${reinstallPkgName}`,
217
- { cwd: electronSrcPath },
218
- true,
219
- );
220
- }
221
- }*/
117
+ private static async _buildAsync(opt: {
118
+ pkgPath: string;
119
+ electronPath: string;
120
+ electronDistPath: string;
121
+ npmConfig: INpmConfig;
122
+ electronConfig: ISdClientBuilderElectronConfig
123
+ }) {
124
+ if (!this._canCreateSymlink()) {
125
+ throw new Error("'Electron 빌드'를 위해서는 'Symlink 생성' 권한이 필요합니다. 윈도우의 개발자모드를 활성화하세요.");
126
+ }
222
127
 
223
- logger.log("build...");
224
128
  await electronBuilder.build({
225
129
  targets: electronBuilder.Platform.WINDOWS.createTarget(),
226
130
  config: {
227
- appId: opt.config.appId,
228
- productName: npmConfig.description,
131
+ appId: opt.electronConfig.appId,
132
+ productName: opt.npmConfig.description,
229
133
  asar: false,
230
134
  win: {
231
- target: opt.config.portable ? "portable" : "nsis",
135
+ target: opt.electronConfig.portable ? "portable" : "nsis",
232
136
  },
233
137
  nsis: {},
234
138
  directories: {
235
- app: electronSrcPath,
236
- output: electronDistPath,
139
+ app: opt.electronPath,
140
+ output: opt.electronDistPath,
237
141
  },
238
- ...(opt.config.installerIcon !== undefined
142
+ ...(opt.electronConfig.installerIcon !== undefined
239
143
  ? {
240
- icon: path.resolve(opt.pkgPath, opt.config.installerIcon),
144
+ icon: path.resolve(opt.pkgPath, opt.electronConfig.installerIcon),
241
145
  }
242
146
  : {}),
243
147
  removePackageScripts: false,
148
+ npmRebuild: false,
149
+ forceCodeSigning: false,
244
150
  },
245
151
  });
246
152
 
247
153
  FsUtils.copy(
248
154
  path.resolve(
249
- electronDistPath,
250
- `${npmConfig.description} ${opt.config.portable ? "" : "Setup "}${npmConfig.version}.exe`,
155
+ opt.electronDistPath,
156
+ `${opt.npmConfig.description} ${opt.electronConfig.portable
157
+ ? ""
158
+ : "Setup "}${opt.npmConfig.version}.exe`,
251
159
  ),
252
160
  path.resolve(
253
161
  opt.pkgPath,
254
- `dist/electron/${npmConfig.description}${opt.config.portable
162
+ `dist/electron/${opt.npmConfig.description}${opt.electronConfig.portable
255
163
  ? "-portable"
256
164
  : ""}-latest.exe`,
257
165
  ),
@@ -259,10 +167,38 @@ export class SdCliElectron {
259
167
 
260
168
  FsUtils.copy(
261
169
  path.resolve(
262
- electronDistPath,
263
- `${npmConfig.description} ${opt.config.portable ? "" : "Setup "}${npmConfig.version}.exe`,
170
+ opt.electronDistPath,
171
+ `${opt.npmConfig.description} ${opt.electronConfig.portable
172
+ ? ""
173
+ : "Setup "}${opt.npmConfig.version}.exe`,
264
174
  ),
265
- path.resolve(opt.pkgPath, `dist/electron/updates/${npmConfig.version}.exe`),
175
+ path.resolve(opt.pkgPath, `dist/electron/updates/${opt.npmConfig.version}.exe`),
266
176
  );
267
177
  }
178
+
179
+ private static _canCreateSymlink() {
180
+ const tmpDir = os.tmpdir();
181
+ const testTarget = path.join(tmpDir, "symlink-test-target.txt");
182
+ const testLink = path.join(tmpDir, "symlink-test-link.txt");
183
+
184
+ try {
185
+ // 대상 파일 생성
186
+ fs.writeFileSync(testTarget, "test");
187
+
188
+ // symlink 시도
189
+ fs.symlinkSync(testTarget, testLink, "file");
190
+
191
+ // symlink 성공 여부 확인
192
+ const isSymlink = fs.lstatSync(testLink).isSymbolicLink();
193
+
194
+ // 정리
195
+ fs.unlinkSync(testLink);
196
+ fs.unlinkSync(testTarget);
197
+
198
+ return isSymlink;
199
+ }
200
+ catch {
201
+ return false;
202
+ }
203
+ }
268
204
  }
@@ -334,7 +334,10 @@ export class SdCliProject {
334
334
  const cordovaPluginConfXml = XmlConvert.parse(FsUtils.readFile(cordovaPluginConfFilePath));
335
335
  cordovaPluginConfXml.plugin.$.version = newVersion;
336
336
 
337
- FsUtils.writeFile(cordovaPluginConfFilePath, XmlConvert.stringify(cordovaPluginConfXml));
337
+ FsUtils.writeFile(
338
+ cordovaPluginConfFilePath,
339
+ XmlConvert.stringify(cordovaPluginConfXml, { format: true }),
340
+ );
338
341
  }
339
342
  }
340
343
  }
@@ -1,13 +1,10 @@
1
1
  /* eslint-disable no-console */
2
2
 
3
- import { MethodDeclaration, Project, PropertyAccessExpression, SyntaxKind } from "ts-morph";
3
+ import { MethodDeclaration, PropertyAccessExpression, SyntaxKind } from "ts-morph";
4
+ import getTsMortphSourceFiles from "./core/get-ts-morph-source-files";
4
5
 
5
- export default function convertPrivate() {
6
- const project = new Project({
7
- tsConfigFilePath: "tsconfig.base.json",
8
- });
9
-
10
- const sourceFiles = project.getSourceFiles("packages/*/src/**/*.ts");
6
+ export default function convertEcmaPrivateToTsPrivate() {
7
+ const sourceFiles = getTsMortphSourceFiles();
11
8
 
12
9
  for (const sourceFile of sourceFiles) {
13
10
  for (const classDec of sourceFile.getClasses()) {
@@ -70,5 +67,5 @@ export default function convertPrivate() {
70
67
  }
71
68
  }
72
69
 
73
- console.log(" ECMAScript private (#field)TypeScript private _field 변환 완료");
70
+ console.log("[완료] #field/#method → private _field/_method 변환 완료");
74
71
  }
@@ -0,0 +1,56 @@
1
+ /* eslint-disable no-console */
2
+ import { SyntaxKind } from "ts-morph";
3
+ import getTsMortphSourceFiles from "./core/get-ts-morph-source-files";
4
+
5
+ export default function convertOrderingInterface() {
6
+ const sourceFiles = getTsMortphSourceFiles();
7
+
8
+ for (const sourceFile of sourceFiles) {
9
+ let changed = false;
10
+
11
+ // 1. import 교체
12
+ for (const importDecl of sourceFile.getImportDeclarations()) {
13
+ if (importDecl.getModuleSpecifierValue() !== "@simplysm/sd-angular") continue;
14
+
15
+ const namedImports = importDecl.getNamedImports();
16
+
17
+ let hasOld = false;
18
+ let hasNew = false;
19
+
20
+ for (const ni of namedImports) {
21
+ const name = ni.getName();
22
+ if (name === "ISdSheetColumnOrderingVM") {
23
+ ni.remove(); // ← ✅ 이 방식으로 제거
24
+ hasOld = true;
25
+ }
26
+ if (name === "ISortingDef") {
27
+ hasNew = true;
28
+ }
29
+ }
30
+
31
+ if (hasOld && !hasNew) {
32
+ importDecl.addNamedImport("ISortingDef");
33
+ changed = true;
34
+ console.log(`[import-updated] ${sourceFile.getBaseName()} :: import 교체 완료`);
35
+ }
36
+ }
37
+
38
+ // 2. 타입 참조 교체
39
+ sourceFile.forEachDescendant((node) => {
40
+ if (
41
+ node.getKind() === SyntaxKind.TypeReference &&
42
+ node.getText() === "ISdSheetColumnOrderingVM"
43
+ ) {
44
+ node.replaceWithText("ISortingDef");
45
+ changed = true;
46
+ console.log(`[type-replaced] ${sourceFile.getBaseName()} :: 타입 참조 변경`);
47
+ }
48
+ });
49
+
50
+ if (changed) {
51
+ sourceFile.saveSync();
52
+ }
53
+ }
54
+
55
+ console.log("[완료] ISdSheetColumnOrderingVM → ISortingDef 변환 완료");
56
+ }
@@ -0,0 +1,62 @@
1
+ /* eslint-disable no-console */
2
+ import { SyntaxKind } from "ts-morph";
3
+ import getTsMortphSourceFiles from "./core/get-ts-morph-source-files";
4
+
5
+ export default function convertSdSheetBindingsSafely() {
6
+ const sourceFiles = getTsMortphSourceFiles();
7
+
8
+ for (const sourceFile of sourceFiles) {
9
+ for (const classDecl of sourceFile.getClasses()) {
10
+ const decorator = classDecl.getDecorator("Component");
11
+ if (!decorator) continue;
12
+
13
+ const arg = decorator.getArguments()[0];
14
+ if (!arg.asKind(SyntaxKind.ObjectLiteralExpression)) continue;
15
+
16
+ const obj = arg.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
17
+ const templateProp = obj.getProperty("template");
18
+ if (!templateProp || !templateProp.isKind(SyntaxKind.PropertyAssignment)) continue;
19
+
20
+ const initializer = templateProp.getInitializer();
21
+ if (!initializer) continue;
22
+
23
+ let rawTemplate: string | undefined;
24
+ if (initializer.isKind(SyntaxKind.NoSubstitutionTemplateLiteral) || initializer.isKind(
25
+ SyntaxKind.StringLiteral)) {
26
+ rawTemplate = initializer.getLiteralText();
27
+ }
28
+ else if (initializer.isKind(SyntaxKind.TemplateExpression)) {
29
+ rawTemplate = initializer.getFullText().slice(1, -1);
30
+ }
31
+ else continue;
32
+
33
+ // 정규식으로 <sd-sheet> 안에서만 바인딩 속성 치환
34
+ let newTemplate = rawTemplate.replace(
35
+ /<sd-sheet([\s\S]*?)>/g,
36
+ (match) =>
37
+ match
38
+ .replace(/\[\(page\)\]/g, "[(currentPage)]")
39
+ .replace(/\[pageLength\]/g, "[totalPageCount]")
40
+ .replace(/\[\(ordering\)\]/g, "[(sorts)]")
41
+ .replace(/\[pageItemCount\]/g, "[itemsPerPage]"),
42
+ );
43
+
44
+ newTemplate = newTemplate.replace(
45
+ /<sd-pagination([\s\S]*?)>/g,
46
+ (match) =>
47
+ match
48
+ .replace(/\[\(page\)\]/g, "[(currentPage)]")
49
+ .replace(/\[pageLength\]/g, "[totalPageCount]")
50
+ .replace(/\[displayPageLength\]/g, "[visiblePageCount]"),
51
+ );
52
+
53
+ if (rawTemplate !== newTemplate) {
54
+ initializer.replaceWithText("`" + newTemplate + "`");
55
+ console.log(`[template-updated] ${sourceFile.getBaseName()} :: 바인딩 속성 안전하게 변경 완료`);
56
+ sourceFile.saveSync();
57
+ }
58
+ }
59
+ }
60
+
61
+ console.log("[완료] 정규식 기반 안전한 sd-sheet 바인딩 속성 변경 완료");
62
+ }
@@ -0,0 +1,9 @@
1
+ import { Project } from "ts-morph";
2
+
3
+ export default function getTsMortphSourceFiles() {
4
+ const project = new Project({
5
+ tsConfigFilePath: "tsconfig.base.json",
6
+ });
7
+
8
+ return project.getSourceFiles("packages/*/src/**/*.ts");
9
+ }
@@ -1,22 +1,18 @@
1
1
  /* eslint-disable no-console */
2
-
3
2
  import {
4
3
  MethodDeclaration,
5
- Project,
6
4
  PropertyAccessExpression,
7
5
  PropertyDeclaration,
8
6
  SyntaxKind,
9
7
  } from "ts-morph";
8
+ import getTsMortphSourceFiles from "./core/get-ts-morph-source-files";
10
9
 
11
- export default function convertPrivateUnderscore() {
12
- const project = new Project({
13
- tsConfigFilePath: "tsconfig.base.json",
14
- });
15
-
16
- const sourceFiles = project.getSourceFiles("packages/*/src/**/*.ts");
10
+ export default function prefixUnderscoreForAccessModifiers() {
11
+ const sourceFiles = getTsMortphSourceFiles();
17
12
 
18
13
  for (const sourceFile of sourceFiles) {
19
14
  for (const classDec of sourceFile.getClasses()) {
15
+ let changed = false;
20
16
  const members = classDec.getMembers();
21
17
 
22
18
  for (const member of members) {
@@ -57,13 +53,16 @@ export default function convertPrivateUnderscore() {
57
53
  }
58
54
  });
59
55
 
60
- console.log(`[updated] ${sourceFile.getBaseName()} :: ${originalName} → ${newName}`);
56
+ console.log(`[private-or-protected] ${sourceFile.getBaseName()} :: ${originalName} → ${newName}`);
57
+ changed = true;
61
58
  }
62
59
  }
63
- }
64
60
 
65
- sourceFile.saveSync();
61
+ if (changed) {
62
+ sourceFile.saveSync();
63
+ }
64
+ }
66
65
  }
67
66
 
68
- console.log(" private/protected prefix 변환 완료");
69
- }
67
+ console.log("[완료] private/protected 멤버 → _접두사 변환 완료");
68
+ }
@@ -104,7 +104,7 @@ export class SdClientBuildRunner extends BuildRunnerBase<"client"> {
104
104
  this._debug("ELECTRON BUILD...");
105
105
  await SdCliElectron.buildAsync({
106
106
  pkgPath: this._pkgPath,
107
- config: this._pkgConf.builder.electron,
107
+ electronConfig: this._pkgConf.builder.electron,
108
108
  });
109
109
  }
110
110
 
@@ -12,8 +12,11 @@ import { SdCliLocalUpdate } from "./entry/sd-cli-local-update";
12
12
  import { SdCliCordova } from "./entry/sd-cli-cordova";
13
13
  import { SdCliAiCommand } from "./entry/sd-cli-ai-command";
14
14
  import { SdCliPostinstall } from "./entry/sd-cli-postinstall";
15
- import convertPrivate from "./fix/convert-private";
16
- import convertPrivateUnderscore from "./fix/convert-private-underscore";
15
+ import convertEcmaPrivateToTsPrivate from "./fix/convert-ecma-private-to-ts-private";
16
+ import prefixUnderscoreForAccessModifiers from "./fix/prefix-underscore-for-access-modifiers";
17
+ import convertSdSheetBindingsInInlineTemplate
18
+ from "./fix/convert-sd-sheet-bindings-inInline-template";
19
+ import convertOrderingInterface from "./fix/convert-ordering-interface";
17
20
 
18
21
  Error.stackTraceLimit = Infinity;
19
22
  EventEmitter.defaultMaxListeners = 0;
@@ -250,14 +253,20 @@ await yargs(hideBin(process.argv))
250
253
  .hide("help")
251
254
  .hide("debug"),
252
255
  () => {
253
- convertPrivate();
254
- convertPrivateUnderscore();
256
+ convertEcmaPrivateToTsPrivate();
257
+ prefixUnderscoreForAccessModifiers();
258
+ convertSdSheetBindingsInInlineTemplate();
259
+ convertOrderingInterface();
255
260
  },
256
261
  )
257
262
  .strict()
258
263
  .recommendCommands()
259
264
  .fail((msg, err, cmd) => {
260
- console.error("🚫 지원되지 않는 명령입니다.");
265
+ if (Boolean(err)) {
266
+ throw err;
267
+ }
268
+
269
+ console.error("지원되지 않는 명령입니다.");
261
270
  console.error(msg);
262
271
  console.log("\n명령어 목록:");
263
272
  cmd.showHelp();