@simplysm/sd-cli 14.0.16 → 14.0.17
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/README.md +2 -1
- package/dist/angular/client-transform-stylesheet.d.ts +2 -0
- package/dist/angular/client-transform-stylesheet.d.ts.map +1 -1
- package/dist/angular/client-transform-stylesheet.js +88 -2
- package/dist/angular/client-transform-stylesheet.js.map +1 -1
- package/dist/angular/vite-angular-plugin.d.ts +7 -0
- package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
- package/dist/angular/vite-angular-plugin.js +78 -16
- package/dist/angular/vite-angular-plugin.js.map +1 -1
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +9 -13
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +8 -9
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +33 -1
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/lint.d.ts +0 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +2 -3
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/publish.js +2 -2
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +0 -1
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/electron/electron.d.ts +3 -2
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +54 -31
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.js +1 -1
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/engines/NgtscEngine.d.ts.map +1 -1
- package/dist/engines/NgtscEngine.js +0 -1
- package/dist/engines/NgtscEngine.js.map +1 -1
- package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
- package/dist/engines/ServerEsbuildEngine.js +0 -1
- package/dist/engines/ServerEsbuildEngine.js.map +1 -1
- package/dist/engines/TscEngine.d.ts.map +1 -1
- package/dist/engines/TscEngine.js +0 -1
- package/dist/engines/TscEngine.js.map +1 -1
- package/dist/engines/ViteEngine.d.ts.map +1 -1
- package/dist/engines/ViteEngine.js +8 -1
- package/dist/engines/ViteEngine.js.map +1 -1
- package/dist/engines/index.d.ts +0 -10
- package/dist/engines/index.d.ts.map +1 -1
- package/dist/engines/index.js +0 -5
- package/dist/engines/index.js.map +1 -1
- package/dist/engines/types.d.ts +0 -1
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/infra/SignalHandler.d.ts +1 -6
- package/dist/infra/SignalHandler.d.ts.map +1 -1
- package/dist/infra/SignalHandler.js +4 -13
- package/dist/infra/SignalHandler.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +7 -12
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.js +17 -10
- package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +0 -1
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +7 -8
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-config.types.d.ts +11 -1
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/angular-compiler.d.ts.map +1 -1
- package/dist/utils/angular-compiler.js +20 -13
- package/dist/utils/angular-compiler.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts +1 -1
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +1 -4
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
- package/dist/utils/ngtsc-build-core.js +3 -0
- package/dist/utils/ngtsc-build-core.js.map +1 -1
- package/dist/utils/tsc-build.d.ts +5 -0
- package/dist/utils/tsc-build.d.ts.map +1 -1
- package/dist/utils/tsc-build.js +2 -1
- package/dist/utils/tsc-build.js.map +1 -1
- package/dist/utils/vite-config.d.ts +1 -1
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +22 -53
- package/dist/utils/vite-config.js.map +1 -1
- package/dist/utils/vite-pwa-plugin.d.ts +9 -0
- package/dist/utils/vite-pwa-plugin.d.ts.map +1 -0
- package/dist/utils/vite-pwa-plugin.js +139 -0
- package/dist/utils/vite-pwa-plugin.js.map +1 -0
- package/dist/utils/worker-utils.d.ts +2 -5
- package/dist/utils/worker-utils.d.ts.map +1 -1
- package/dist/utils/worker-utils.js +5 -11
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +9 -3
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +6 -2
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/ngtsc-build.worker.js +2 -2
- package/dist/workers/ngtsc-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +6 -2
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.js +4 -4
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/docs/config.md +26 -0
- package/docs/pwa-configuration-types.md +1 -1
- package/package.json +8 -10
- package/src/angular/client-transform-stylesheet.ts +104 -2
- package/src/angular/vite-angular-plugin.ts +92 -31
- package/src/capacitor/capacitor.ts +10 -26
- package/src/commands/check.ts +8 -11
- package/src/commands/device.ts +38 -3
- package/src/commands/lint.ts +2 -3
- package/src/commands/publish.ts +2 -2
- package/src/commands/typecheck.ts +0 -1
- package/src/electron/electron.ts +62 -43
- package/src/engines/BaseEngine.ts +1 -1
- package/src/engines/NgtscEngine.ts +0 -1
- package/src/engines/ServerEsbuildEngine.ts +0 -1
- package/src/engines/TscEngine.ts +0 -1
- package/src/engines/ViteEngine.ts +7 -1
- package/src/engines/index.ts +0 -10
- package/src/engines/types.ts +0 -1
- package/src/infra/SignalHandler.ts +4 -14
- package/src/orchestrators/BuildOrchestrator.ts +7 -9
- package/src/orchestrators/DevWatchOrchestrator.ts +21 -9
- package/src/sd-cli-entry.ts +11 -16
- package/src/sd-config.types.ts +12 -1
- package/src/utils/angular-compiler.ts +21 -21
- package/src/utils/esbuild-config.ts +2 -5
- package/src/utils/ngtsc-build-core.ts +7 -0
- package/src/utils/tsc-build.ts +7 -0
- package/src/utils/vite-config.ts +23 -55
- package/src/utils/vite-pwa-plugin.ts +168 -0
- package/src/utils/worker-utils.ts +5 -11
- package/src/workers/client.worker.ts +11 -3
- package/src/workers/library-build.worker.ts +6 -2
- package/src/workers/ngtsc-build.worker.ts +2 -2
- package/src/workers/server-build.worker.ts +7 -2
- package/src/workers/server-runtime.worker.ts +4 -4
- package/tests/angular/client-transform-stylesheet.spec.ts +43 -0
- package/tests/angular/find-affected-by-scss.spec.ts +37 -0
- package/tests/angular/fixtures/basic-app/scss/_colors.scss +1 -0
- package/tests/angular/fixtures/basic-app/scss/_variables.scss +3 -0
- package/tests/angular/fixtures/basic-app/src/styled.component.ts +14 -0
- package/tests/angular/linker-disk-cache.spec.ts +158 -0
- package/tests/angular/scss-disk-cache.spec.ts +162 -0
- package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +15 -15
- package/tests/angular/vite-angular-plugin-hmr.spec.ts +9 -9
- package/tests/angular/vite-angular-plugin-lint.spec.ts +4 -4
- package/tests/angular/vite-angular-plugin-scss-hmr.spec.ts +87 -0
- package/tests/angular/vite-angular-plugin.spec.ts +15 -15
- package/tests/capacitor/capacitor-icon.spec.ts +2 -4
- package/tests/capacitor/capacitor-init.spec.ts +2 -4
- package/tests/capacitor/capacitor-workspace.spec.ts +2 -4
- package/tests/commands/device.spec.ts +100 -0
- package/tests/electron/electron.spec.ts +24 -17
- package/tests/engines/ngtsc-engine.spec.ts +0 -3
- package/tests/engines/server-esbuild-engine.spec.ts +0 -3
- package/tests/engines/tsc-engine.spec.ts +1 -2
- package/tests/engines/vite-engine.spec.ts +0 -2
- package/tests/infra/signal-handler.spec.ts +1 -12
- package/tests/orchestrators/build-orchestrator.spec.ts +0 -6
- package/tests/orchestrators/dev-watch-orchestrator.spec.ts +24 -66
- package/tests/utils/angular-compiler.spec.ts +1396 -32
- package/tests/utils/esbuild-config.spec.ts +4 -7
- package/tests/utils/{ngtsc-build-core-angular-compiler.spec.ts → ngtsc-build-core.spec.ts} +142 -11
- package/tests/utils/tsc-build.spec.ts +4 -1
- package/tests/utils/vite-config.spec.ts +130 -261
- package/tests/utils/vite-pwa-plugin.acc.spec.ts +143 -0
- package/tests/utils/vite-pwa-plugin.spec.ts +350 -0
- package/tests/utils/worker-utils.spec.ts +8 -7
- package/tests/workers/client-worker.spec.ts +50 -1
- package/tests/workers/dev-port-file.verify.md +6 -0
- package/tests/workers/library-build-lint.spec.ts +1 -1
- package/tests/workers/library-build-worker.spec.ts +1 -1
- package/tests/workers/ngtsc-build-lint.spec.ts +1 -1
- package/tests/workers/server-build-lint.spec.ts +1 -1
- package/tests/workers/server-build-worker.spec.ts +1 -1
- package/tests/workers/server-runtime-worker.spec.ts +8 -1
- package/dist/infra/WorkerManager.d.ts +0 -40
- package/dist/infra/WorkerManager.d.ts.map +0 -1
- package/dist/infra/WorkerManager.js +0 -59
- package/dist/infra/WorkerManager.js.map +0 -1
- package/dist/utils/SdCliReporter.d.ts +0 -18
- package/dist/utils/SdCliReporter.d.ts.map +0 -1
- package/dist/utils/SdCliReporter.js +0 -144
- package/dist/utils/SdCliReporter.js.map +0 -1
- package/src/infra/WorkerManager.ts +0 -65
- package/src/utils/SdCliReporter.ts +0 -177
- package/tests/angular/scss-compiler-async.spec.ts +0 -54
- package/tests/commands/dev.spec.ts +0 -53
- package/tests/commands/watch.spec.ts +0 -53
- package/tests/infra/worker-manager.spec.ts +0 -63
- package/tests/utils/angular-compiler-emit.spec.ts +0 -570
- package/tests/utils/angular-compiler-init.spec.ts +0 -705
- package/tests/utils/angular-compiler-update.spec.ts +0 -293
- package/tests/utils/build-env.spec.ts +0 -33
- package/tests/utils/ngtsc-build-core-transform-stylesheet.spec.ts +0 -124
- package/tests/utils/ngtsc-scss-refactor.spec.ts +0 -47
package/src/electron/electron.ts
CHANGED
|
@@ -3,20 +3,14 @@ import fs from "fs";
|
|
|
3
3
|
import module from "module";
|
|
4
4
|
import { cpx, fsx, pathx } from "@simplysm/core-node";
|
|
5
5
|
import { consola, LogLevels } from "consola";
|
|
6
|
-
import type { SdElectronConfig } from "../sd-config.types.js";
|
|
6
|
+
import type { NpmConfig, SdElectronConfig } from "../sd-config.types.js";
|
|
7
7
|
import { createEnvBanner } from "../utils/esbuild-config.js";
|
|
8
8
|
|
|
9
|
-
interface NpmConfig {
|
|
10
|
-
name: string;
|
|
11
|
-
version: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
dependencies?: Record<string, string>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
9
|
export class Electron {
|
|
17
10
|
private static readonly _logger = consola.withTag("sd:cli:electron");
|
|
18
11
|
|
|
19
12
|
private readonly _electronPath: string;
|
|
13
|
+
private readonly _srcPath: string;
|
|
20
14
|
|
|
21
15
|
private constructor(
|
|
22
16
|
private readonly _pkgPath: string,
|
|
@@ -25,6 +19,7 @@ export class Electron {
|
|
|
25
19
|
private readonly _exclude: string[],
|
|
26
20
|
) {
|
|
27
21
|
this._electronPath = pathx.posixResolve(this._pkgPath, ".electron");
|
|
22
|
+
this._srcPath = pathx.posixResolve(this._electronPath, "src");
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
static async create(
|
|
@@ -44,10 +39,6 @@ export class Electron {
|
|
|
44
39
|
}
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
private _localBin(name: string): string {
|
|
48
|
-
return pathx.posixResolve(this._pkgPath, "node_modules/.bin", name);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
42
|
private async _exec(
|
|
52
43
|
cmd: string,
|
|
53
44
|
args: string[],
|
|
@@ -70,20 +61,26 @@ export class Electron {
|
|
|
70
61
|
|
|
71
62
|
async initialize(): Promise<void> {
|
|
72
63
|
Electron._logger.debug("initialize 시작");
|
|
73
|
-
const srcPath = pathx.posixResolve(this._electronPath, "src");
|
|
74
64
|
|
|
75
65
|
Electron._logger.debug("package.json 설정 시작");
|
|
76
|
-
await this.
|
|
66
|
+
await this._setupNpmConf();
|
|
77
67
|
Electron._logger.debug("package.json 설정 완료");
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
// pnpm-workspace.yaml 생성 (상위 workspace 탐색 차단)
|
|
70
|
+
const workspaceYamlPath = pathx.posixResolve(this._srcPath, "pnpm-workspace.yaml");
|
|
71
|
+
if (!(await fsx.exists(workspaceYamlPath))) {
|
|
72
|
+
await fsx.write(workspaceYamlPath, "");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Electron._logger.debug("pnpm install 시작");
|
|
76
|
+
await this._exec("pnpm", ["install"], this._srcPath);
|
|
77
|
+
await this._exec("pnpm", ["approve-builds", "--all"], this._srcPath);
|
|
78
|
+
Electron._logger.debug("pnpm install 완료");
|
|
82
79
|
|
|
83
80
|
const reinstallDeps = this._config.reinstallDependencies ?? [];
|
|
84
81
|
if (reinstallDeps.length > 0) {
|
|
85
82
|
Electron._logger.debug(`electron-rebuild 시작 (${reinstallDeps.join(", ")})`);
|
|
86
|
-
await this._exec(
|
|
83
|
+
await this._exec("pnpm", ["exec", "electron-rebuild"], this._srcPath);
|
|
87
84
|
Electron._logger.debug("electron-rebuild 완료");
|
|
88
85
|
}
|
|
89
86
|
Electron._logger.debug("initialize 완료");
|
|
@@ -91,9 +88,9 @@ export class Electron {
|
|
|
91
88
|
|
|
92
89
|
async run(url: string): Promise<void> {
|
|
93
90
|
Electron._logger.debug(`run 시작 (url: ${url})`);
|
|
94
|
-
const srcPath = pathx.posixResolve(this._electronPath, "src");
|
|
95
91
|
|
|
96
92
|
await this.initialize();
|
|
93
|
+
await this._copyPublicAssets();
|
|
97
94
|
|
|
98
95
|
const esbuild = await import("esbuild");
|
|
99
96
|
const entryPoint = pathx.posixResolve(this._pkgPath, "src/electron-main.ts");
|
|
@@ -104,7 +101,6 @@ export class Electron {
|
|
|
104
101
|
|
|
105
102
|
const builtinModules = module.builtinModules.flatMap((m) => [m, `node:${m}`]);
|
|
106
103
|
const reinstallDeps = this._config.reinstallDependencies ?? [];
|
|
107
|
-
await fsx.mkdir(srcPath);
|
|
108
104
|
|
|
109
105
|
let currentElectron: cpx.SpawnProcess | null = null;
|
|
110
106
|
let isRestarting = false;
|
|
@@ -112,9 +108,10 @@ export class Electron {
|
|
|
112
108
|
|
|
113
109
|
const spawnElectron = () => {
|
|
114
110
|
Electron._logger.debug("Electron 프로세스 시작");
|
|
115
|
-
currentElectron = cpx.spawn(
|
|
116
|
-
cwd:
|
|
111
|
+
currentElectron = cpx.spawn("pnpm", ["exec", "electron", "."], {
|
|
112
|
+
cwd: this._srcPath,
|
|
117
113
|
stdio: "inherit",
|
|
114
|
+
shell: true,
|
|
118
115
|
reject: false,
|
|
119
116
|
});
|
|
120
117
|
|
|
@@ -132,7 +129,7 @@ export class Electron {
|
|
|
132
129
|
Electron._logger.debug("esbuild context 생성 시작");
|
|
133
130
|
const ctx = await esbuild.context({
|
|
134
131
|
entryPoints: [entryPoint],
|
|
135
|
-
outfile: pathx.posixResolve(
|
|
132
|
+
outfile: pathx.posixResolve(this._srcPath, "electron-main.js"),
|
|
136
133
|
platform: "node",
|
|
137
134
|
target: "node20",
|
|
138
135
|
format: "cjs",
|
|
@@ -205,18 +202,19 @@ export class Electron {
|
|
|
205
202
|
|
|
206
203
|
async build(outPath: string): Promise<void> {
|
|
207
204
|
Electron._logger.debug("build 시작");
|
|
208
|
-
|
|
205
|
+
|
|
206
|
+
await this.initialize();
|
|
209
207
|
|
|
210
208
|
Electron._logger.debug("메인 프로세스 번들링 시작");
|
|
211
|
-
await this._bundleMainProcess(
|
|
209
|
+
await this._bundleMainProcess();
|
|
212
210
|
Electron._logger.debug("메인 프로세스 번들링 완료");
|
|
213
211
|
|
|
214
212
|
Electron._logger.debug("웹 에셋 복사 시작");
|
|
215
|
-
await this._copyWebAssets(outPath
|
|
213
|
+
await this._copyWebAssets(outPath);
|
|
216
214
|
Electron._logger.debug("웹 에셋 복사 완료");
|
|
217
215
|
|
|
218
216
|
Electron._logger.debug("electron-builder 실행 시작");
|
|
219
|
-
await this._runElectronBuilder(
|
|
217
|
+
await this._runElectronBuilder();
|
|
220
218
|
Electron._logger.debug("electron-builder 실행 완료");
|
|
221
219
|
|
|
222
220
|
Electron._logger.debug("빌드 산출물 복사 시작");
|
|
@@ -230,14 +228,19 @@ export class Electron {
|
|
|
230
228
|
|
|
231
229
|
//#region Private - Initialization
|
|
232
230
|
|
|
233
|
-
private async
|
|
234
|
-
await fsx.mkdir(
|
|
231
|
+
private async _setupNpmConf(): Promise<void> {
|
|
232
|
+
await fsx.mkdir(this._srcPath);
|
|
233
|
+
|
|
234
|
+
const mainDeps: Record<string, string | undefined> = {
|
|
235
|
+
...this._npmConfig.dependencies,
|
|
236
|
+
...this._npmConfig.devDependencies,
|
|
237
|
+
};
|
|
235
238
|
|
|
236
239
|
const reinstallDeps = this._config.reinstallDependencies ?? [];
|
|
237
240
|
|
|
238
241
|
const dependencies: Record<string, string> = {};
|
|
239
242
|
for (const dep of reinstallDeps) {
|
|
240
|
-
const version =
|
|
243
|
+
const version = mainDeps[dep];
|
|
241
244
|
if (version != null) {
|
|
242
245
|
dependencies[dep] = version;
|
|
243
246
|
}
|
|
@@ -245,33 +248,39 @@ export class Electron {
|
|
|
245
248
|
|
|
246
249
|
for (const excludePkg of this._exclude) {
|
|
247
250
|
if (!(excludePkg in dependencies)) {
|
|
248
|
-
const version =
|
|
251
|
+
const version = mainDeps[excludePkg];
|
|
249
252
|
if (version != null) {
|
|
250
253
|
dependencies[excludePkg] = version;
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
}
|
|
254
257
|
|
|
258
|
+
const devDependencies: Record<string, string> = {};
|
|
259
|
+
devDependencies["electron"] = "^41";
|
|
260
|
+
devDependencies["@electron/rebuild"] = "^4";
|
|
261
|
+
devDependencies["electron-builder"] = "^26";
|
|
262
|
+
|
|
255
263
|
const packageJson: Record<string, unknown> = {
|
|
256
264
|
name: this._npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
|
|
257
265
|
version: this._npmConfig.version,
|
|
258
266
|
description: this._npmConfig.description,
|
|
259
267
|
main: "electron-main.js",
|
|
260
268
|
dependencies,
|
|
269
|
+
devDependencies,
|
|
261
270
|
};
|
|
262
271
|
|
|
263
272
|
if (this._config.postInstallScript != null) {
|
|
264
273
|
packageJson["scripts"] = { postinstall: this._config.postInstallScript };
|
|
265
274
|
}
|
|
266
275
|
|
|
267
|
-
await fsx.writeJson(pathx.posixResolve(
|
|
276
|
+
await fsx.writeJson(pathx.posixResolve(this._srcPath, "package.json"), packageJson, { space: 2 });
|
|
268
277
|
}
|
|
269
278
|
|
|
270
279
|
//#endregion
|
|
271
280
|
|
|
272
281
|
//#region Private - Bundling
|
|
273
282
|
|
|
274
|
-
private async _bundleMainProcess(
|
|
283
|
+
private async _bundleMainProcess(): Promise<void> {
|
|
275
284
|
const esbuild = await import("esbuild");
|
|
276
285
|
const entryPoint = pathx.posixResolve(this._pkgPath, "src/electron-main.ts");
|
|
277
286
|
|
|
@@ -282,14 +291,12 @@ export class Electron {
|
|
|
282
291
|
const builtinModules = module.builtinModules.flatMap((m) => [m, `node:${m}`]);
|
|
283
292
|
const reinstallDeps = this._config.reinstallDependencies ?? [];
|
|
284
293
|
|
|
285
|
-
await fsx.mkdir(outDir);
|
|
286
|
-
|
|
287
294
|
const envBanner = createEnvBanner(this._config.env);
|
|
288
295
|
|
|
289
296
|
Electron._logger.debug(`esbuild 번들링: ${entryPoint}`);
|
|
290
297
|
await esbuild.build({
|
|
291
298
|
entryPoints: [entryPoint],
|
|
292
|
-
outfile: pathx.posixResolve(
|
|
299
|
+
outfile: pathx.posixResolve(this._srcPath, "electron-main.js"),
|
|
293
300
|
platform: "node",
|
|
294
301
|
target: "node20",
|
|
295
302
|
format: "cjs",
|
|
@@ -301,15 +308,27 @@ export class Electron {
|
|
|
301
308
|
|
|
302
309
|
//#endregion
|
|
303
310
|
|
|
311
|
+
private async _copyPublicAssets(): Promise<void> {
|
|
312
|
+
const publicPath = pathx.posixResolve(this._pkgPath, "public");
|
|
313
|
+
if (!(await fsx.exists(publicPath))) return;
|
|
314
|
+
|
|
315
|
+
const items = await fsx.readdir(publicPath);
|
|
316
|
+
for (const item of items) {
|
|
317
|
+
const source = pathx.posixResolve(publicPath, item);
|
|
318
|
+
const dest = pathx.posixResolve(this._srcPath, item);
|
|
319
|
+
await fsx.copy(source, dest);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
304
323
|
//#region Private - Build
|
|
305
324
|
|
|
306
|
-
private async _copyWebAssets(outPath: string
|
|
325
|
+
private async _copyWebAssets(outPath: string): Promise<void> {
|
|
307
326
|
const items = await fsx.readdir(outPath);
|
|
308
327
|
for (const item of items) {
|
|
309
328
|
if (item === "electron") continue;
|
|
310
329
|
|
|
311
330
|
const source = pathx.posixResolve(outPath, item);
|
|
312
|
-
const dest = pathx.posixResolve(
|
|
331
|
+
const dest = pathx.posixResolve(this._srcPath, item);
|
|
313
332
|
await fsx.copy(source, dest);
|
|
314
333
|
}
|
|
315
334
|
}
|
|
@@ -331,7 +350,7 @@ export class Electron {
|
|
|
331
350
|
}
|
|
332
351
|
}
|
|
333
352
|
|
|
334
|
-
private async _runElectronBuilder(
|
|
353
|
+
private async _runElectronBuilder(): Promise<void> {
|
|
335
354
|
if (!Electron._canCreateSymlink()) {
|
|
336
355
|
throw new Error(
|
|
337
356
|
"Symlink 생성 권한이 필요합니다. Windows 개발자 모드를 활성화하세요.",
|
|
@@ -349,7 +368,7 @@ export class Electron {
|
|
|
349
368
|
},
|
|
350
369
|
nsis: this._config.nsisOptions ?? {},
|
|
351
370
|
directories: {
|
|
352
|
-
app:
|
|
371
|
+
app: this._srcPath,
|
|
353
372
|
output: distPath,
|
|
354
373
|
},
|
|
355
374
|
removePackageScripts: false,
|
|
@@ -366,9 +385,9 @@ export class Electron {
|
|
|
366
385
|
|
|
367
386
|
Electron._logger.debug(`electron-builder 설정: ${configFilePath}`);
|
|
368
387
|
await this._exec(
|
|
369
|
-
|
|
370
|
-
["--win", "--config", configFilePath],
|
|
371
|
-
this.
|
|
388
|
+
"pnpm",
|
|
389
|
+
["exec", "electron-builder", "--win", "--config", configFilePath],
|
|
390
|
+
this._srcPath,
|
|
372
391
|
);
|
|
373
392
|
}
|
|
374
393
|
|
|
@@ -112,7 +112,7 @@ export abstract class BaseEngine<
|
|
|
112
112
|
logger.debug(`[${this._pkg.name}] run 시작 (js: ${output.js}, dts: ${output.dts}, env: ${output.env ?? "none"})`);
|
|
113
113
|
this._createWorker();
|
|
114
114
|
const result = await this._callBuild(output);
|
|
115
|
-
logger.debug(`[${this._pkg.name}] run 완료 (success: ${result.success})`);
|
|
115
|
+
logger.debug(`[${this._pkg.name}] run 완료 (success: ${result.build.success})`);
|
|
116
116
|
return result;
|
|
117
117
|
}
|
|
118
118
|
|
package/src/engines/TscEngine.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "path";
|
|
1
3
|
import { Worker, type WorkerProxy } from "@simplysm/core-node";
|
|
2
4
|
import { consola } from "consola";
|
|
3
5
|
import type * as ClientWorkerModule from "../workers/client.worker";
|
|
@@ -81,7 +83,6 @@ export class ViteEngine implements BuildEngine {
|
|
|
81
83
|
|
|
82
84
|
logger.debug(`[${this._pkg.name}] ViteEngine.run 완료 (success: ${result.success})`);
|
|
83
85
|
return {
|
|
84
|
-
success: result.success,
|
|
85
86
|
build: {
|
|
86
87
|
success: result.success,
|
|
87
88
|
errors: result.errors ?? [],
|
|
@@ -196,6 +197,11 @@ export class ViteEngine implements BuildEngine {
|
|
|
196
197
|
*/
|
|
197
198
|
async stop(): Promise<void> {
|
|
198
199
|
logger.debug(`[${this._pkg.name}] ViteEngine stop 시작`);
|
|
200
|
+
|
|
201
|
+
// .dev-port 파일 삭제
|
|
202
|
+
const portFile = path.join(this._pkg.dir, "dist", ".dev-port");
|
|
203
|
+
try { fs.unlinkSync(portFile); } catch { /* 파일 없으면 무시 */ }
|
|
204
|
+
|
|
199
205
|
await stopEngineWorker(this._worker, this._isWatchMode);
|
|
200
206
|
this._worker = undefined;
|
|
201
207
|
logger.debug(`[${this._pkg.name}] ViteEngine stop 완료`);
|
package/src/engines/index.ts
CHANGED
|
@@ -10,16 +10,6 @@ import type { BuildEngine, BuildPackageInfo, ClientPackageInfo, ServerPackageInf
|
|
|
10
10
|
|
|
11
11
|
const logger = consola.withTag("sd:cli:engine");
|
|
12
12
|
|
|
13
|
-
export { BaseEngine } from "./BaseEngine";
|
|
14
|
-
export type { BaseEngineOptions, CommonBuildWorkerEvents, CommonBuildWorkerModule } from "./BaseEngine";
|
|
15
|
-
export { NgtscEngine } from "./NgtscEngine";
|
|
16
|
-
export type { NgtscEngineOptions } from "./NgtscEngine";
|
|
17
|
-
export { ServerEsbuildEngine } from "./ServerEsbuildEngine";
|
|
18
|
-
export type { ServerEsbuildEngineOptions } from "./ServerEsbuildEngine";
|
|
19
|
-
export { TscEngine } from "./TscEngine";
|
|
20
|
-
export type { TscEngineOptions } from "./TscEngine";
|
|
21
|
-
export { ViteEngine } from "./ViteEngine";
|
|
22
|
-
export type { ViteEngineOptions } from "./ViteEngine";
|
|
23
13
|
export type { BuildEngine, BuildOutput, BuildPackageInfo, ClientPackageInfo, EngineResult, PackageInfo, ServerPackageInfo } from "./types";
|
|
24
14
|
|
|
25
15
|
/**
|
package/src/engines/types.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
export class SignalHandler {
|
|
8
8
|
private _terminateResolver: (() => void) | null = null;
|
|
9
9
|
private readonly _terminatePromise: Promise<void>;
|
|
10
|
-
private _terminated = false;
|
|
11
10
|
|
|
12
11
|
constructor() {
|
|
13
12
|
this._terminatePromise = new Promise((resolve) => {
|
|
@@ -17,8 +16,8 @@ export class SignalHandler {
|
|
|
17
16
|
const handler = () => {
|
|
18
17
|
process.off("SIGINT", handler);
|
|
19
18
|
process.off("SIGTERM", handler);
|
|
20
|
-
this._terminated = true;
|
|
21
19
|
this._terminateResolver?.();
|
|
20
|
+
this._terminateResolver = null;
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
process.on("SIGINT", handler);
|
|
@@ -32,21 +31,12 @@ export class SignalHandler {
|
|
|
32
31
|
return this._terminatePromise;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
/**
|
|
36
|
-
* 종료 여부를 확인한다
|
|
37
|
-
*/
|
|
38
|
-
isTerminated(): boolean {
|
|
39
|
-
return this._terminated;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
34
|
/**
|
|
43
35
|
* 프로그래밍 방식으로 종료를 요청한다
|
|
44
|
-
* (
|
|
36
|
+
* (테스트에서 종료를 트리거할 때 사용)
|
|
45
37
|
*/
|
|
46
38
|
requestTermination(): void {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this._terminateResolver?.();
|
|
50
|
-
}
|
|
39
|
+
this._terminateResolver?.();
|
|
40
|
+
this._terminateResolver = null;
|
|
51
41
|
}
|
|
52
42
|
}
|
|
@@ -200,8 +200,8 @@ export class BuildOrchestrator {
|
|
|
200
200
|
|
|
201
201
|
// 결과 수집
|
|
202
202
|
const results: BuildStepResult[] = [];
|
|
203
|
-
// 에러 추적 (
|
|
204
|
-
|
|
203
|
+
// results에 포함되지 않는 에러 추적 (네이티브 빌드 실패, rejected 태스크 등)
|
|
204
|
+
let hasUntrackedError = false;
|
|
205
205
|
|
|
206
206
|
// 파일 캐시 (진단 출력용)
|
|
207
207
|
const fileCache = new Map<string, string>();
|
|
@@ -249,7 +249,6 @@ export class BuildOrchestrator {
|
|
|
249
249
|
warnings: engineResult.build.warnings.length > 0 ? engineResult.build.warnings : undefined,
|
|
250
250
|
diagnostics,
|
|
251
251
|
});
|
|
252
|
-
if (!engineResult.build.success) state.hasError = true;
|
|
253
252
|
|
|
254
253
|
} finally {
|
|
255
254
|
await engine.stop();
|
|
@@ -289,7 +288,6 @@ export class BuildOrchestrator {
|
|
|
289
288
|
warnings: engineResult.build.warnings.length > 0 ? engineResult.build.warnings : undefined,
|
|
290
289
|
diagnostics,
|
|
291
290
|
});
|
|
292
|
-
if (!engineResult.build.success) state.hasError = true;
|
|
293
291
|
|
|
294
292
|
} finally {
|
|
295
293
|
await engine.stop();
|
|
@@ -327,7 +325,6 @@ export class BuildOrchestrator {
|
|
|
327
325
|
warnings: engineResult.build.warnings.length > 0 ? engineResult.build.warnings : undefined,
|
|
328
326
|
diagnostics,
|
|
329
327
|
});
|
|
330
|
-
if (!engineResult.build.success) state.hasError = true;
|
|
331
328
|
|
|
332
329
|
// 네이티브 빌드 (빌드 성공 시에만 실행)
|
|
333
330
|
if (engineResult.build.success) {
|
|
@@ -362,7 +359,7 @@ export class BuildOrchestrator {
|
|
|
362
359
|
const nativeResults = await Promise.allSettled(nativeBuildPromises);
|
|
363
360
|
for (const nativeResult of nativeResults) {
|
|
364
361
|
if (nativeResult.status === "rejected") {
|
|
365
|
-
|
|
362
|
+
hasUntrackedError = true;
|
|
366
363
|
const err = nativeResult.reason;
|
|
367
364
|
this._logger.error(
|
|
368
365
|
`[${name}] 네이티브 빌드 실패: ${err instanceof Error ? err.message : String(err)}`,
|
|
@@ -391,7 +388,7 @@ export class BuildOrchestrator {
|
|
|
391
388
|
if (stack != null) {
|
|
392
389
|
this._logger.debug(`빌드 예외 스택:\n${stack}`);
|
|
393
390
|
}
|
|
394
|
-
|
|
391
|
+
hasUntrackedError = true;
|
|
395
392
|
}
|
|
396
393
|
}
|
|
397
394
|
this._logger.success("빌드 실행 완료");
|
|
@@ -429,13 +426,14 @@ export class BuildOrchestrator {
|
|
|
429
426
|
// 최종 결과 로그
|
|
430
427
|
const errorCount = results.filter((r) => !r.success).length;
|
|
431
428
|
const warningCount = results.filter((r) => r.warnings != null).length;
|
|
432
|
-
|
|
429
|
+
const hasError = errorCount > 0 || hasUntrackedError;
|
|
430
|
+
if (hasError) {
|
|
433
431
|
this._logger.error("빌드 에러 발생", { errorCount, warningCount });
|
|
434
432
|
} else {
|
|
435
433
|
this._logger.info("빌드 완료", { errorCount, warningCount });
|
|
436
434
|
}
|
|
437
435
|
|
|
438
|
-
return
|
|
436
|
+
return hasError;
|
|
439
437
|
}
|
|
440
438
|
|
|
441
439
|
/**
|
|
@@ -156,15 +156,11 @@ export class DevWatchOrchestrator {
|
|
|
156
156
|
this._resultCollector = new ResultCollector();
|
|
157
157
|
this._rebuildManager = new RebuildManager(this._logger);
|
|
158
158
|
|
|
159
|
-
// 배치 완료 핸들러
|
|
159
|
+
// 배치 완료 핸들러 (watch 모드만 여기서 등록, dev 모드는 _startDevMode() 끝에서 등록)
|
|
160
160
|
if (this._options.mode === "watch") {
|
|
161
161
|
this._rebuildManager.on("batchComplete", (_completedKeys) => {
|
|
162
162
|
printErrors(this._resultCollector.toMap());
|
|
163
163
|
});
|
|
164
|
-
} else {
|
|
165
|
-
this._rebuildManager.on("batchComplete", (completedKeys) => {
|
|
166
|
-
this._onDevBatchComplete(completedKeys);
|
|
167
|
-
});
|
|
168
164
|
}
|
|
169
165
|
|
|
170
166
|
// 라이브러리 패키지용 BuildEngine 생성 (watch 모드 전용)
|
|
@@ -418,9 +414,26 @@ export class DevWatchOrchestrator {
|
|
|
418
414
|
}
|
|
419
415
|
}
|
|
420
416
|
|
|
421
|
-
//
|
|
422
|
-
|
|
423
|
-
|
|
417
|
+
// 모든 엔진 준비 완료 후 서버 런타임 시작 (클라이언트 포트 확보 보장)
|
|
418
|
+
await this._restartServers();
|
|
419
|
+
|
|
420
|
+
// 독립 클라이언트만 존재하고 서버가 없는 경우 URL 출력 예약
|
|
421
|
+
if (this._serverPackages.length === 0) {
|
|
422
|
+
const hasIndependentClients = this._clientPackages.some(({ name }) => {
|
|
423
|
+
const isServerConnected = [...this._serverClientsMap.values()].some(
|
|
424
|
+
(clients) => clients.includes(name),
|
|
425
|
+
);
|
|
426
|
+
return !isServerConnected && this._getClientPort(name) != null;
|
|
427
|
+
});
|
|
428
|
+
if (hasIndependentClients) {
|
|
429
|
+
this._schedulePrintServers();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// dev 모드 배치 완료 핸들러 등록 (이후 watch 이벤트용)
|
|
434
|
+
this._rebuildManager.on("batchComplete", (completedKeys) => {
|
|
435
|
+
this._onDevBatchComplete(completedKeys);
|
|
436
|
+
});
|
|
424
437
|
}
|
|
425
438
|
|
|
426
439
|
private _onDevBatchComplete(completedKeys: string[]): void {
|
|
@@ -464,7 +477,6 @@ export class DevWatchOrchestrator {
|
|
|
464
477
|
await Promise.all(restartPromises);
|
|
465
478
|
this._logger.debug("서버 재시작 완료");
|
|
466
479
|
printErrors(this._resultCollector.toMap());
|
|
467
|
-
this._schedulePrintServers();
|
|
468
480
|
}
|
|
469
481
|
|
|
470
482
|
private _schedulePrintServers(): void {
|
package/src/sd-cli-entry.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/* eslint-disable no-console */
|
|
3
3
|
|
|
4
4
|
// 사이드 이펙트: Map/Array prototype 확장 (getOrCreate 등)
|
|
5
|
-
import "@simplysm/core-common";
|
|
5
|
+
import { env } from "@simplysm/core-common";
|
|
6
6
|
import yargs, { type Argv } from "yargs";
|
|
7
7
|
import { hideBin } from "yargs/helpers";
|
|
8
|
-
import {
|
|
8
|
+
import { type CheckType, runCheck } from "./commands/check";
|
|
9
9
|
import { runWatch } from "./commands/watch";
|
|
10
10
|
import { runDev } from "./commands/dev";
|
|
11
11
|
import { runBuild } from "./commands/build";
|
|
@@ -15,14 +15,12 @@ import path from "path";
|
|
|
15
15
|
import fs from "fs";
|
|
16
16
|
import { fileURLToPath } from "url";
|
|
17
17
|
import { EventEmitter } from "node:events";
|
|
18
|
-
import { consola
|
|
19
|
-
import {
|
|
18
|
+
import { consola } from "consola";
|
|
19
|
+
import { setupConsola } from "@simplysm/core-node";
|
|
20
20
|
|
|
21
21
|
Error.stackTraceLimit = Infinity;
|
|
22
22
|
EventEmitter.defaultMaxListeners = 100;
|
|
23
23
|
|
|
24
|
-
consola.options.reporters = [new SdCliReporter()];
|
|
25
|
-
|
|
26
24
|
const COMMAND_NAMES = ["check", "watch", "dev", "device", "build", "publish", "replace-deps"];
|
|
27
25
|
|
|
28
26
|
async function collectYargsHelp(argv: string[]): Promise<string> {
|
|
@@ -36,7 +34,6 @@ async function collectYargsHelp(argv: string[]): Promise<string> {
|
|
|
36
34
|
} catch {
|
|
37
35
|
// yargs가 help 출력 후 throw할 수 있음
|
|
38
36
|
} finally {
|
|
39
|
-
|
|
40
37
|
console.log = orig;
|
|
41
38
|
}
|
|
42
39
|
return lines.join("\n");
|
|
@@ -58,9 +55,9 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
58
55
|
async () => {
|
|
59
56
|
for (const cmdName of COMMAND_NAMES) {
|
|
60
57
|
const helpText = await collectYargsHelp([cmdName, "--help"]);
|
|
61
|
-
|
|
58
|
+
|
|
62
59
|
console.log(helpText);
|
|
63
|
-
|
|
60
|
+
|
|
64
61
|
console.log();
|
|
65
62
|
}
|
|
66
63
|
},
|
|
@@ -78,9 +75,9 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
78
75
|
})
|
|
79
76
|
.middleware((args) => {
|
|
80
77
|
if (args.debug) {
|
|
81
|
-
|
|
82
|
-
process.env["SD_DEBUG"] = "true";
|
|
78
|
+
env("SD_DEBUG", "true");
|
|
83
79
|
}
|
|
80
|
+
setupConsola({ cli: true });
|
|
84
81
|
})
|
|
85
82
|
.command(
|
|
86
83
|
"check [targets..]",
|
|
@@ -113,9 +110,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
113
110
|
types: (() => {
|
|
114
111
|
const validTypes = ["typecheck", "lint", "test"] as const;
|
|
115
112
|
const types = args.type.split(",").map((t) => t.trim());
|
|
116
|
-
const invalidTypes = types.filter(
|
|
117
|
-
(t) => !validTypes.includes(t as CheckType),
|
|
118
|
-
);
|
|
113
|
+
const invalidTypes = types.filter((t) => !validTypes.includes(t as CheckType));
|
|
119
114
|
if (invalidTypes.length > 0) {
|
|
120
115
|
throw new Error(
|
|
121
116
|
`Invalid check type(s): ${invalidTypes.join(", ")}. Valid types: ${validTypes.join(", ")}`,
|
|
@@ -197,11 +192,11 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
197
192
|
describe: "Client package to run (e.g., my-client-app)",
|
|
198
193
|
})
|
|
199
194
|
.options({
|
|
200
|
-
|
|
195
|
+
url: {
|
|
201
196
|
type: "string",
|
|
202
197
|
description: "Dev server URL (auto-detected from sd.config.ts if omitted)",
|
|
203
198
|
},
|
|
204
|
-
|
|
199
|
+
opt: {
|
|
205
200
|
type: "string",
|
|
206
201
|
array: true,
|
|
207
202
|
alias: "o",
|
package/src/sd-config.types.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/** npm package.json 구조 */
|
|
2
|
+
export interface NpmConfig {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
dependencies?: Record<string, string>;
|
|
7
|
+
devDependencies?: Record<string, string>;
|
|
8
|
+
peerDependencies?: Record<string, string>;
|
|
9
|
+
volta?: unknown;
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
/**
|
|
2
13
|
* 빌드 타겟 타입 (esbuild로 빌드)
|
|
3
14
|
* - node: Node.js 전용 패키지
|
|
@@ -169,7 +180,7 @@ export interface SdElectronConfig {
|
|
|
169
180
|
//#region PWA 설정 타입
|
|
170
181
|
|
|
171
182
|
/**
|
|
172
|
-
* PWA manifest 설정
|
|
183
|
+
* PWA manifest 설정
|
|
173
184
|
*/
|
|
174
185
|
export interface SdPwaManifestConfig {
|
|
175
186
|
name?: string;
|