@simplysm/sd-cli 14.0.5 → 14.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +10 -10
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +1 -4
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/replace-deps.js +1 -1
- package/dist/commands/replace-deps.js.map +1 -1
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +5 -6
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +1 -0
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +52 -45
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.js +32 -26
- package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
- package/dist/sd-cli.js +1 -1
- package/dist/sd-cli.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts +7 -2
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +15 -12
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/output-utils.js +1 -1
- package/dist/utils/output-utils.js.map +1 -1
- package/dist/utils/package-utils.js +3 -3
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/rebuild-manager.js +3 -3
- package/dist/utils/rebuild-manager.js.map +1 -1
- package/dist/utils/replace-deps.js +11 -11
- package/dist/utils/replace-deps.js.map +1 -1
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +1 -2
- package/dist/utils/vite-config.js.map +1 -1
- package/dist/utils/worker-utils.js +1 -1
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/workers/server-build.worker.js +2 -2
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.js +13 -13
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/package.json +4 -5
- package/src/commands/check.ts +12 -11
- package/src/commands/lint.ts +1 -3
- package/src/commands/replace-deps.ts +1 -1
- package/src/electron/electron.ts +7 -7
- package/src/engines/BaseEngine.ts +1 -0
- package/src/index.ts +3 -0
- package/src/orchestrators/BuildOrchestrator.ts +52 -45
- package/src/orchestrators/DevWatchOrchestrator.ts +33 -26
- package/src/sd-cli.ts +1 -1
- package/src/utils/esbuild-config.ts +16 -12
- package/src/utils/output-utils.ts +1 -1
- package/src/utils/package-utils.ts +3 -3
- package/src/utils/rebuild-manager.ts +3 -3
- package/src/utils/replace-deps.ts +11 -11
- package/src/utils/vite-config.ts +1 -2
- package/src/utils/worker-utils.ts +1 -1
- package/src/workers/server-build.worker.ts +2 -2
- package/src/workers/server-runtime.worker.ts +13 -13
- package/tests/commands/check.spec.ts +11 -26
- package/tests/electron/electron.spec.ts +42 -35
- package/tests/orchestrators/build-orchestrator.spec.ts +4 -9
- package/tests/orchestrators/dev-watch-orchestrator.spec.ts +3 -5
- package/tests/utils/esbuild-config.spec.ts +38 -8
- package/tests/utils/vite-config.spec.ts +13 -0
|
@@ -141,9 +141,9 @@ export class BuildOrchestrator {
|
|
|
141
141
|
* - Prepare environment variables
|
|
142
142
|
*/
|
|
143
143
|
async initialize(): Promise<void> {
|
|
144
|
-
this._logger.debug("
|
|
144
|
+
this._logger.debug("빌드 시작", { targets: this._options.targets });
|
|
145
145
|
|
|
146
|
-
//
|
|
146
|
+
// sd.config.ts 로드 및 대상 유효성 검사
|
|
147
147
|
try {
|
|
148
148
|
this._sdConfig = await loadAndValidateConfig({
|
|
149
149
|
cwd: this._cwd,
|
|
@@ -151,18 +151,19 @@ export class BuildOrchestrator {
|
|
|
151
151
|
options: this._options.options,
|
|
152
152
|
targets: this._options.targets,
|
|
153
153
|
});
|
|
154
|
-
this._logger.debug("sd.config.ts
|
|
154
|
+
this._logger.debug("sd.config.ts 로드 완료");
|
|
155
155
|
} catch (err) {
|
|
156
|
-
this._logger.error(`sd.config.ts
|
|
156
|
+
this._logger.error(`sd.config.ts 로드 실패: ${err instanceof Error ? err.message : err}`);
|
|
157
157
|
process.exitCode = 1;
|
|
158
158
|
throw err;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
//
|
|
161
|
+
// 환경변수 준비 (VER, DEV)
|
|
162
162
|
const version = await getVersion(this._cwd);
|
|
163
163
|
this._baseEnv = { VER: version, DEV: "false" };
|
|
164
|
+
this._logger.debug("환경변수 준비 완료", { VER: version, DEV: "false" });
|
|
164
165
|
|
|
165
|
-
//
|
|
166
|
+
// 패키지 분류
|
|
166
167
|
this._classified = classifyPackages(this._sdConfig.packages, this._options.targets);
|
|
167
168
|
this._allPackageNames = [
|
|
168
169
|
...this._classified.buildPackages.map((p) => p.name),
|
|
@@ -171,12 +172,12 @@ export class BuildOrchestrator {
|
|
|
171
172
|
];
|
|
172
173
|
|
|
173
174
|
if (this._allPackageNames.length === 0) {
|
|
174
|
-
process.stdout.write("✔
|
|
175
|
+
process.stdout.write("✔ 빌드할 패키지가 없습니다.\n");
|
|
175
176
|
return;
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
this._logger.debug("
|
|
179
|
-
buildPackages: this._classified.buildPackages.map((p) => p.name),
|
|
179
|
+
this._logger.debug("패키지 분류 완료", {
|
|
180
|
+
buildPackages: this._classified.buildPackages.map((p) => `${p.name} (${p.config.target})`),
|
|
180
181
|
serverPackages: this._classified.serverPackages.map((p) => p.name),
|
|
181
182
|
clientPackages: this._classified.clientPackages.map((p) => p.name),
|
|
182
183
|
});
|
|
@@ -213,13 +214,13 @@ export class BuildOrchestrator {
|
|
|
213
214
|
getNewLine: () => ts.sys.newLine,
|
|
214
215
|
};
|
|
215
216
|
|
|
216
|
-
// Phase 1:
|
|
217
|
-
this._logger.start(
|
|
217
|
+
// Phase 1: dist 클린
|
|
218
|
+
this._logger.start(`dist 폴더 정리 중... (${this._allPackageNames.length}개 패키지)`);
|
|
218
219
|
await cleanDistFolders(this._cwd, this._allPackageNames);
|
|
219
|
-
this._logger.success("
|
|
220
|
+
this._logger.success("dist 폴더 정리 완료");
|
|
220
221
|
|
|
221
|
-
// Phase 2:
|
|
222
|
-
|
|
222
|
+
// Phase 2: 빌드
|
|
223
|
+
const concurrency = getMaxConcurrency();
|
|
223
224
|
|
|
224
225
|
// Create list of build tasks
|
|
225
226
|
const buildTasks: Array<() => Promise<void>> = [];
|
|
@@ -229,7 +230,7 @@ export class BuildOrchestrator {
|
|
|
229
230
|
const pkgDir = path.join(this._cwd, "packages", name);
|
|
230
231
|
|
|
231
232
|
buildTasks.push(async () => {
|
|
232
|
-
this._logger.debug(
|
|
233
|
+
this._logger.debug(`[${name}] (${config.target}) 빌드 시작`);
|
|
233
234
|
const engine = createBuildEngine(
|
|
234
235
|
{ name, dir: pkgDir, config },
|
|
235
236
|
{ cwd: this._cwd },
|
|
@@ -238,7 +239,7 @@ export class BuildOrchestrator {
|
|
|
238
239
|
try {
|
|
239
240
|
const engineResult = await engine.run({ js: true, dts: true, lint: true });
|
|
240
241
|
|
|
241
|
-
//
|
|
242
|
+
// JS 빌드 결과 처리
|
|
242
243
|
results.push({
|
|
243
244
|
name,
|
|
244
245
|
target: config.target,
|
|
@@ -249,7 +250,7 @@ export class BuildOrchestrator {
|
|
|
249
250
|
});
|
|
250
251
|
if (!engineResult.js.success) state.hasError = true;
|
|
251
252
|
|
|
252
|
-
//
|
|
253
|
+
// DTS 결과 처리
|
|
253
254
|
const diagnostics = engineResult.dts.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
|
|
254
255
|
results.push({
|
|
255
256
|
name,
|
|
@@ -261,7 +262,7 @@ export class BuildOrchestrator {
|
|
|
261
262
|
});
|
|
262
263
|
if (!engineResult.dts.success) state.hasError = true;
|
|
263
264
|
|
|
264
|
-
//
|
|
265
|
+
// 린트 결과 처리
|
|
265
266
|
if (engineResult.lint != null) {
|
|
266
267
|
results.push({
|
|
267
268
|
name,
|
|
@@ -277,11 +278,12 @@ export class BuildOrchestrator {
|
|
|
277
278
|
await engine.stop();
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
//
|
|
281
|
+
// copySrc 파일 복사
|
|
281
282
|
if (config.copySrc != null && config.copySrc.length > 0) {
|
|
283
|
+
this._logger.debug(`[${name}] copySrc 파일 복사 중 (${config.copySrc.length}개)`);
|
|
282
284
|
await copySrcFiles(pkgDir, config.copySrc);
|
|
283
285
|
}
|
|
284
|
-
this._logger.debug(
|
|
286
|
+
this._logger.debug(`[${name}] (${config.target}) 빌드 완료`);
|
|
285
287
|
});
|
|
286
288
|
}
|
|
287
289
|
|
|
@@ -290,7 +292,7 @@ export class BuildOrchestrator {
|
|
|
290
292
|
const pkgDir = path.join(this._cwd, "packages", name);
|
|
291
293
|
|
|
292
294
|
buildTasks.push(async () => {
|
|
293
|
-
this._logger.debug(
|
|
295
|
+
this._logger.debug(`[${name}] (server) 빌드 시작`);
|
|
294
296
|
const engine = createBuildEngine(
|
|
295
297
|
{ name, dir: pkgDir, config: { ...config, env: { ...baseEnv, ...config.env } } },
|
|
296
298
|
{ cwd: this._cwd },
|
|
@@ -299,7 +301,7 @@ export class BuildOrchestrator {
|
|
|
299
301
|
try {
|
|
300
302
|
const engineResult = await engine.run({ js: true, dts: false, lint: true });
|
|
301
303
|
|
|
302
|
-
//
|
|
304
|
+
// JS 빌드 결과 처리
|
|
303
305
|
results.push({
|
|
304
306
|
name,
|
|
305
307
|
target: "server",
|
|
@@ -310,7 +312,7 @@ export class BuildOrchestrator {
|
|
|
310
312
|
});
|
|
311
313
|
if (!engineResult.js.success) state.hasError = true;
|
|
312
314
|
|
|
313
|
-
//
|
|
315
|
+
// DTS/타입체크 결과 처리
|
|
314
316
|
const diagnostics = engineResult.dts.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
|
|
315
317
|
results.push({
|
|
316
318
|
name,
|
|
@@ -322,7 +324,7 @@ export class BuildOrchestrator {
|
|
|
322
324
|
});
|
|
323
325
|
if (!engineResult.dts.success) state.hasError = true;
|
|
324
326
|
|
|
325
|
-
//
|
|
327
|
+
// 린트 결과 처리
|
|
326
328
|
if (engineResult.lint != null) {
|
|
327
329
|
results.push({
|
|
328
330
|
name,
|
|
@@ -337,7 +339,7 @@ export class BuildOrchestrator {
|
|
|
337
339
|
} finally {
|
|
338
340
|
await engine.stop();
|
|
339
341
|
}
|
|
340
|
-
this._logger.debug(
|
|
342
|
+
this._logger.debug(`[${name}] (server) 빌드 완료`);
|
|
341
343
|
});
|
|
342
344
|
}
|
|
343
345
|
|
|
@@ -346,7 +348,7 @@ export class BuildOrchestrator {
|
|
|
346
348
|
const pkgDir = path.join(this._cwd, "packages", name);
|
|
347
349
|
|
|
348
350
|
buildTasks.push(async () => {
|
|
349
|
-
this._logger.debug(
|
|
351
|
+
this._logger.debug(`[${name}] (client) 빌드 시작`);
|
|
350
352
|
const engine = createBuildEngine(
|
|
351
353
|
{ name, dir: pkgDir, config: { ...config, env: { ...baseEnv, ...config.env } } },
|
|
352
354
|
{ cwd: this._cwd },
|
|
@@ -355,7 +357,7 @@ export class BuildOrchestrator {
|
|
|
355
357
|
try {
|
|
356
358
|
const engineResult = await engine.run({ js: true, dts: false, lint: true });
|
|
357
359
|
|
|
358
|
-
//
|
|
360
|
+
// JS 빌드 결과 처리
|
|
359
361
|
results.push({
|
|
360
362
|
name,
|
|
361
363
|
target: "client",
|
|
@@ -366,7 +368,7 @@ export class BuildOrchestrator {
|
|
|
366
368
|
});
|
|
367
369
|
if (!engineResult.js.success) state.hasError = true;
|
|
368
370
|
|
|
369
|
-
//
|
|
371
|
+
// DTS 결과 처리
|
|
370
372
|
const diagnostics = engineResult.dts.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
|
|
371
373
|
results.push({
|
|
372
374
|
name,
|
|
@@ -378,7 +380,7 @@ export class BuildOrchestrator {
|
|
|
378
380
|
});
|
|
379
381
|
if (!engineResult.dts.success) state.hasError = true;
|
|
380
382
|
|
|
381
|
-
//
|
|
383
|
+
// 린트 결과 처리
|
|
382
384
|
if (engineResult.lint != null) {
|
|
383
385
|
results.push({
|
|
384
386
|
name,
|
|
@@ -390,27 +392,31 @@ export class BuildOrchestrator {
|
|
|
390
392
|
if (!engineResult.lint.success) state.hasError = true;
|
|
391
393
|
}
|
|
392
394
|
|
|
393
|
-
//
|
|
395
|
+
// 네이티브 빌드 (JS 빌드 성공 시에만 실행)
|
|
394
396
|
if (engineResult.js.success) {
|
|
395
397
|
const distPath = path.join(pkgDir, "dist");
|
|
396
398
|
const nativeBuildPromises: Array<Promise<void>> = [];
|
|
397
399
|
|
|
398
400
|
if (config.capacitor != null) {
|
|
401
|
+
this._logger.debug(`[${name}] Capacitor 네이티브 빌드 시작`);
|
|
399
402
|
nativeBuildPromises.push(
|
|
400
403
|
(async () => {
|
|
401
404
|
const cap = await Capacitor.create(pkgDir, config.capacitor!, config.exclude);
|
|
402
405
|
await cap.initialize();
|
|
403
406
|
await cap.build(distPath);
|
|
407
|
+
this._logger.debug(`[${name}] Capacitor 네이티브 빌드 완료`);
|
|
404
408
|
})(),
|
|
405
409
|
);
|
|
406
410
|
}
|
|
407
411
|
|
|
408
412
|
if (config.electron != null) {
|
|
413
|
+
this._logger.debug(`[${name}] Electron 네이티브 빌드 시작`);
|
|
409
414
|
nativeBuildPromises.push(
|
|
410
415
|
(async () => {
|
|
411
416
|
const elc = await Electron.create(pkgDir, config.electron!, config.exclude);
|
|
412
417
|
await elc.initialize();
|
|
413
418
|
await elc.build(distPath);
|
|
419
|
+
this._logger.debug(`[${name}] Electron 네이티브 빌드 완료`);
|
|
414
420
|
})(),
|
|
415
421
|
);
|
|
416
422
|
}
|
|
@@ -422,7 +428,7 @@ export class BuildOrchestrator {
|
|
|
422
428
|
state.hasError = true;
|
|
423
429
|
const err = nativeResult.reason;
|
|
424
430
|
this._logger.error(
|
|
425
|
-
|
|
431
|
+
`[${name}] 네이티브 빌드 실패: ${err instanceof Error ? err.message : String(err)}`,
|
|
426
432
|
);
|
|
427
433
|
}
|
|
428
434
|
}
|
|
@@ -431,19 +437,18 @@ export class BuildOrchestrator {
|
|
|
431
437
|
} finally {
|
|
432
438
|
await engine.stop();
|
|
433
439
|
}
|
|
434
|
-
this._logger.debug(
|
|
440
|
+
this._logger.debug(`[${name}] (client) 빌드 완료`);
|
|
435
441
|
});
|
|
436
442
|
}
|
|
437
443
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this._logger.debug(`빌드 실행 (${buildTasks.length}개 작업, 동시성: ${concurrency})`);
|
|
444
|
+
this._logger.start(`빌드 실행 중... (${buildTasks.length}개 작업, 동시성: ${concurrency})`);
|
|
445
|
+
this._logger.debug("빌드 작업 목록", { tasks: buildTasks.length, concurrency });
|
|
441
446
|
const buildResults = await runWithConcurrency(buildTasks, concurrency);
|
|
442
447
|
for (const settledResult of buildResults) {
|
|
443
448
|
if (settledResult.status === "rejected") {
|
|
444
449
|
const err = settledResult.reason;
|
|
445
450
|
const stack = err instanceof Error ? err.stack : undefined;
|
|
446
|
-
this._logger.error("
|
|
451
|
+
this._logger.error("빌드 중 예기치 않은 에러", {
|
|
447
452
|
error: String(err),
|
|
448
453
|
});
|
|
449
454
|
if (stack != null) {
|
|
@@ -452,24 +457,24 @@ export class BuildOrchestrator {
|
|
|
452
457
|
state.hasError = true;
|
|
453
458
|
}
|
|
454
459
|
}
|
|
455
|
-
this._logger.success("
|
|
460
|
+
this._logger.success("빌드 실행 완료");
|
|
456
461
|
|
|
457
|
-
//
|
|
462
|
+
// 결과 출력
|
|
458
463
|
const allDiagnostics: ts.Diagnostic[] = [];
|
|
459
464
|
for (const result of results) {
|
|
460
465
|
const typeLabel = result.type === "dts" ? "dts" : result.type === "lint" ? "lint" : result.target;
|
|
461
466
|
|
|
462
|
-
//
|
|
467
|
+
// 경고 출력
|
|
463
468
|
if (result.warnings != null) {
|
|
464
469
|
this._logger.warn(formatBuildMessages(result.name, typeLabel, result.warnings));
|
|
465
470
|
}
|
|
466
471
|
|
|
467
|
-
//
|
|
472
|
+
// 에러 출력
|
|
468
473
|
if (!result.success) {
|
|
469
474
|
if (result.errors != null) {
|
|
470
475
|
this._logger.error(formatBuildMessages(result.name, typeLabel, result.errors));
|
|
471
476
|
} else {
|
|
472
|
-
this._logger.error(
|
|
477
|
+
this._logger.error(`[${result.name}] (${typeLabel}) 실패`);
|
|
473
478
|
}
|
|
474
479
|
}
|
|
475
480
|
if (result.diagnostics != null) {
|
|
@@ -477,18 +482,20 @@ export class BuildOrchestrator {
|
|
|
477
482
|
}
|
|
478
483
|
}
|
|
479
484
|
|
|
480
|
-
//
|
|
485
|
+
// 진단 정보 출력 (중복 제거)
|
|
481
486
|
if (allDiagnostics.length > 0) {
|
|
482
487
|
const uniqueDiagnostics = ts.sortAndDeduplicateDiagnostics(allDiagnostics);
|
|
483
488
|
const message = ts.formatDiagnosticsWithColorAndContext(uniqueDiagnostics, formatHost);
|
|
484
489
|
process.stdout.write(message);
|
|
485
490
|
}
|
|
486
491
|
|
|
487
|
-
//
|
|
492
|
+
// 최종 결과 로그
|
|
493
|
+
const errorCount = results.filter((r) => !r.success).length;
|
|
494
|
+
const warningCount = results.filter((r) => r.warnings != null).length;
|
|
488
495
|
if (state.hasError) {
|
|
489
|
-
this._logger.error("
|
|
496
|
+
this._logger.error("빌드 에러 발생", { errorCount, warningCount });
|
|
490
497
|
} else {
|
|
491
|
-
this._logger.info("
|
|
498
|
+
this._logger.info("빌드 완료", { errorCount, warningCount });
|
|
492
499
|
}
|
|
493
500
|
|
|
494
501
|
return state.hasError;
|
|
@@ -90,9 +90,9 @@ export class DevWatchOrchestrator {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
async initialize(): Promise<void> {
|
|
93
|
-
this._logger.debug(`${this._options.mode}
|
|
93
|
+
this._logger.debug(`${this._options.mode} 시작`, { targets: this._options.targets });
|
|
94
94
|
|
|
95
|
-
//
|
|
95
|
+
// sd.config.ts 로드
|
|
96
96
|
let sdConfig: SdConfig;
|
|
97
97
|
try {
|
|
98
98
|
sdConfig = await loadSdConfig({
|
|
@@ -100,9 +100,9 @@ export class DevWatchOrchestrator {
|
|
|
100
100
|
dev: true,
|
|
101
101
|
options: this._options.options,
|
|
102
102
|
});
|
|
103
|
-
this._logger.debug("sd.config.ts
|
|
103
|
+
this._logger.debug("sd.config.ts 로드 완료");
|
|
104
104
|
} catch (err) {
|
|
105
|
-
this._logger.error(`
|
|
105
|
+
this._logger.error(`sd.config.ts 로드 실패: ${err instanceof Error ? err.message : err}`);
|
|
106
106
|
process.exitCode = 1;
|
|
107
107
|
throw err;
|
|
108
108
|
}
|
|
@@ -147,8 +147,8 @@ export class DevWatchOrchestrator {
|
|
|
147
147
|
// Check if there are packages to process
|
|
148
148
|
const totalPackages = this._libraryPackages.length + this._serverPackages.length + this._watchHookPackages.length + this._clientPackages.length;
|
|
149
149
|
if (totalPackages === 0) {
|
|
150
|
-
const modeLabel = this._options.mode === "watch" ? "
|
|
151
|
-
process.stdout.write(`⚠
|
|
150
|
+
const modeLabel = this._options.mode === "watch" ? "워치" : "개발";
|
|
151
|
+
process.stdout.write(`⚠ ${modeLabel} 대상 패키지가 없습니다.\n`);
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -245,7 +245,7 @@ export class DevWatchOrchestrator {
|
|
|
245
245
|
return;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
process.stdout.write("⏳
|
|
248
|
+
process.stdout.write("⏳ 종료 중...\n");
|
|
249
249
|
|
|
250
250
|
const shutdownTasks: Array<Promise<void>> = [];
|
|
251
251
|
|
|
@@ -274,7 +274,7 @@ export class DevWatchOrchestrator {
|
|
|
274
274
|
this._watchHookWatchers.length = 0;
|
|
275
275
|
this._replaceDepWatcher?.dispose();
|
|
276
276
|
|
|
277
|
-
process.stdout.write("✔
|
|
277
|
+
process.stdout.write("✔ 종료 완료\n");
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// --- Watch mode ---
|
|
@@ -289,12 +289,19 @@ export class DevWatchOrchestrator {
|
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
// Start all engines
|
|
292
|
-
this.
|
|
293
|
-
|
|
294
|
-
|
|
292
|
+
const total = this._libraryEngines.length;
|
|
293
|
+
this._logger.start(`초기 빌드 실행 중... (${total}개 패키지)`);
|
|
294
|
+
let completed = 0;
|
|
295
|
+
|
|
296
|
+
const watchPromises = this._libraryEngines.map(async (engine, i) => {
|
|
297
|
+
const pkgName = this._libraryPackages[i].name;
|
|
298
|
+
await engine.startWatch({ js: true, dts: true, lint: true });
|
|
299
|
+
completed++;
|
|
300
|
+
this._logger.info(` [${completed}/${total}] ${pkgName} 완료`);
|
|
301
|
+
});
|
|
295
302
|
|
|
296
303
|
await Promise.allSettled(watchPromises);
|
|
297
|
-
this._logger.success("
|
|
304
|
+
this._logger.success("초기 빌드 실행 완료");
|
|
298
305
|
|
|
299
306
|
// Print initial build results
|
|
300
307
|
printErrors(this._resultCollector.toMap());
|
|
@@ -314,7 +321,7 @@ export class DevWatchOrchestrator {
|
|
|
314
321
|
});
|
|
315
322
|
this._watchHookWatchers.push(watcher);
|
|
316
323
|
|
|
317
|
-
this._logger.success(
|
|
324
|
+
this._logger.success(`워치 훅 시작됨: ${pkg.name}`);
|
|
318
325
|
}
|
|
319
326
|
}
|
|
320
327
|
|
|
@@ -329,11 +336,11 @@ export class DevWatchOrchestrator {
|
|
|
329
336
|
this._watchHookChildren.set(pkgName, child);
|
|
330
337
|
|
|
331
338
|
child.on("error", (err) => {
|
|
332
|
-
this._logger.error(`
|
|
339
|
+
this._logger.error(`[${pkgName}] 워치 훅 에러: ${err.message}`);
|
|
333
340
|
});
|
|
334
341
|
child.on("close", (code) => {
|
|
335
342
|
if (code !== 0 && code !== null) {
|
|
336
|
-
this._logger.warn(`
|
|
343
|
+
this._logger.warn(`[${pkgName}] 워치 훅이 코드 ${String(code)}로 종료됨`);
|
|
337
344
|
}
|
|
338
345
|
});
|
|
339
346
|
}
|
|
@@ -342,7 +349,7 @@ export class DevWatchOrchestrator {
|
|
|
342
349
|
|
|
343
350
|
private async _startDevMode(): Promise<void> {
|
|
344
351
|
// Start client and server engines in parallel
|
|
345
|
-
this._logger.debug("
|
|
352
|
+
this._logger.debug("초기 빌드 시작");
|
|
346
353
|
const initialBuildPromises: Array<{ name: string; promise: Promise<void> }> = [];
|
|
347
354
|
|
|
348
355
|
for (const [name, engine] of this._clientEngines) {
|
|
@@ -366,9 +373,9 @@ export class DevWatchOrchestrator {
|
|
|
366
373
|
initialResults.forEach((result, index) => {
|
|
367
374
|
const taskName = initialBuildPromises[index].name;
|
|
368
375
|
if (result.status === "rejected") {
|
|
369
|
-
this._logger.debug(`[${taskName}]
|
|
376
|
+
this._logger.debug(`[${taskName}] 초기 빌드 실패:`, result.reason);
|
|
370
377
|
} else {
|
|
371
|
-
this._logger.debug(`[${taskName}]
|
|
378
|
+
this._logger.debug(`[${taskName}] 초기 빌드 완료`);
|
|
372
379
|
}
|
|
373
380
|
});
|
|
374
381
|
|
|
@@ -400,7 +407,7 @@ export class DevWatchOrchestrator {
|
|
|
400
407
|
try {
|
|
401
408
|
await this._startServerRuntime(name, mainJsPath, { ...this._baseEnv, ...config.env }, clientPorts);
|
|
402
409
|
} catch (err) {
|
|
403
|
-
this._logger.error(`[${name}]
|
|
410
|
+
this._logger.error(`[${name}] 서버 런타임 시작 실패:`, errNs.message(err));
|
|
404
411
|
this._resultCollector.add({
|
|
405
412
|
name,
|
|
406
413
|
target: "server",
|
|
@@ -427,7 +434,7 @@ export class DevWatchOrchestrator {
|
|
|
427
434
|
await cap.run(devServerUrl);
|
|
428
435
|
} catch (err) {
|
|
429
436
|
this._logger.error(
|
|
430
|
-
`[${name}] Capacitor
|
|
437
|
+
`[${name}] Capacitor 실행 실패: ${errNs.message(err)}`,
|
|
431
438
|
);
|
|
432
439
|
}
|
|
433
440
|
}
|
|
@@ -440,14 +447,14 @@ export class DevWatchOrchestrator {
|
|
|
440
447
|
await elc.run(devServerUrl);
|
|
441
448
|
} catch (err) {
|
|
442
449
|
this._logger.error(
|
|
443
|
-
`[${name}] Electron
|
|
450
|
+
`[${name}] Electron 실행 실패: ${errNs.message(err)}`,
|
|
444
451
|
);
|
|
445
452
|
this._resultCollector.add({
|
|
446
453
|
name,
|
|
447
454
|
target: "client",
|
|
448
455
|
type: "build",
|
|
449
456
|
status: "error",
|
|
450
|
-
message: `Electron
|
|
457
|
+
message: `Electron 실행 실패: ${errNs.message(err)}`,
|
|
451
458
|
});
|
|
452
459
|
}
|
|
453
460
|
})();
|
|
@@ -469,7 +476,7 @@ export class DevWatchOrchestrator {
|
|
|
469
476
|
restartPromises.push(
|
|
470
477
|
this._startServerRuntime(name, mainJsPath, { ...this._baseEnv, ...config.env }, clientPorts)
|
|
471
478
|
.catch((err: unknown) => {
|
|
472
|
-
this._logger.error(`[${name}]
|
|
479
|
+
this._logger.error(`[${name}] 서버 런타임 시작 실패:`, errNs.message(err));
|
|
473
480
|
this._resultCollector.add({
|
|
474
481
|
name,
|
|
475
482
|
target: "server",
|
|
@@ -519,12 +526,12 @@ export class DevWatchOrchestrator {
|
|
|
519
526
|
env?: Record<string, string>,
|
|
520
527
|
clientPorts?: Record<string, number>,
|
|
521
528
|
): Promise<void> {
|
|
522
|
-
this._logger.debug(`[${serverName}]
|
|
529
|
+
this._logger.debug(`[${serverName}] 서버 런타임 시작: ${mainJsPath}`);
|
|
523
530
|
|
|
524
531
|
// Terminate existing runtime
|
|
525
532
|
const existingRuntime = this._serverRuntimeWorkers.get(serverName);
|
|
526
533
|
if (existingRuntime != null) {
|
|
527
|
-
this._logger.info(`[${serverName}]
|
|
534
|
+
this._logger.info(`[${serverName}] 서버 재시작 중...`);
|
|
528
535
|
await existingRuntime.terminate();
|
|
529
536
|
}
|
|
530
537
|
|
|
@@ -560,7 +567,7 @@ export class DevWatchOrchestrator {
|
|
|
560
567
|
runtimeWorker
|
|
561
568
|
.start({ mainJsPath, clientPorts, env })
|
|
562
569
|
.catch((err: unknown) => {
|
|
563
|
-
this._logger.error(`[${serverName}]
|
|
570
|
+
this._logger.error(`[${serverName}] 서버 런타임 워커 비정상 종료:`, errNs.message(err));
|
|
564
571
|
this._resultCollector.add({
|
|
565
572
|
name: serverName,
|
|
566
573
|
target: "server",
|
package/src/sd-cli.ts
CHANGED
|
@@ -31,7 +31,7 @@ if (isDev) {
|
|
|
31
31
|
const { loadSdConfig } = await import("./utils/sd-config.js");
|
|
32
32
|
const { setupReplaceDeps } = await import("./utils/replace-deps.js");
|
|
33
33
|
const sdConfig = await loadSdConfig({ cwd: process.cwd(), dev: false, options: [] });
|
|
34
|
-
if (sdConfig.replaceDeps != null) {
|
|
34
|
+
if (process.argv[2] !== "replace-deps" && sdConfig.replaceDeps != null) {
|
|
35
35
|
await setupReplaceDeps(process.cwd(), sdConfig.replaceDeps);
|
|
36
36
|
}
|
|
37
37
|
} catch {
|
|
@@ -57,22 +57,29 @@ export interface ServerEsbuildOptions {
|
|
|
57
57
|
dev?: boolean;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Generate a JS banner snippet that merges env vars into process.env at runtime.
|
|
62
|
+
* Uses ??= so that runtime ENV (e.g. `DEV=false node server.js`) takes precedence
|
|
63
|
+
* over build-time defaults.
|
|
64
|
+
*/
|
|
65
|
+
export function createEnvBanner(env?: Record<string, string>): string {
|
|
66
|
+
if (env == null || Object.keys(env).length === 0) return "";
|
|
67
|
+
return `for(const[__k,__v]of Object.entries(${JSON.stringify(env)})){process.env[__k]??=__v;}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
60
70
|
/**
|
|
61
71
|
* Create esbuild config for Server build
|
|
62
72
|
*
|
|
63
73
|
* Used for server package builds
|
|
64
74
|
* - bundle: true (single bundle with all dependencies)
|
|
65
75
|
* - minify: true (minify for code protection)
|
|
66
|
-
* - banner: createRequire shim for CJS package require() support
|
|
67
|
-
* - Replace env with define option (process.env.KEY format)
|
|
76
|
+
* - banner: createRequire shim for CJS package require() support + env injection
|
|
68
77
|
*/
|
|
69
78
|
export function createServerEsbuildOptions(options: ServerEsbuildOptions): esbuild.BuildOptions {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
}
|
|
79
|
+
const envBanner = createEnvBanner(options.env);
|
|
80
|
+
const bannerJs =
|
|
81
|
+
"import { createRequire } from 'module'; const require = createRequire(import.meta.url);" +
|
|
82
|
+
envBanner;
|
|
76
83
|
|
|
77
84
|
return {
|
|
78
85
|
entryPoints: options.entryPoints,
|
|
@@ -82,11 +89,8 @@ export function createServerEsbuildOptions(options: ServerEsbuildOptions): esbui
|
|
|
82
89
|
platform: "node",
|
|
83
90
|
target: "node20",
|
|
84
91
|
bundle: true,
|
|
85
|
-
banner: {
|
|
86
|
-
js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);",
|
|
87
|
-
},
|
|
92
|
+
banner: { js: bannerJs },
|
|
88
93
|
external: options.external,
|
|
89
|
-
define,
|
|
90
94
|
tsconfig: path.join(options.pkgDir, "tsconfig.json"),
|
|
91
95
|
logLevel: "silent",
|
|
92
96
|
};
|
|
@@ -25,7 +25,7 @@ export function printErrors(results: Map<string, BuildResult>): void {
|
|
|
25
25
|
if (result.message != null && result.message !== "") {
|
|
26
26
|
consola.error(formatBuildMessages(result.name, typeLabel, [result.message]));
|
|
27
27
|
} else {
|
|
28
|
-
consola.error(
|
|
28
|
+
consola.error(`[${result.name}] (${typeLabel}) 실패`);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -113,7 +113,7 @@ export function collectDeps(
|
|
|
113
113
|
replaceDepsConfig?: Record<string, string>,
|
|
114
114
|
): DepsResult {
|
|
115
115
|
const startTime = performance.now();
|
|
116
|
-
logger.debug("
|
|
116
|
+
logger.debug("의존성 수집 시작");
|
|
117
117
|
const rootPkgJsonPath = path.join(cwd, "package.json");
|
|
118
118
|
const rootPkgJson = JSON.parse(fs.readFileSync(rootPkgJsonPath, "utf-8")) as { name: string };
|
|
119
119
|
const scopeMatch = rootPkgJson.name.match(/^(@[^/]+)\//);
|
|
@@ -170,7 +170,7 @@ export function collectDeps(
|
|
|
170
170
|
|
|
171
171
|
traverse(pkgDir);
|
|
172
172
|
logger.debug(
|
|
173
|
-
|
|
173
|
+
`의존성 수집 완료: workspace=${String(workspaceDeps.length)}, replace=${String(replaceDeps.length)} (${Math.round(performance.now() - startTime)}ms)`,
|
|
174
174
|
);
|
|
175
175
|
return { workspaceDeps, replaceDeps };
|
|
176
176
|
}
|
|
@@ -347,7 +347,7 @@ export function classifyDevPackages(
|
|
|
347
347
|
serverClientsMap.set(clientConfig.server, clients);
|
|
348
348
|
} else {
|
|
349
349
|
process.stdout.write(
|
|
350
|
-
`⚠
|
|
350
|
+
`⚠ 클라이언트 "${name}"의 서버 "${clientConfig.server}"가 dev 대상에 없어 독립 실행됩니다.\n`,
|
|
351
351
|
);
|
|
352
352
|
}
|
|
353
353
|
}
|
|
@@ -45,7 +45,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
|
45
45
|
|
|
46
46
|
const tasks = Array.from(batchBuilds.entries());
|
|
47
47
|
const titles = tasks.map(([, { title }]) => title).join(", ");
|
|
48
|
-
this._logger.start(
|
|
48
|
+
this._logger.start(`리빌드 실행 중... (${titles})`);
|
|
49
49
|
|
|
50
50
|
const results = await Promise.allSettled(tasks.map(([, { promise }]) => promise));
|
|
51
51
|
|
|
@@ -54,11 +54,11 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
|
54
54
|
const failed = results.filter((r): r is PromiseRejectedResult => r.status === "rejected");
|
|
55
55
|
if (failed.length > 0) {
|
|
56
56
|
for (const result of failed) {
|
|
57
|
-
this._logger.error("
|
|
57
|
+
this._logger.error("리빌드 에러 발생", { error: String(result.reason) });
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
this._logger.success(
|
|
61
|
+
this._logger.success(`리빌드 실행 완료 (${titles})`);
|
|
62
62
|
|
|
63
63
|
this.emit("batchComplete");
|
|
64
64
|
|