@simplysm/sd-cli 14.0.10 → 14.0.12
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 +58 -253
- package/dist/angular/client-transform-stylesheet.js +1 -1
- package/dist/angular/client-transform-stylesheet.js.map +1 -1
- package/dist/angular/vite-angular-plugin.d.ts +1 -1
- package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
- package/dist/angular/vite-angular-plugin.js +60 -34
- package/dist/angular/vite-angular-plugin.js.map +1 -1
- package/dist/angular/vite-postcss-inline-plugin.d.ts +1 -1
- package/dist/angular/vite-postcss-inline-plugin.js +1 -1
- package/dist/capacitor/capacitor.d.ts +14 -2
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +131 -17
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/build.d.ts +3 -10
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +3 -10
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +3 -9
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +3 -9
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/device.d.ts +13 -0
- package/dist/commands/device.d.ts.map +1 -0
- package/dist/commands/device.js +53 -0
- package/dist/commands/device.js.map +1 -0
- package/dist/commands/publish.d.ts +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +18 -26
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/replace-deps.d.ts +3 -3
- package/dist/commands/replace-deps.d.ts.map +1 -1
- package/dist/commands/replace-deps.js +1 -1
- package/dist/commands/typecheck.d.ts +4 -3
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +5 -11
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/watch.d.ts +9 -9
- package/dist/commands/watch.js +9 -9
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +42 -3
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts +1 -1
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +3 -1
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/engines/NgtscEngine.d.ts +7 -7
- package/dist/engines/NgtscEngine.d.ts.map +1 -1
- package/dist/engines/NgtscEngine.js +3 -3
- package/dist/engines/ServerEsbuildEngine.d.ts +7 -7
- package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
- package/dist/engines/ServerEsbuildEngine.js +3 -3
- package/dist/engines/TscEngine.d.ts +7 -7
- package/dist/engines/TscEngine.d.ts.map +1 -1
- package/dist/engines/TscEngine.js +3 -3
- package/dist/engines/ViteEngine.d.ts +1 -1
- package/dist/engines/ViteEngine.d.ts.map +1 -1
- package/dist/engines/ViteEngine.js +7 -12
- package/dist/engines/ViteEngine.js.map +1 -1
- package/dist/engines/index.d.ts +5 -5
- package/dist/engines/index.js +5 -5
- package/dist/engines/types.d.ts +20 -20
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/infra/ResultCollector.d.ts +9 -9
- package/dist/infra/ResultCollector.js +8 -8
- package/dist/infra/SignalHandler.d.ts +7 -7
- package/dist/infra/SignalHandler.js +7 -7
- package/dist/infra/WorkerManager.d.ts +14 -14
- package/dist/infra/WorkerManager.js +14 -14
- package/dist/orchestrators/BuildOrchestrator.d.ts +25 -25
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +29 -29
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.d.ts +7 -7
- package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.js +35 -57
- package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +2 -2
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +45 -9
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.d.ts +3 -3
- package/dist/sd-cli.js +16 -16
- package/dist/sd-cli.js.map +1 -1
- package/dist/sd-config.types.d.ts +105 -105
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/angular-compiler.js +5 -5
- package/dist/utils/angular-compiler.js.map +1 -1
- package/dist/utils/build-env.d.ts +1 -1
- package/dist/utils/build-env.js +1 -1
- package/dist/utils/concurrency.d.ts +7 -7
- package/dist/utils/concurrency.js +7 -7
- package/dist/utils/copy-public.d.ts +9 -9
- package/dist/utils/copy-public.js +17 -17
- package/dist/utils/copy-public.js.map +1 -1
- package/dist/utils/copy-src.d.ts +9 -9
- package/dist/utils/copy-src.js +11 -11
- package/dist/utils/copy-src.js.map +1 -1
- package/dist/utils/engine-stop.d.ts +8 -9
- package/dist/utils/engine-stop.d.ts.map +1 -1
- package/dist/utils/engine-stop.js +9 -10
- package/dist/utils/engine-stop.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts +23 -23
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +25 -25
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/lint-with-program.d.ts +15 -15
- package/dist/utils/lint-with-program.d.ts.map +1 -1
- package/dist/utils/lint-with-program.js +29 -29
- package/dist/utils/lint-with-program.js.map +1 -1
- package/dist/utils/ngtsc-build-core.d.ts +8 -8
- package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
- package/dist/utils/ngtsc-build-core.js +14 -14
- package/dist/utils/ngtsc-build-core.js.map +1 -1
- package/dist/utils/output-path-rewriter.d.ts +14 -14
- package/dist/utils/output-path-rewriter.js +18 -18
- package/dist/utils/output-path-rewriter.js.map +1 -1
- package/dist/utils/output-utils.d.ts +6 -6
- package/dist/utils/output-utils.js +11 -11
- package/dist/utils/output-utils.js.map +1 -1
- package/dist/utils/package-utils.d.ts +21 -21
- package/dist/utils/package-utils.d.ts.map +1 -1
- package/dist/utils/package-utils.js +56 -45
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/replace-deps.d.ts +25 -25
- package/dist/utils/replace-deps.d.ts.map +1 -1
- package/dist/utils/replace-deps.js +84 -65
- package/dist/utils/replace-deps.js.map +1 -1
- package/dist/utils/sd-config.d.ts +3 -3
- package/dist/utils/sd-config.js +3 -3
- package/dist/utils/tsc-build.d.ts +13 -13
- package/dist/utils/tsc-build.d.ts.map +1 -1
- package/dist/utils/tsc-build.js +9 -9
- package/dist/utils/tsc-build.js.map +1 -1
- package/dist/utils/tsconfig.d.ts +11 -9
- package/dist/utils/tsconfig.d.ts.map +1 -1
- package/dist/utils/tsconfig.js +11 -9
- package/dist/utils/tsconfig.js.map +1 -1
- package/dist/utils/typecheck-non-package.d.ts +5 -6
- package/dist/utils/typecheck-non-package.d.ts.map +1 -1
- package/dist/utils/typecheck-non-package.js +7 -8
- package/dist/utils/typecheck-non-package.js.map +1 -1
- package/dist/utils/typecheck-serialization.d.ts +8 -8
- package/dist/utils/typecheck-serialization.d.ts.map +1 -1
- package/dist/utils/typecheck-serialization.js +12 -16
- package/dist/utils/typecheck-serialization.js.map +1 -1
- package/dist/utils/vite-config.d.ts +8 -5
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +36 -29
- package/dist/utils/vite-config.js.map +1 -1
- package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
- package/dist/utils/vite-scope-watch-plugin.js +1 -1
- package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
- package/dist/utils/worker-events.d.ts +12 -12
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-events.js +10 -10
- package/dist/utils/worker-events.js.map +1 -1
- package/dist/utils/worker-utils.d.ts +12 -13
- package/dist/utils/worker-utils.d.ts.map +1 -1
- package/dist/utils/worker-utils.js +12 -13
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/vitest-plugin.d.ts.map +1 -1
- package/dist/vitest-plugin.js +5 -7
- package/dist/vitest-plugin.js.map +1 -1
- package/dist/workers/client.worker.d.ts +4 -2
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +209 -1
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts +1 -1
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +7 -7
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/lint.worker.d.ts +2 -2
- package/dist/workers/lint.worker.js +2 -2
- package/dist/workers/ngtsc-build.worker.js +30 -30
- package/dist/workers/ngtsc-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts +17 -17
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +46 -46
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.d.ts +7 -7
- package/dist/workers/server-runtime.worker.d.ts.map +1 -1
- package/dist/workers/server-runtime.worker.js +17 -17
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/docs/config.md +340 -0
- package/docs/publish-configuration-types.md +87 -0
- package/docs/pwa-configuration-types.md +55 -0
- package/docs/vitest-plugin.md +47 -0
- package/package.json +9 -7
- package/src/angular/client-transform-stylesheet.ts +1 -1
- package/src/angular/vite-angular-plugin.ts +70 -37
- package/src/angular/vite-postcss-inline-plugin.ts +1 -1
- package/src/capacitor/capacitor.ts +159 -23
- package/src/commands/build.ts +3 -10
- package/src/commands/check.ts +3 -3
- package/src/commands/dev.ts +3 -9
- package/src/commands/device.ts +65 -0
- package/src/commands/publish.ts +30 -26
- package/src/commands/replace-deps.ts +3 -3
- package/src/commands/typecheck.ts +7 -13
- package/src/commands/watch.ts +9 -9
- package/src/electron/electron.ts +49 -4
- package/src/engines/BaseEngine.ts +4 -1
- package/src/engines/NgtscEngine.ts +7 -7
- package/src/engines/ServerEsbuildEngine.ts +7 -7
- package/src/engines/TscEngine.ts +7 -7
- package/src/engines/ViteEngine.ts +8 -13
- package/src/engines/index.ts +5 -5
- package/src/engines/types.ts +20 -20
- package/src/infra/ResultCollector.ts +9 -9
- package/src/infra/SignalHandler.ts +7 -7
- package/src/infra/WorkerManager.ts +14 -14
- package/src/orchestrators/BuildOrchestrator.ts +37 -37
- package/src/orchestrators/DevWatchOrchestrator.ts +37 -61
- package/src/sd-cli-entry.ts +51 -9
- package/src/sd-cli.ts +16 -16
- package/src/sd-config.types.ts +107 -107
- package/src/utils/angular-compiler.ts +5 -5
- package/src/utils/build-env.ts +1 -1
- package/src/utils/concurrency.ts +7 -7
- package/src/utils/copy-public.ts +17 -17
- package/src/utils/copy-src.ts +11 -11
- package/src/utils/engine-stop.ts +9 -10
- package/src/utils/esbuild-config.ts +29 -29
- package/src/utils/lint-with-program.ts +34 -34
- package/src/utils/ngtsc-build-core.ts +17 -17
- package/src/utils/output-path-rewriter.ts +18 -18
- package/src/utils/output-utils.ts +11 -11
- package/src/utils/package-utils.ts +57 -45
- package/src/utils/replace-deps.ts +92 -67
- package/src/utils/sd-config.ts +3 -3
- package/src/utils/tsc-build.ts +18 -18
- package/src/utils/tsconfig.ts +11 -9
- package/src/utils/typecheck-non-package.ts +7 -8
- package/src/utils/typecheck-serialization.ts +13 -15
- package/src/utils/vite-config.ts +45 -35
- package/src/utils/vite-scope-watch-plugin.ts +6 -1
- package/src/utils/worker-events.ts +16 -16
- package/src/utils/worker-utils.ts +12 -13
- package/src/vitest-plugin.ts +5 -8
- package/src/workers/client.worker.ts +236 -2
- package/src/workers/library-build.worker.ts +8 -8
- package/src/workers/lint.worker.ts +2 -2
- package/src/workers/ngtsc-build.worker.ts +31 -31
- package/src/workers/server-build.worker.ts +60 -60
- package/src/workers/server-runtime.worker.ts +22 -22
- package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +1 -0
- package/tests/angular/vite-angular-plugin-hmr.spec.ts +78 -0
- package/tests/angular/vite-angular-plugin.spec.ts +67 -0
- package/tests/capacitor/capacitor-build.spec.ts +6 -4
- package/tests/capacitor/capacitor-icon.spec.ts +7 -5
- package/tests/capacitor/capacitor-init.spec.ts +120 -10
- package/tests/capacitor/capacitor-run.spec.ts +14 -17
- package/tests/capacitor/capacitor-workspace.spec.ts +5 -3
- package/tests/commands/check.spec.ts +2 -2
- package/tests/commands/device.spec.ts +147 -0
- package/tests/commands/publish.spec.ts +2 -2
- package/tests/commands/typecheck.spec.ts +8 -0
- package/tests/electron/electron.spec.ts +12 -10
- package/tests/engines/base-engine.spec.ts +37 -0
- package/tests/engines/vite-engine.spec.ts +115 -3
- package/tests/orchestrators/dev-watch-orchestrator.spec.ts +21 -93
- package/tests/utils/vite-config.spec.ts +144 -90
- package/tests/workers/client-worker.spec.ts +690 -0
- package/tests/workers/server-build-worker.spec.ts +3 -3
|
@@ -34,7 +34,7 @@ export interface SdAngularPluginOptions {
|
|
|
34
34
|
warnings?: string[];
|
|
35
35
|
lint?: LintWithProgramResult;
|
|
36
36
|
}) => void;
|
|
37
|
-
/**
|
|
37
|
+
/** 컴파일의 ts.Program을 사용하여 lint 실행 */
|
|
38
38
|
enableLint?: boolean;
|
|
39
39
|
/** browserslist 타겟 (정규화된 배열) */
|
|
40
40
|
browserslist?: string[];
|
|
@@ -68,7 +68,7 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
68
68
|
) as { name?: string };
|
|
69
69
|
pkgName = pkgJson.name ?? "unknown";
|
|
70
70
|
} catch {
|
|
71
|
-
//
|
|
71
|
+
// 무시
|
|
72
72
|
}
|
|
73
73
|
lintRunner = new LintWithProgramRunner({
|
|
74
74
|
cwd: process.cwd(),
|
|
@@ -83,6 +83,12 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
83
83
|
let hmrLock: Promise<void> = Promise.resolve();
|
|
84
84
|
const scssDependencies = new Map<string, Set<string>>();
|
|
85
85
|
|
|
86
|
+
// Pre-bundle transformer: optimizeDeps의 esbuild 단계에서 Angular Linker 실행
|
|
87
|
+
const prebundleTransformer = new JavaScriptTransformer(
|
|
88
|
+
{ sourcemap: options.dev, jit: false, thirdPartySourcemaps: options.dev },
|
|
89
|
+
1,
|
|
90
|
+
);
|
|
91
|
+
|
|
86
92
|
function createJsTransformer(): JavaScriptTransformer {
|
|
87
93
|
const maxThreads = Math.max(1, Math.floor((os.cpus().length * 2) / 3));
|
|
88
94
|
return new JavaScriptTransformer(
|
|
@@ -107,6 +113,24 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
107
113
|
ngJitMode: "false",
|
|
108
114
|
ngHmrMode: options.dev ? undefined : "false",
|
|
109
115
|
},
|
|
116
|
+
optimizeDeps: {
|
|
117
|
+
esbuildOptions: {
|
|
118
|
+
plugins: [
|
|
119
|
+
{
|
|
120
|
+
name: "angular-vite-optimize-deps",
|
|
121
|
+
setup(build: { onLoad: Function }) {
|
|
122
|
+
build.onLoad(
|
|
123
|
+
{ filter: /\.[cm]?js$/ },
|
|
124
|
+
async (args: { path: string }) => ({
|
|
125
|
+
contents: await prebundleTransformer.transformFile(args.path),
|
|
126
|
+
loader: "js" as const,
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
110
134
|
};
|
|
111
135
|
},
|
|
112
136
|
|
|
@@ -188,7 +212,7 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
188
212
|
logger.error(err);
|
|
189
213
|
}
|
|
190
214
|
|
|
191
|
-
//
|
|
215
|
+
// lint 실행 (활성화된 경우)
|
|
192
216
|
let initialLintResult: LintWithProgramResult | undefined;
|
|
193
217
|
if (options.enableLint === true) {
|
|
194
218
|
initialLintResult = await getOrCreateLintRunner().lint({
|
|
@@ -196,7 +220,7 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
196
220
|
});
|
|
197
221
|
}
|
|
198
222
|
|
|
199
|
-
//
|
|
223
|
+
// 초기 빌드 결과 보고 (dev, prod 공통)
|
|
200
224
|
options.onBuild?.({
|
|
201
225
|
success: diagnosticResult.errors.length === 0,
|
|
202
226
|
errors: diagnosticResult.errors.map((e) => e.message),
|
|
@@ -218,14 +242,13 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
218
242
|
if (compiler == null || !options.dev) return;
|
|
219
243
|
if (
|
|
220
244
|
!file.endsWith(".ts") &&
|
|
221
|
-
!file.endsWith(".tsx") &&
|
|
222
245
|
!file.endsWith(".html") &&
|
|
223
246
|
!file.endsWith(".scss")
|
|
224
247
|
) {
|
|
225
248
|
return;
|
|
226
249
|
}
|
|
227
250
|
|
|
228
|
-
//
|
|
251
|
+
// 의존성 필터: TypeScript program에 포함되지 않은 파일은 건너뜀
|
|
229
252
|
const normalizedFile = pathx.posix(file);
|
|
230
253
|
const programFiles = compiler.getTsProgram().getSourceFiles();
|
|
231
254
|
const isInProgram = programFiles.some(
|
|
@@ -269,13 +292,13 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
269
292
|
const diagnosticResult = collectAndFormatDiagnostics(compiler, process.cwd());
|
|
270
293
|
reportDiagnostics(diagnosticResult);
|
|
271
294
|
|
|
272
|
-
//
|
|
295
|
+
// 영향받은 ts.SourceFile 집합을 파일명 문자열로 변환 (incremental lint용)
|
|
273
296
|
const affectedFileNames = new Set<string>();
|
|
274
297
|
for (const sf of updateResult.affectedFiles) {
|
|
275
298
|
affectedFileNames.add(pathx.posix(sf.fileName));
|
|
276
299
|
}
|
|
277
300
|
|
|
278
|
-
//
|
|
301
|
+
// lint 실행 (활성화된 경우)
|
|
279
302
|
let lintResult: LintWithProgramResult | undefined;
|
|
280
303
|
if (options.enableLint === true) {
|
|
281
304
|
lintResult = await getOrCreateLintRunner().lint({
|
|
@@ -306,21 +329,23 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
306
329
|
},
|
|
307
330
|
|
|
308
331
|
async transform(_code, id) {
|
|
309
|
-
if (
|
|
332
|
+
if (jsTransformer == null) return;
|
|
310
333
|
|
|
311
|
-
|
|
312
|
-
const emittedContent = emittedFiles.get(normalizedId);
|
|
313
|
-
if (emittedContent == null) return;
|
|
334
|
+
let code = _code;
|
|
314
335
|
|
|
315
|
-
|
|
316
|
-
|
|
336
|
+
// Phase 1: TS 컴파일 — .ts 파일은 AngularCompiler가 emit한 JS로 교체
|
|
337
|
+
if (id.endsWith(".ts")) {
|
|
338
|
+
const normalizedId = pathx.posix(id);
|
|
339
|
+
const emittedContent = emittedFiles.get(normalizedId);
|
|
340
|
+
if (emittedContent == null) return;
|
|
341
|
+
code = emittedContent;
|
|
342
|
+
} else if (!id.endsWith(".mjs") && !id.endsWith(".js")) {
|
|
343
|
+
return;
|
|
317
344
|
}
|
|
318
345
|
|
|
319
|
-
// AOT
|
|
320
|
-
const transformed = await jsTransformer.transformData(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return { code };
|
|
346
|
+
// Phase 2: JS 변환 — Angular Linker로 partial → full AOT 링킹 + 최적화
|
|
347
|
+
const transformed = await jsTransformer.transformData(pathx.posix(id), code, false);
|
|
348
|
+
return { code: new TextDecoder().decode(transformed) };
|
|
324
349
|
},
|
|
325
350
|
|
|
326
351
|
async buildEnd() {
|
|
@@ -330,6 +355,7 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
330
355
|
await jsTransformer.close();
|
|
331
356
|
jsTransformer = undefined;
|
|
332
357
|
}
|
|
358
|
+
await prebundleTransformer.close();
|
|
333
359
|
compiler = undefined;
|
|
334
360
|
emittedFiles.clear();
|
|
335
361
|
}
|
|
@@ -337,24 +363,24 @@ export function sdAngularPlugin(options: SdAngularPluginOptions): Plugin {
|
|
|
337
363
|
|
|
338
364
|
configureServer(server: ViteDevServer) {
|
|
339
365
|
// component-middleware 등록 (HMR template updates 서빙)
|
|
340
|
-
server.middlewares.use(angularComponentMiddleware(templateUpdates));
|
|
366
|
+
server.middlewares.use(angularComponentMiddleware(templateUpdates, server.config.base));
|
|
341
367
|
|
|
342
368
|
// dev server 종료 시 리소스 정리
|
|
343
369
|
server.httpServer?.on("close", () => {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
370
|
+
void Promise.all([
|
|
371
|
+
jsTransformer?.close(),
|
|
372
|
+
prebundleTransformer.close(),
|
|
373
|
+
])
|
|
374
|
+
.catch((err: unknown) => {
|
|
375
|
+
logger.error(
|
|
376
|
+
`Resource dispose failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
377
|
+
);
|
|
378
|
+
})
|
|
379
|
+
.finally(() => {
|
|
380
|
+
jsTransformer = undefined;
|
|
381
|
+
compiler = undefined;
|
|
382
|
+
emittedFiles.clear();
|
|
383
|
+
});
|
|
358
384
|
});
|
|
359
385
|
},
|
|
360
386
|
};
|
|
@@ -401,15 +427,22 @@ function collectAndFormatDiagnostics(compiler: AngularCompiler, cwd: string): Di
|
|
|
401
427
|
|
|
402
428
|
function angularComponentMiddleware(
|
|
403
429
|
templateUpdates: Map<string, string>,
|
|
430
|
+
basePath: string,
|
|
404
431
|
): (req: IncomingMessage, res: ServerResponse, next: () => void) => void {
|
|
405
432
|
return (req, res, next) => {
|
|
406
|
-
|
|
433
|
+
const rawUrl = req.url ?? "";
|
|
434
|
+
const parsedUrl = new URL(rawUrl, "http://localhost");
|
|
435
|
+
const pathname = decodeURIComponent(parsedUrl.pathname);
|
|
436
|
+
const strippedPathname =
|
|
437
|
+
basePath !== "/" && pathname.startsWith(basePath)
|
|
438
|
+
? pathname.slice(basePath.length - 1)
|
|
439
|
+
: pathname;
|
|
440
|
+
if (!strippedPathname.includes("/@ng/component")) {
|
|
407
441
|
next();
|
|
408
442
|
return;
|
|
409
443
|
}
|
|
410
444
|
|
|
411
|
-
const
|
|
412
|
-
const componentId = url.searchParams.get("c") ?? "";
|
|
445
|
+
const componentId = parsedUrl.searchParams.get("c") ?? "";
|
|
413
446
|
const body = templateUpdates.get(encodeURIComponent(componentId)) ?? "";
|
|
414
447
|
|
|
415
448
|
res.writeHead(200, {
|
|
@@ -9,7 +9,7 @@ export interface SdPostCssInlinePluginOptions {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* JS 파일 내 Angular @Component 인라인 스타일에 PostCSS를 적용하는 Vite 플러그인.
|
|
13
13
|
*
|
|
14
14
|
* TS AST로 @Component decorator의 `styles` 배열에서 CSS 문자열을 추출하고,
|
|
15
15
|
* PostCSS를 적용한 후 교체한다.
|
|
@@ -5,7 +5,7 @@ import { symlink } from "fs/promises";
|
|
|
5
5
|
import { createRequire } from "module";
|
|
6
6
|
import { cpx, fsx, pathx } from "@simplysm/core-node";
|
|
7
7
|
import { env } from "@simplysm/core-common";
|
|
8
|
-
import { consola } from "consola";
|
|
8
|
+
import { consola, LogLevels } from "consola";
|
|
9
9
|
import type { SdCapacitorConfig } from "../sd-config.types.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -91,9 +91,7 @@ export class Capacitor {
|
|
|
91
91
|
const platforms = Object.keys(config.platform);
|
|
92
92
|
for (const p of platforms) {
|
|
93
93
|
if (p !== "android") {
|
|
94
|
-
throw new CapacitorConfigError(
|
|
95
|
-
`지원하지 않는 플랫폼입니다: ${p} (현재 android만 지원)`,
|
|
96
|
-
);
|
|
94
|
+
throw new CapacitorConfigError(`지원하지 않는 플랫폼입니다: ${p} (현재 android만 지원)`);
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
97
|
}
|
|
@@ -109,47 +107,65 @@ export class Capacitor {
|
|
|
109
107
|
* 5. cap sync 또는 cap copy 실행
|
|
110
108
|
*/
|
|
111
109
|
async initialize(): Promise<void> {
|
|
110
|
+
Capacitor._logger.debug("initialize 시작");
|
|
112
111
|
await this._acquireLock();
|
|
113
112
|
|
|
114
113
|
try {
|
|
115
114
|
// 외부 도구 검증
|
|
115
|
+
Capacitor._logger.debug("외부 도구 검증 시작");
|
|
116
116
|
await this._validateTools();
|
|
117
|
+
Capacitor._logger.debug("외부 도구 검증 완료");
|
|
117
118
|
|
|
118
119
|
// 1. Capacitor 프로젝트 초기화
|
|
120
|
+
Capacitor._logger.debug("Capacitor 프로젝트 초기화 시작");
|
|
119
121
|
const changed = await this._initCap();
|
|
122
|
+
Capacitor._logger.debug(`Capacitor 프로젝트 초기화 완료 (changed: ${changed})`);
|
|
120
123
|
|
|
121
124
|
// 2. Capacitor 설정 파일 생성
|
|
125
|
+
Capacitor._logger.debug("Capacitor 설정 파일 생성 시작");
|
|
122
126
|
await this._writeCapConf();
|
|
127
|
+
Capacitor._logger.debug("Capacitor 설정 파일 생성 완료");
|
|
123
128
|
|
|
124
129
|
// 3. 플랫폼 관리 (멱등성: 이미 존재하면 스킵)
|
|
130
|
+
Capacitor._logger.debug("플랫폼 추가 시작");
|
|
125
131
|
await this._addPlatforms();
|
|
132
|
+
Capacitor._logger.debug("플랫폼 추가 완료");
|
|
126
133
|
|
|
127
134
|
// 4. 아이콘 처리
|
|
135
|
+
Capacitor._logger.debug("아이콘 처리 시작");
|
|
128
136
|
await this._setupIcon();
|
|
137
|
+
Capacitor._logger.debug("아이콘 처리 완료");
|
|
129
138
|
|
|
130
139
|
// 5. Android 네이티브 설정 구성
|
|
131
140
|
if (this._platforms.includes("android")) {
|
|
141
|
+
Capacitor._logger.debug("Android 네이티브 설정 시작");
|
|
132
142
|
await this._configureAndroid();
|
|
143
|
+
Capacitor._logger.debug("Android 네이티브 설정 완료");
|
|
133
144
|
}
|
|
134
145
|
|
|
135
146
|
// 6. 웹 에셋 동기화
|
|
136
147
|
if (changed) {
|
|
148
|
+
Capacitor._logger.debug("cap sync 시작 (의존성 변경됨)");
|
|
137
149
|
await this._execCap(["sync"]);
|
|
150
|
+
Capacitor._logger.debug("cap sync 완료");
|
|
138
151
|
} else {
|
|
152
|
+
Capacitor._logger.debug("cap copy 시작");
|
|
139
153
|
await this._execCap(["copy"]);
|
|
154
|
+
Capacitor._logger.debug("cap copy 완료");
|
|
140
155
|
}
|
|
141
156
|
} finally {
|
|
142
157
|
await this._releaseLock();
|
|
158
|
+
Capacitor._logger.debug("initialize 완료");
|
|
143
159
|
}
|
|
144
160
|
}
|
|
145
161
|
|
|
146
162
|
//#region Private - 명령어 실행
|
|
147
163
|
|
|
148
164
|
/**
|
|
149
|
-
* Capacitor CLI 명령어를
|
|
165
|
+
* Capacitor CLI 명령어를 pnpm exec로 실행
|
|
150
166
|
*/
|
|
151
167
|
private async _execCap(args: string[]): Promise<string> {
|
|
152
|
-
return this._exec("
|
|
168
|
+
return this._exec("pnpm", ["exec", "cap", ...args], this._capPath);
|
|
153
169
|
}
|
|
154
170
|
|
|
155
171
|
/**
|
|
@@ -157,7 +173,11 @@ export class Capacitor {
|
|
|
157
173
|
*/
|
|
158
174
|
private async _exec(command: string, args: string[], cwd: string): Promise<string> {
|
|
159
175
|
Capacitor._logger.debug(`명령어 실행: ${command} ${args.join(" ")}`);
|
|
160
|
-
const
|
|
176
|
+
const isDebug = consola.level >= LogLevels.debug;
|
|
177
|
+
const { stdout } = await cpx.spawn(command, args, {
|
|
178
|
+
cwd,
|
|
179
|
+
...(isDebug ? { stdio: ["ignore", "inherit", "inherit"] } : {}),
|
|
180
|
+
});
|
|
161
181
|
Capacitor._logger.debug(`실행 결과: ${stdout}`);
|
|
162
182
|
return stdout;
|
|
163
183
|
}
|
|
@@ -215,6 +235,7 @@ export class Capacitor {
|
|
|
215
235
|
"2. ANDROID_HOME 또는 ANDROID_SDK_ROOT 환경 변수를 설정하세요.",
|
|
216
236
|
);
|
|
217
237
|
}
|
|
238
|
+
Capacitor._logger.debug(`Android SDK 경로: ${sdkPath}`);
|
|
218
239
|
|
|
219
240
|
// Java 확인 (android 플랫폼인 경우에만)
|
|
220
241
|
if (this._platforms.includes("android")) {
|
|
@@ -223,6 +244,8 @@ export class Capacitor {
|
|
|
223
244
|
Capacitor._logger.warn(
|
|
224
245
|
"Java 21을 찾을 수 없습니다. Gradle이 내장 JDK를 사용하거나 빌드가 실패할 수 있습니다.",
|
|
225
246
|
);
|
|
247
|
+
} else {
|
|
248
|
+
Capacitor._logger.debug(`Java 21 경로: ${javaPath}`);
|
|
226
249
|
}
|
|
227
250
|
}
|
|
228
251
|
}
|
|
@@ -235,26 +258,45 @@ export class Capacitor {
|
|
|
235
258
|
* Capacitor 프로젝트 기본 초기화 (package.json, npm install, cap init)
|
|
236
259
|
*/
|
|
237
260
|
private async _initCap(): Promise<boolean> {
|
|
261
|
+
Capacitor._logger.debug("package.json 설정 시작");
|
|
238
262
|
const { depChanged, workspacePlugins } = await this._setupNpmConf();
|
|
239
263
|
const nodeModulesExists = await fsx.exists(pathx.posixResolve(this._capPath, "node_modules"));
|
|
264
|
+
Capacitor._logger.debug(`depChanged: ${depChanged}, nodeModulesExists: ${nodeModulesExists}`);
|
|
240
265
|
|
|
241
266
|
if (!depChanged && nodeModulesExists) {
|
|
242
267
|
// 의존성 미변경이어도 workspace 플러그인 symlink는 항상 갱신
|
|
268
|
+
Capacitor._logger.debug("의존성 변경 없음, workspace 플러그인 symlink만 갱신");
|
|
243
269
|
await this._linkWorkspacePlugins(workspacePlugins);
|
|
244
270
|
return false;
|
|
245
271
|
}
|
|
246
272
|
|
|
247
|
-
//
|
|
248
|
-
const
|
|
249
|
-
|
|
273
|
+
// pnpm-workspace.yaml 생성 (상위 workspace 탐색 차단)
|
|
274
|
+
const workspaceYamlPath = pathx.posixResolve(this._capPath, "pnpm-workspace.yaml");
|
|
275
|
+
if (!(await fsx.exists(workspaceYamlPath))) {
|
|
276
|
+
await fsx.write(workspaceYamlPath, "");
|
|
277
|
+
}
|
|
278
|
+
const lockfilePath = pathx.posixResolve(this._capPath, "pnpm-lock.yaml");
|
|
279
|
+
if (!(await fsx.exists(lockfilePath))) {
|
|
280
|
+
await fsx.write(lockfilePath, "");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// pnpm install + 빌드 스크립트 승인
|
|
284
|
+
Capacitor._logger.debug("pnpm install 시작");
|
|
285
|
+
await this._exec("pnpm", ["install"], this._capPath);
|
|
286
|
+
await this._exec("pnpm", ["approve-builds", "--all"], this._capPath);
|
|
287
|
+
Capacitor._logger.debug("pnpm install 완료");
|
|
250
288
|
|
|
251
289
|
// workspace 플러그인 symlink
|
|
290
|
+
Capacitor._logger.debug("workspace 플러그인 symlink 시작");
|
|
252
291
|
await this._linkWorkspacePlugins(workspacePlugins);
|
|
292
|
+
Capacitor._logger.debug("workspace 플러그인 symlink 완료");
|
|
253
293
|
|
|
254
294
|
// 멱등성: capacitor.config.ts가 없을 때만 cap init 실행
|
|
255
295
|
const configPath = pathx.posixResolve(this._capPath, "capacitor.config.ts");
|
|
256
296
|
if (!(await fsx.exists(configPath))) {
|
|
297
|
+
Capacitor._logger.debug("cap init 시작");
|
|
257
298
|
await this._execCap(["init", this._config.appId, this._config.appId]);
|
|
299
|
+
Capacitor._logger.debug("cap init 완료");
|
|
258
300
|
}
|
|
259
301
|
|
|
260
302
|
// 기본 www/index.html 생성
|
|
@@ -264,6 +306,7 @@ export class Capacitor {
|
|
|
264
306
|
pathx.posixResolve(wwwPath, "index.html"),
|
|
265
307
|
"<!DOCTYPE html><html><head></head><body></body></html>",
|
|
266
308
|
);
|
|
309
|
+
Capacitor._logger.debug("www/index.html 생성 완료");
|
|
267
310
|
|
|
268
311
|
return true;
|
|
269
312
|
}
|
|
@@ -465,8 +508,9 @@ export default config;
|
|
|
465
508
|
|
|
466
509
|
// capacitor-assets로 모든 해상도 아이콘/스플래시 생성
|
|
467
510
|
await this._exec(
|
|
468
|
-
"
|
|
511
|
+
"pnpm",
|
|
469
512
|
[
|
|
513
|
+
"exec",
|
|
470
514
|
"capacitor-assets",
|
|
471
515
|
"generate",
|
|
472
516
|
"--iconBackgroundColor",
|
|
@@ -500,10 +544,29 @@ export default config;
|
|
|
500
544
|
throw new Error(`Android 프로젝트 디렉토리를 찾을 수 없습니다: ${androidPath}`);
|
|
501
545
|
}
|
|
502
546
|
|
|
547
|
+
Capacitor._logger.debug("JAVA_HOME 설정 시작");
|
|
503
548
|
await this._configureAndroidJavaHomePath(androidPath);
|
|
549
|
+
Capacitor._logger.debug("JAVA_HOME 설정 완료");
|
|
550
|
+
|
|
551
|
+
Capacitor._logger.debug("Android SDK 경로 설정 시작");
|
|
504
552
|
await this._configureAndroidSdkPath(androidPath);
|
|
553
|
+
Capacitor._logger.debug("Android SDK 경로 설정 완료");
|
|
554
|
+
|
|
555
|
+
Capacitor._logger.debug("AndroidManifest.xml 설정 시작");
|
|
505
556
|
await this._configureAndroidManifest(androidPath);
|
|
557
|
+
Capacitor._logger.debug("AndroidManifest.xml 설정 완료");
|
|
558
|
+
|
|
559
|
+
Capacitor._logger.debug("루트 build.gradle Kotlin 플러그인 설정 시작");
|
|
560
|
+
await this._configureAndroidRootBuildGradle(androidPath);
|
|
561
|
+
Capacitor._logger.debug("루트 build.gradle Kotlin 플러그인 설정 완료");
|
|
562
|
+
|
|
563
|
+
Capacitor._logger.debug("build.gradle 설정 시작");
|
|
506
564
|
await this._configureAndroidBuildGradle(androidPath);
|
|
565
|
+
Capacitor._logger.debug("build.gradle 설정 완료");
|
|
566
|
+
|
|
567
|
+
Capacitor._logger.debug("styles.xml 설정 시작");
|
|
568
|
+
await this._configureAndroidStyles(androidPath);
|
|
569
|
+
Capacitor._logger.debug("styles.xml 설정 완료");
|
|
507
570
|
}
|
|
508
571
|
|
|
509
572
|
/**
|
|
@@ -574,7 +637,9 @@ export default config;
|
|
|
574
637
|
* Android SDK 경로 탐색
|
|
575
638
|
*/
|
|
576
639
|
private async _findAndroidSdk(): Promise<string | undefined> {
|
|
577
|
-
const androidHome =
|
|
640
|
+
const androidHome =
|
|
641
|
+
(env["ANDROID_HOME"] as string | undefined) ??
|
|
642
|
+
(env["ANDROID_SDK_ROOT"] as string | undefined);
|
|
578
643
|
if (androidHome != null && (await fsx.exists(androidHome))) {
|
|
579
644
|
return androidHome;
|
|
580
645
|
}
|
|
@@ -670,6 +735,28 @@ export default config;
|
|
|
670
735
|
await fsx.write(manifestPath, content);
|
|
671
736
|
}
|
|
672
737
|
|
|
738
|
+
/**
|
|
739
|
+
* 루트 build.gradle에 Kotlin Gradle 플러그인 classpath 추가
|
|
740
|
+
*/
|
|
741
|
+
private async _configureAndroidRootBuildGradle(androidPath: string): Promise<void> {
|
|
742
|
+
const rootBuildGradlePath = pathx.posixResolve(androidPath, "build.gradle");
|
|
743
|
+
|
|
744
|
+
if (!(await fsx.exists(rootBuildGradlePath))) {
|
|
745
|
+
Capacitor._logger.warn(`루트 build.gradle 파일을 찾을 수 없습니다: ${rootBuildGradlePath}`);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
let content = await fsx.read(rootBuildGradlePath);
|
|
750
|
+
|
|
751
|
+
if (!content.includes("kotlin-gradle-plugin")) {
|
|
752
|
+
content = content.replace(
|
|
753
|
+
/classpath 'com\.android\.tools\.build:gradle:[^']+'/,
|
|
754
|
+
`$&\n classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20'`,
|
|
755
|
+
);
|
|
756
|
+
await fsx.write(rootBuildGradlePath, content);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
673
760
|
/**
|
|
674
761
|
* build.gradle 수정 (서명 설정 제외)
|
|
675
762
|
*/
|
|
@@ -710,6 +797,35 @@ export default config;
|
|
|
710
797
|
await fsx.write(buildGradlePath, content);
|
|
711
798
|
}
|
|
712
799
|
|
|
800
|
+
/**
|
|
801
|
+
* styles.xml의 스플래시 테마 parent 변경
|
|
802
|
+
*
|
|
803
|
+
* Theme.SplashScreen은 android:windowBackground에 compat_splash_screen을 설정하여
|
|
804
|
+
* android:background(@drawable/splash)와 이중 표시를 발생시킨다.
|
|
805
|
+
* installSplashScreen()을 호출하지 않으므로 Theme.SplashScreen 기능이 불필요하다.
|
|
806
|
+
*/
|
|
807
|
+
private async _configureAndroidStyles(androidPath: string): Promise<void> {
|
|
808
|
+
const stylesPath = pathx.posixResolve(androidPath, "app/src/main/res/values/styles.xml");
|
|
809
|
+
|
|
810
|
+
if (!(await fsx.exists(stylesPath))) {
|
|
811
|
+
Capacitor._logger.warn(`styles.xml 파일을 찾을 수 없습니다: ${stylesPath}`);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
let content = await fsx.read(stylesPath);
|
|
816
|
+
|
|
817
|
+
if (!content.includes('parent="Theme.SplashScreen"')) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
content = content.replace(
|
|
822
|
+
'parent="Theme.SplashScreen"',
|
|
823
|
+
'parent="Theme.AppCompat.DayNight.NoActionBar"',
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
await fsx.write(stylesPath, content);
|
|
827
|
+
}
|
|
828
|
+
|
|
713
829
|
//#endregion
|
|
714
830
|
|
|
715
831
|
//#region Public — 기기 실행
|
|
@@ -719,28 +835,35 @@ export default config;
|
|
|
719
835
|
*
|
|
720
836
|
* 1. capacitor.config.ts에 server.url 설정 (Hot Reload용)
|
|
721
837
|
* 2. cap copy — 웹 에셋 동기화
|
|
722
|
-
* 3. cap run — 기기에서 앱 실행
|
|
838
|
+
* 3. cap run — 기기에서 앱 실행
|
|
723
839
|
*/
|
|
724
840
|
async run(url: string): Promise<void> {
|
|
841
|
+
Capacitor._logger.debug(`server.url 설정: ${url}`);
|
|
725
842
|
await this._updateServerUrl(url);
|
|
726
843
|
|
|
727
844
|
for (const platform of this._platforms) {
|
|
845
|
+
Capacitor._logger.debug(`[${platform}] cap copy 시작`);
|
|
728
846
|
await this._execCap(["copy", platform]);
|
|
847
|
+
Capacitor._logger.debug(`[${platform}] cap copy 완료`);
|
|
729
848
|
|
|
730
849
|
try {
|
|
850
|
+
Capacitor._logger.debug(`[${platform}] cap run 시작`);
|
|
731
851
|
await this._execCap(["run", platform]);
|
|
852
|
+
Capacitor._logger.debug(`[${platform}] cap run 완료`);
|
|
732
853
|
} catch (err) {
|
|
733
854
|
if (platform === "android") {
|
|
734
|
-
Capacitor._logger.
|
|
855
|
+
Capacitor._logger.debug(`[${platform}] adb kill-server 시작`);
|
|
735
856
|
try {
|
|
736
857
|
await this._exec("adb", ["kill-server"], this._capPath);
|
|
737
|
-
|
|
738
|
-
|
|
858
|
+
Capacitor._logger.debug(`[${platform}] adb kill-server 완료`);
|
|
859
|
+
} catch (adbErr) {
|
|
860
|
+
const adbErrMsg = adbErr instanceof Error ? adbErr.message : String(adbErr);
|
|
861
|
+
Capacitor._logger.debug(
|
|
862
|
+
`[${platform}] adb kill-server 실패 (무시): ${adbErrMsg}`,
|
|
863
|
+
);
|
|
739
864
|
}
|
|
740
|
-
await this._execCap(["run", platform]);
|
|
741
|
-
} else {
|
|
742
|
-
throw err;
|
|
743
865
|
}
|
|
866
|
+
throw err;
|
|
744
867
|
}
|
|
745
868
|
}
|
|
746
869
|
}
|
|
@@ -779,30 +902,40 @@ export default config;
|
|
|
779
902
|
* 4. 빌드 산출물 복사
|
|
780
903
|
*/
|
|
781
904
|
async build(outPath: string): Promise<void> {
|
|
905
|
+
Capacitor._logger.debug("build 시작");
|
|
906
|
+
|
|
782
907
|
// 1. 웹 에셋 동기화
|
|
908
|
+
Capacitor._logger.debug("cap copy 시작");
|
|
783
909
|
await this._execCap(["copy"]);
|
|
910
|
+
Capacitor._logger.debug("cap copy 완료");
|
|
784
911
|
|
|
785
912
|
// 2. 빌드 타입 결정
|
|
786
913
|
const isDebug = this._config.debug === true;
|
|
787
914
|
const isBundle = this._config.platform?.android?.bundle === true;
|
|
788
915
|
const buildType = isDebug ? "debug" : "release";
|
|
916
|
+
Capacitor._logger.debug(`빌드 타입: ${buildType}, bundle: ${isBundle}`);
|
|
789
917
|
|
|
790
918
|
// 3. 서명 설정
|
|
791
919
|
const signConfig = this._config.platform?.android?.sign;
|
|
792
920
|
if (!isDebug && signConfig != null) {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
);
|
|
921
|
+
Capacitor._logger.debug("서명 설정 시작");
|
|
922
|
+
await this._configureSigningConfig(pathx.posixResolve(this._capPath, "android"), signConfig);
|
|
923
|
+
Capacitor._logger.debug("서명 설정 완료");
|
|
797
924
|
} else if (!isDebug) {
|
|
798
925
|
Capacitor._logger.warn("서명 설정이 없어 unsigned 빌드가 생성됩니다.");
|
|
799
926
|
}
|
|
800
927
|
|
|
801
928
|
// 4. Gradle 빌드
|
|
929
|
+
Capacitor._logger.debug("Gradle 빌드 시작");
|
|
802
930
|
await this._buildAndroid(buildType, isBundle);
|
|
931
|
+
Capacitor._logger.debug("Gradle 빌드 완료");
|
|
803
932
|
|
|
804
933
|
// 5. 빌드 산출물 복사
|
|
934
|
+
Capacitor._logger.debug("빌드 산출물 복사 시작");
|
|
805
935
|
await this._copyBuildOutput(outPath, buildType, isBundle);
|
|
936
|
+
Capacitor._logger.debug("빌드 산출물 복사 완료");
|
|
937
|
+
|
|
938
|
+
Capacitor._logger.debug("build 완료");
|
|
806
939
|
}
|
|
807
940
|
|
|
808
941
|
//#endregion
|
|
@@ -878,6 +1011,7 @@ export default config;
|
|
|
878
1011
|
? pathx.posixResolve(androidPath, "gradlew.bat")
|
|
879
1012
|
: pathx.posixResolve(androidPath, "gradlew");
|
|
880
1013
|
|
|
1014
|
+
Capacitor._logger.debug(`Gradle 실행: ${gradlew} ${gradleTask}`);
|
|
881
1015
|
await this._exec(gradlew, [gradleTask, "--no-daemon"], androidPath);
|
|
882
1016
|
}
|
|
883
1017
|
|
|
@@ -899,11 +1033,13 @@ export default config;
|
|
|
899
1033
|
);
|
|
900
1034
|
|
|
901
1035
|
// 빌드 산출물 찾기
|
|
1036
|
+
Capacitor._logger.debug(`빌드 산출물 탐색: ${androidBuildPath}`);
|
|
902
1037
|
const candidates = await fsx.glob(pathx.posixResolve(androidBuildPath, `app-*.${ext}`));
|
|
903
1038
|
if (candidates.length === 0) {
|
|
904
1039
|
throw new Error(`빌드 산출물을 찾을 수 없습니다: ${androidBuildPath}`);
|
|
905
1040
|
}
|
|
906
1041
|
const builtFile = candidates[0];
|
|
1042
|
+
Capacitor._logger.debug(`빌드 산출물: ${builtFile}`);
|
|
907
1043
|
const isUnsigned = builtFile.includes("unsigned");
|
|
908
1044
|
|
|
909
1045
|
// 출력 디렉토리 생성
|
package/src/commands/build.ts
CHANGED
|
@@ -4,17 +4,10 @@ import {
|
|
|
4
4
|
} from "../orchestrators/BuildOrchestrator";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* BuildOrchestrator를 통해 프로덕션 빌드를 실행한다.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* - Clean dist folder (clean build)
|
|
12
|
-
* - `node`/`browser`/`neutral` target: esbuild JS build + dts generation (with type check)
|
|
13
|
-
* - `client` target: Vite production build + typecheck (dts not needed)
|
|
14
|
-
* - Set `process.exitCode = 1` if any step fails
|
|
15
|
-
*
|
|
16
|
-
* @param options - build execution options
|
|
17
|
-
* @returns resolves on completion
|
|
9
|
+
* @param options - 빌드 실행 옵션
|
|
10
|
+
* @returns 완료 시 resolve
|
|
18
11
|
*/
|
|
19
12
|
export async function runBuild(options: BuildOrchestratorOptions): Promise<void> {
|
|
20
13
|
const orchestrator = new BuildOrchestrator(options);
|
package/src/commands/check.ts
CHANGED
|
@@ -34,7 +34,7 @@ async function spawnVitest(targets: string[]): Promise<CheckResult> {
|
|
|
34
34
|
const args = ["vitest", ...targets, "--run"];
|
|
35
35
|
logger.debug("vitest 실행", { args });
|
|
36
36
|
logger.start("테스트 실행 중...");
|
|
37
|
-
const result = await cpx.
|
|
37
|
+
const result = await cpx.spawn("pnpm", args, { cwd: process.cwd(), reject: false });
|
|
38
38
|
const output = result.stdout + result.stderr;
|
|
39
39
|
const code = result.exitCode;
|
|
40
40
|
|
|
@@ -188,7 +188,7 @@ export async function runCheck(options: CheckOptions): Promise<void> {
|
|
|
188
188
|
const results = await Promise.allSettled(tasks);
|
|
189
189
|
logger.success("체크 실행 완료");
|
|
190
190
|
|
|
191
|
-
// 결과 수집 (
|
|
191
|
+
// 결과 수집 (executeTypecheck 배열 평탄화)
|
|
192
192
|
const checkResults: CheckResult[] = results.flatMap((r) => {
|
|
193
193
|
if (r.status === "fulfilled") {
|
|
194
194
|
const value = r.value;
|
|
@@ -211,7 +211,7 @@ export async function runCheck(options: CheckOptions): Promise<void> {
|
|
|
211
211
|
process.stdout.write(formatSection(result));
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
//
|
|
214
|
+
// 요약
|
|
215
215
|
const failed = checkResults.filter((r) => !r.success);
|
|
216
216
|
const totalErrors = checkResults.reduce((sum, r) => sum + r.errorCount, 0);
|
|
217
217
|
const totalWarnings = checkResults.reduce((sum, r) => sum + r.warningCount, 0);
|