@simplysm/sd-cli 14.0.16 → 14.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/README.md +2 -1
  2. package/dist/angular/client-transform-stylesheet.d.ts +2 -0
  3. package/dist/angular/client-transform-stylesheet.d.ts.map +1 -1
  4. package/dist/angular/client-transform-stylesheet.js +88 -2
  5. package/dist/angular/client-transform-stylesheet.js.map +1 -1
  6. package/dist/angular/vite-angular-plugin.d.ts +7 -0
  7. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  8. package/dist/angular/vite-angular-plugin.js +78 -16
  9. package/dist/angular/vite-angular-plugin.js.map +1 -1
  10. package/dist/capacitor/capacitor.d.ts.map +1 -1
  11. package/dist/capacitor/capacitor.js +9 -13
  12. package/dist/capacitor/capacitor.js.map +1 -1
  13. package/dist/commands/check.d.ts.map +1 -1
  14. package/dist/commands/check.js +8 -9
  15. package/dist/commands/check.js.map +1 -1
  16. package/dist/commands/device.d.ts.map +1 -1
  17. package/dist/commands/device.js +33 -1
  18. package/dist/commands/device.js.map +1 -1
  19. package/dist/commands/lint.d.ts +0 -1
  20. package/dist/commands/lint.d.ts.map +1 -1
  21. package/dist/commands/lint.js +2 -3
  22. package/dist/commands/lint.js.map +1 -1
  23. package/dist/commands/publish.js +2 -2
  24. package/dist/commands/publish.js.map +1 -1
  25. package/dist/commands/typecheck.d.ts.map +1 -1
  26. package/dist/commands/typecheck.js +0 -1
  27. package/dist/commands/typecheck.js.map +1 -1
  28. package/dist/electron/electron.d.ts +3 -2
  29. package/dist/electron/electron.d.ts.map +1 -1
  30. package/dist/electron/electron.js +54 -31
  31. package/dist/electron/electron.js.map +1 -1
  32. package/dist/engines/BaseEngine.js +1 -1
  33. package/dist/engines/BaseEngine.js.map +1 -1
  34. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  35. package/dist/engines/NgtscEngine.js +0 -1
  36. package/dist/engines/NgtscEngine.js.map +1 -1
  37. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
  38. package/dist/engines/ServerEsbuildEngine.js +0 -1
  39. package/dist/engines/ServerEsbuildEngine.js.map +1 -1
  40. package/dist/engines/TscEngine.d.ts.map +1 -1
  41. package/dist/engines/TscEngine.js +0 -1
  42. package/dist/engines/TscEngine.js.map +1 -1
  43. package/dist/engines/ViteEngine.d.ts.map +1 -1
  44. package/dist/engines/ViteEngine.js +8 -1
  45. package/dist/engines/ViteEngine.js.map +1 -1
  46. package/dist/engines/index.d.ts +0 -10
  47. package/dist/engines/index.d.ts.map +1 -1
  48. package/dist/engines/index.js +0 -5
  49. package/dist/engines/index.js.map +1 -1
  50. package/dist/engines/types.d.ts +0 -1
  51. package/dist/engines/types.d.ts.map +1 -1
  52. package/dist/infra/SignalHandler.d.ts +1 -6
  53. package/dist/infra/SignalHandler.d.ts.map +1 -1
  54. package/dist/infra/SignalHandler.js +4 -13
  55. package/dist/infra/SignalHandler.js.map +1 -1
  56. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  57. package/dist/orchestrators/BuildOrchestrator.js +7 -12
  58. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  59. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  60. package/dist/orchestrators/DevWatchOrchestrator.js +17 -10
  61. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  62. package/dist/sd-cli-entry.d.ts +0 -1
  63. package/dist/sd-cli-entry.d.ts.map +1 -1
  64. package/dist/sd-cli-entry.js +7 -8
  65. package/dist/sd-cli-entry.js.map +1 -1
  66. package/dist/sd-config.types.d.ts +11 -1
  67. package/dist/sd-config.types.d.ts.map +1 -1
  68. package/dist/utils/angular-compiler.d.ts.map +1 -1
  69. package/dist/utils/angular-compiler.js +20 -13
  70. package/dist/utils/angular-compiler.js.map +1 -1
  71. package/dist/utils/esbuild-config.d.ts +1 -1
  72. package/dist/utils/esbuild-config.d.ts.map +1 -1
  73. package/dist/utils/esbuild-config.js +1 -4
  74. package/dist/utils/esbuild-config.js.map +1 -1
  75. package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
  76. package/dist/utils/ngtsc-build-core.js +3 -0
  77. package/dist/utils/ngtsc-build-core.js.map +1 -1
  78. package/dist/utils/tsc-build.d.ts +5 -0
  79. package/dist/utils/tsc-build.d.ts.map +1 -1
  80. package/dist/utils/tsc-build.js +2 -1
  81. package/dist/utils/tsc-build.js.map +1 -1
  82. package/dist/utils/vite-config.d.ts +1 -1
  83. package/dist/utils/vite-config.d.ts.map +1 -1
  84. package/dist/utils/vite-config.js +22 -53
  85. package/dist/utils/vite-config.js.map +1 -1
  86. package/dist/utils/vite-pwa-plugin.d.ts +9 -0
  87. package/dist/utils/vite-pwa-plugin.d.ts.map +1 -0
  88. package/dist/utils/vite-pwa-plugin.js +139 -0
  89. package/dist/utils/vite-pwa-plugin.js.map +1 -0
  90. package/dist/utils/worker-utils.d.ts +2 -5
  91. package/dist/utils/worker-utils.d.ts.map +1 -1
  92. package/dist/utils/worker-utils.js +5 -11
  93. package/dist/utils/worker-utils.js.map +1 -1
  94. package/dist/workers/client.worker.d.ts.map +1 -1
  95. package/dist/workers/client.worker.js +9 -3
  96. package/dist/workers/client.worker.js.map +1 -1
  97. package/dist/workers/library-build.worker.d.ts.map +1 -1
  98. package/dist/workers/library-build.worker.js +6 -2
  99. package/dist/workers/library-build.worker.js.map +1 -1
  100. package/dist/workers/ngtsc-build.worker.js +2 -2
  101. package/dist/workers/ngtsc-build.worker.js.map +1 -1
  102. package/dist/workers/server-build.worker.d.ts.map +1 -1
  103. package/dist/workers/server-build.worker.js +6 -2
  104. package/dist/workers/server-build.worker.js.map +1 -1
  105. package/dist/workers/server-runtime.worker.js +4 -4
  106. package/dist/workers/server-runtime.worker.js.map +1 -1
  107. package/docs/config.md +26 -0
  108. package/docs/pwa-configuration-types.md +1 -1
  109. package/package.json +8 -10
  110. package/src/angular/client-transform-stylesheet.ts +104 -2
  111. package/src/angular/vite-angular-plugin.ts +92 -31
  112. package/src/capacitor/capacitor.ts +10 -26
  113. package/src/commands/check.ts +8 -11
  114. package/src/commands/device.ts +38 -3
  115. package/src/commands/lint.ts +2 -3
  116. package/src/commands/publish.ts +2 -2
  117. package/src/commands/typecheck.ts +0 -1
  118. package/src/electron/electron.ts +62 -43
  119. package/src/engines/BaseEngine.ts +1 -1
  120. package/src/engines/NgtscEngine.ts +0 -1
  121. package/src/engines/ServerEsbuildEngine.ts +0 -1
  122. package/src/engines/TscEngine.ts +0 -1
  123. package/src/engines/ViteEngine.ts +7 -1
  124. package/src/engines/index.ts +0 -10
  125. package/src/engines/types.ts +0 -1
  126. package/src/infra/SignalHandler.ts +4 -14
  127. package/src/orchestrators/BuildOrchestrator.ts +7 -9
  128. package/src/orchestrators/DevWatchOrchestrator.ts +21 -9
  129. package/src/sd-cli-entry.ts +11 -16
  130. package/src/sd-config.types.ts +12 -1
  131. package/src/utils/angular-compiler.ts +21 -21
  132. package/src/utils/esbuild-config.ts +2 -5
  133. package/src/utils/ngtsc-build-core.ts +7 -0
  134. package/src/utils/tsc-build.ts +7 -0
  135. package/src/utils/vite-config.ts +23 -55
  136. package/src/utils/vite-pwa-plugin.ts +168 -0
  137. package/src/utils/worker-utils.ts +5 -11
  138. package/src/workers/client.worker.ts +11 -3
  139. package/src/workers/library-build.worker.ts +6 -2
  140. package/src/workers/ngtsc-build.worker.ts +2 -2
  141. package/src/workers/server-build.worker.ts +7 -2
  142. package/src/workers/server-runtime.worker.ts +4 -4
  143. package/tests/angular/client-transform-stylesheet.spec.ts +43 -0
  144. package/tests/angular/find-affected-by-scss.spec.ts +37 -0
  145. package/tests/angular/fixtures/basic-app/scss/_colors.scss +1 -0
  146. package/tests/angular/fixtures/basic-app/scss/_variables.scss +3 -0
  147. package/tests/angular/fixtures/basic-app/src/styled.component.ts +14 -0
  148. package/tests/angular/linker-disk-cache.spec.ts +158 -0
  149. package/tests/angular/scss-disk-cache.spec.ts +162 -0
  150. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +15 -15
  151. package/tests/angular/vite-angular-plugin-hmr.spec.ts +9 -9
  152. package/tests/angular/vite-angular-plugin-lint.spec.ts +4 -4
  153. package/tests/angular/vite-angular-plugin-scss-hmr.spec.ts +87 -0
  154. package/tests/angular/vite-angular-plugin.spec.ts +15 -15
  155. package/tests/capacitor/capacitor-icon.spec.ts +2 -4
  156. package/tests/capacitor/capacitor-init.spec.ts +2 -4
  157. package/tests/capacitor/capacitor-workspace.spec.ts +2 -4
  158. package/tests/commands/device.spec.ts +100 -0
  159. package/tests/electron/electron.spec.ts +24 -17
  160. package/tests/engines/ngtsc-engine.spec.ts +0 -3
  161. package/tests/engines/server-esbuild-engine.spec.ts +0 -3
  162. package/tests/engines/tsc-engine.spec.ts +1 -2
  163. package/tests/engines/vite-engine.spec.ts +0 -2
  164. package/tests/infra/signal-handler.spec.ts +1 -12
  165. package/tests/orchestrators/build-orchestrator.spec.ts +0 -6
  166. package/tests/orchestrators/dev-watch-orchestrator.spec.ts +24 -66
  167. package/tests/utils/angular-compiler.spec.ts +1396 -32
  168. package/tests/utils/esbuild-config.spec.ts +4 -7
  169. package/tests/utils/{ngtsc-build-core-angular-compiler.spec.ts → ngtsc-build-core.spec.ts} +142 -11
  170. package/tests/utils/tsc-build.spec.ts +4 -1
  171. package/tests/utils/vite-config.spec.ts +130 -261
  172. package/tests/utils/vite-pwa-plugin.acc.spec.ts +143 -0
  173. package/tests/utils/vite-pwa-plugin.spec.ts +350 -0
  174. package/tests/utils/worker-utils.spec.ts +8 -7
  175. package/tests/workers/client-worker.spec.ts +50 -1
  176. package/tests/workers/dev-port-file.verify.md +6 -0
  177. package/tests/workers/library-build-lint.spec.ts +1 -1
  178. package/tests/workers/library-build-worker.spec.ts +1 -1
  179. package/tests/workers/ngtsc-build-lint.spec.ts +1 -1
  180. package/tests/workers/server-build-lint.spec.ts +1 -1
  181. package/tests/workers/server-build-worker.spec.ts +1 -1
  182. package/tests/workers/server-runtime-worker.spec.ts +8 -1
  183. package/dist/infra/WorkerManager.d.ts +0 -40
  184. package/dist/infra/WorkerManager.d.ts.map +0 -1
  185. package/dist/infra/WorkerManager.js +0 -59
  186. package/dist/infra/WorkerManager.js.map +0 -1
  187. package/dist/utils/SdCliReporter.d.ts +0 -18
  188. package/dist/utils/SdCliReporter.d.ts.map +0 -1
  189. package/dist/utils/SdCliReporter.js +0 -144
  190. package/dist/utils/SdCliReporter.js.map +0 -1
  191. package/src/infra/WorkerManager.ts +0 -65
  192. package/src/utils/SdCliReporter.ts +0 -177
  193. package/tests/angular/scss-compiler-async.spec.ts +0 -54
  194. package/tests/commands/dev.spec.ts +0 -53
  195. package/tests/commands/watch.spec.ts +0 -53
  196. package/tests/infra/worker-manager.spec.ts +0 -63
  197. package/tests/utils/angular-compiler-emit.spec.ts +0 -570
  198. package/tests/utils/angular-compiler-init.spec.ts +0 -705
  199. package/tests/utils/angular-compiler-update.spec.ts +0 -293
  200. package/tests/utils/build-env.spec.ts +0 -33
  201. package/tests/utils/ngtsc-build-core-transform-stylesheet.spec.ts +0 -124
  202. package/tests/utils/ngtsc-scss-refactor.spec.ts +0 -47
@@ -1,40 +0,0 @@
1
- import { type WorkerProxy, type WorkerModule } from "@simplysm/core-node";
2
- /**
3
- * Worker 생명주기를 관리하는 클래스
4
- *
5
- * Worker 생성, 조회, 종료를 중앙에서 관리하여
6
- * 리소스 누수를 방지하고 일관된 Worker 관리를 제공한다.
7
- */
8
- export declare class WorkerManager {
9
- private readonly _workers;
10
- /**
11
- * 새 Worker를 생성한다
12
- * @param id Worker 식별자 (예: "core-common:build")
13
- * @param workerPath Worker 파일 경로
14
- * @returns 생성된 WorkerProxy
15
- */
16
- create<TModule extends WorkerModule>(id: string, workerPath: string): WorkerProxy<TModule>;
17
- /**
18
- * ID로 Worker를 조회한다
19
- * @param id Worker 식별자
20
- */
21
- get<TModule extends WorkerModule>(id: string): WorkerProxy<TModule> | undefined;
22
- /**
23
- * 특정 Worker를 종료하고 제거한다
24
- * @param id Worker 식별자
25
- */
26
- terminate(id: string): Promise<void>;
27
- /**
28
- * 모든 Worker를 종료한다
29
- */
30
- terminateAll(): Promise<void>;
31
- /**
32
- * 관리 중인 Worker 수
33
- */
34
- get size(): number;
35
- /**
36
- * 모든 Worker ID 목록
37
- */
38
- get ids(): string[];
39
- }
40
- //# sourceMappingURL=WorkerManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WorkerManager.d.ts","sourceRoot":"","sources":["../../src/infra/WorkerManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAElF;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgD;IAEzE;;;;;OAKG;IACH,MAAM,CAAC,OAAO,SAAS,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC;IAM1F;;;OAGG;IACH,GAAG,CAAC,OAAO,SAAS,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS;IAI/E;;;OAGG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1C;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAKnC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,EAAE,CAElB;CACF"}
@@ -1,59 +0,0 @@
1
- import { Worker } from "@simplysm/core-node";
2
- /**
3
- * Worker 생명주기를 관리하는 클래스
4
- *
5
- * Worker 생성, 조회, 종료를 중앙에서 관리하여
6
- * 리소스 누수를 방지하고 일관된 Worker 관리를 제공한다.
7
- */
8
- export class WorkerManager {
9
- _workers = new Map();
10
- /**
11
- * 새 Worker를 생성한다
12
- * @param id Worker 식별자 (예: "core-common:build")
13
- * @param workerPath Worker 파일 경로
14
- * @returns 생성된 WorkerProxy
15
- */
16
- create(id, workerPath) {
17
- const worker = Worker.create(workerPath);
18
- this._workers.set(id, worker);
19
- return worker;
20
- }
21
- /**
22
- * ID로 Worker를 조회한다
23
- * @param id Worker 식별자
24
- */
25
- get(id) {
26
- return this._workers.get(id);
27
- }
28
- /**
29
- * 특정 Worker를 종료하고 제거한다
30
- * @param id Worker 식별자
31
- */
32
- async terminate(id) {
33
- const worker = this._workers.get(id);
34
- if (worker != null) {
35
- await worker.terminate();
36
- this._workers.delete(id);
37
- }
38
- }
39
- /**
40
- * 모든 Worker를 종료한다
41
- */
42
- async terminateAll() {
43
- await Promise.all([...this._workers.values()].map((w) => w.terminate()));
44
- this._workers.clear();
45
- }
46
- /**
47
- * 관리 중인 Worker 수
48
- */
49
- get size() {
50
- return this._workers.size;
51
- }
52
- /**
53
- * 모든 Worker ID 목록
54
- */
55
- get ids() {
56
- return [...this._workers.keys()];
57
- }
58
- }
59
- //# sourceMappingURL=WorkerManager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WorkerManager.js","sourceRoot":"","sources":["../../src/infra/WorkerManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAuC,MAAM,qBAAqB,CAAC;AAElF;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACP,QAAQ,GAAG,IAAI,GAAG,EAAqC,CAAC;IAEzE;;;;;OAKG;IACH,MAAM,CAA+B,EAAU,EAAE,UAAkB;QACjE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAU,UAAU,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,MAAmC,CAAC,CAAC;QAC3D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,GAAG,CAA+B,EAAU;QAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAqC,CAAC;IACnE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,IAAI,GAAG;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;CACF"}
@@ -1,18 +0,0 @@
1
- import type { ConsolaReporter, LogObject, ConsolaOptions } from "consola";
2
- /**
3
- * sd-cli 전용 consola reporter.
4
- * 모든 로그를 `[tag] icon message time` 형식으로 통일한다.
5
- */
6
- export declare class SdCliReporter implements ConsolaReporter {
7
- log(logObj: LogObject, ctx: {
8
- options: ConsolaOptions;
9
- }): void;
10
- private _formatLogObj;
11
- private _formatArgs;
12
- private _formatError;
13
- private _formatStack;
14
- private _formatIcon;
15
- private _formatDate;
16
- private _formatBox;
17
- }
18
- //# sourceMappingURL=SdCliReporter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SdCliReporter.d.ts","sourceRoot":"","sources":["../../src/utils/SdCliReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA4E1E;;;GAGG;AACH,qBAAa,aAAc,YAAW,eAAe;IACnD,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE;QAAE,OAAO,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI;IAe9D,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,UAAU;CAMnB"}
@@ -1,144 +0,0 @@
1
- import { formatWithOptions } from "node:util";
2
- import { sep } from "node:path";
3
- // -- Constants ----------------------------------------------------------------
4
- const TYPE_ICONS = {
5
- error: "✖",
6
- fatal: "✖",
7
- ready: "✔",
8
- warn: "⚠",
9
- info: "ℹ",
10
- success: "✔",
11
- debug: "⚙",
12
- trace: "→",
13
- fail: "✖",
14
- start: "◐",
15
- log: "",
16
- };
17
- const TYPE_COLORS = {
18
- info: "cyan",
19
- fail: "red",
20
- success: "green",
21
- ready: "green",
22
- start: "magenta",
23
- };
24
- const LEVEL_COLORS = {
25
- 0: "red",
26
- 1: "yellow",
27
- };
28
- const ANSI_CODES = {
29
- gray: "\x1b[90m",
30
- red: "\x1b[31m",
31
- green: "\x1b[32m",
32
- yellow: "\x1b[33m",
33
- cyan: "\x1b[36m",
34
- magenta: "\x1b[35m",
35
- };
36
- const ANSI_RESET = "\x1b[0m";
37
- // -- Helpers ------------------------------------------------------------------
38
- function colorize(color, text, enabled) {
39
- if (!enabled)
40
- return text;
41
- return `${ANSI_CODES[color]}${text}${ANSI_RESET}`;
42
- }
43
- function writeStream(data, stream) {
44
- const s = stream;
45
- const write = s.__write ?? s.write;
46
- write.call(stream, data);
47
- }
48
- function detectColorSupport() {
49
- if (process.env["NO_COLOR"] != null)
50
- return false;
51
- if (process.env["FORCE_COLOR"] != null)
52
- return true;
53
- if (process.stdout.isTTY === true)
54
- return true;
55
- // 워커 스레드에서는 process.stdout.isTTY가 없음. Windows 터미널은 ANSI 지원.
56
- return process.platform === "win32";
57
- }
58
- /**
59
- * sd-cli 전용 consola reporter.
60
- * 모든 로그를 `[tag] icon message time` 형식으로 통일한다.
61
- */
62
- export class SdCliReporter {
63
- log(logObj, ctx) {
64
- const opts = {
65
- ...ctx.options.formatOptions,
66
- colors: detectColorSupport(),
67
- };
68
- const line = this._formatLogObj(logObj, opts);
69
- const stream = logObj.level < 2
70
- ? ctx.options.stderr ?? process.stderr
71
- : ctx.options.stdout ?? process.stdout;
72
- writeStream(line + "\n", stream);
73
- }
74
- _formatLogObj(logObj, opts) {
75
- const formattedArgs = this._formatArgs(logObj.args, opts);
76
- const [message, ...additional] = formattedArgs.split("\n");
77
- if (logObj.type === "box") {
78
- return this._formatBox(logObj, formattedArgs);
79
- }
80
- // Build: [tag] icon message time
81
- const tag = logObj.tag !== "" ? colorize("gray", `[${logObj.tag}]`, opts.colors) : "";
82
- const icon = this._formatIcon(logObj, opts.colors);
83
- const date = this._formatDate(logObj.date, opts);
84
- const coloredDate = date !== "" ? colorize("gray", date, opts.colors) : "";
85
- let fullLine = [tag, icon, message, coloredDate].filter(Boolean).join(" ");
86
- if (additional.length > 0) {
87
- fullLine += "\n" + additional.join("\n");
88
- }
89
- if (logObj.type === "trace") {
90
- const err = new Error("Trace: " + logObj.message);
91
- fullLine += this._formatStack(err.stack ?? "", err.message);
92
- }
93
- const isBadge = logObj.badge ?? logObj.level < 2;
94
- return isBadge ? "\n" + fullLine + "\n" : fullLine;
95
- }
96
- _formatArgs(args, opts) {
97
- const processed = args.map((arg) => {
98
- if (arg != null && typeof arg === "object" && typeof arg.stack === "string") {
99
- return this._formatError(arg, opts);
100
- }
101
- return arg;
102
- });
103
- return formatWithOptions({ colors: opts.colors, compact: opts.compact }, ...processed);
104
- }
105
- _formatError(err, opts) {
106
- const message = err.message;
107
- const stack = err.stack != null ? this._formatStack(err.stack, message, opts) : "";
108
- const level = opts.errorLevel ?? 0;
109
- const prefix = level > 0 ? `${" ".repeat(level)}[cause]: ` : "";
110
- const cause = err.cause instanceof Error
111
- ? "\n\n" + this._formatError(err.cause, { ...opts, errorLevel: level + 1 })
112
- : "";
113
- return prefix + message + "\n" + stack + cause;
114
- }
115
- _formatStack(stack, message, opts) {
116
- const cwd = process.cwd() + sep;
117
- const indent = " ".repeat((opts?.errorLevel ?? 0) + 1);
118
- const lines = stack
119
- .split("\n")
120
- .splice(message.split("\n").length)
121
- .map((l) => l.trim().replace("file://", "").replace(cwd, ""));
122
- return `\n${indent}` + lines.map((l) => ` ${l}`).join(`\n${indent}`);
123
- }
124
- _formatIcon(logObj, useColors) {
125
- const icon = TYPE_ICONS[logObj.type] ?? "";
126
- if (icon === "")
127
- return "";
128
- const color = TYPE_COLORS[logObj.type] ?? LEVEL_COLORS[logObj.level] ?? "gray";
129
- return colorize(color, icon, useColors);
130
- }
131
- _formatDate(date, opts) {
132
- if (!opts.date)
133
- return "";
134
- const base = date.toLocaleTimeString();
135
- return `${base}.${String(date.getMilliseconds()).padStart(3, "0")}`;
136
- }
137
- _formatBox(logObj, message) {
138
- const tag = logObj.tag !== "" ? `[${logObj.tag}]` : "";
139
- const title = logObj.title;
140
- const lines = [tag, title, ...message.split("\n")].filter(Boolean);
141
- return "\n" + lines.map((l) => ` > ${l}`).join("\n") + "\n";
142
- }
143
- }
144
- //# sourceMappingURL=SdCliReporter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SdCliReporter.js","sourceRoot":"","sources":["../../src/utils/SdCliReporter.ts"],"names":[],"mappings":"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"}
@@ -1,65 +0,0 @@
1
- import { Worker, type WorkerProxy, type WorkerModule } from "@simplysm/core-node";
2
-
3
- /**
4
- * Worker 생명주기를 관리하는 클래스
5
- *
6
- * Worker 생성, 조회, 종료를 중앙에서 관리하여
7
- * 리소스 누수를 방지하고 일관된 Worker 관리를 제공한다.
8
- */
9
- export class WorkerManager {
10
- private readonly _workers = new Map<string, WorkerProxy<WorkerModule>>();
11
-
12
- /**
13
- * 새 Worker를 생성한다
14
- * @param id Worker 식별자 (예: "core-common:build")
15
- * @param workerPath Worker 파일 경로
16
- * @returns 생성된 WorkerProxy
17
- */
18
- create<TModule extends WorkerModule>(id: string, workerPath: string): WorkerProxy<TModule> {
19
- const worker = Worker.create<TModule>(workerPath);
20
- this._workers.set(id, worker as WorkerProxy<WorkerModule>);
21
- return worker;
22
- }
23
-
24
- /**
25
- * ID로 Worker를 조회한다
26
- * @param id Worker 식별자
27
- */
28
- get<TModule extends WorkerModule>(id: string): WorkerProxy<TModule> | undefined {
29
- return this._workers.get(id) as WorkerProxy<TModule> | undefined;
30
- }
31
-
32
- /**
33
- * 특정 Worker를 종료하고 제거한다
34
- * @param id Worker 식별자
35
- */
36
- async terminate(id: string): Promise<void> {
37
- const worker = this._workers.get(id);
38
- if (worker != null) {
39
- await worker.terminate();
40
- this._workers.delete(id);
41
- }
42
- }
43
-
44
- /**
45
- * 모든 Worker를 종료한다
46
- */
47
- async terminateAll(): Promise<void> {
48
- await Promise.all([...this._workers.values()].map((w) => w.terminate()));
49
- this._workers.clear();
50
- }
51
-
52
- /**
53
- * 관리 중인 Worker 수
54
- */
55
- get size(): number {
56
- return this._workers.size;
57
- }
58
-
59
- /**
60
- * 모든 Worker ID 목록
61
- */
62
- get ids(): string[] {
63
- return [...this._workers.keys()];
64
- }
65
- }
@@ -1,177 +0,0 @@
1
- import type { ConsolaReporter, LogObject, ConsolaOptions } from "consola";
2
- import { formatWithOptions } from "node:util";
3
- import { sep } from "node:path";
4
-
5
- // -- Constants ----------------------------------------------------------------
6
-
7
- const TYPE_ICONS: Record<string, string> = {
8
- error: "✖",
9
- fatal: "✖",
10
- ready: "✔",
11
- warn: "⚠",
12
- info: "ℹ",
13
- success: "✔",
14
- debug: "⚙",
15
- trace: "→",
16
- fail: "✖",
17
- start: "◐",
18
- log: "",
19
- };
20
-
21
- type AnsiColor = "gray" | "red" | "green" | "yellow" | "cyan" | "magenta";
22
-
23
- const TYPE_COLORS: Record<string, AnsiColor | undefined> = {
24
- info: "cyan",
25
- fail: "red",
26
- success: "green",
27
- ready: "green",
28
- start: "magenta",
29
- };
30
-
31
- const LEVEL_COLORS: Record<number, AnsiColor | undefined> = {
32
- 0: "red",
33
- 1: "yellow",
34
- };
35
-
36
- const ANSI_CODES: Record<AnsiColor, string> = {
37
- gray: "\x1b[90m",
38
- red: "\x1b[31m",
39
- green: "\x1b[32m",
40
- yellow: "\x1b[33m",
41
- cyan: "\x1b[36m",
42
- magenta: "\x1b[35m",
43
- };
44
-
45
- const ANSI_RESET = "\x1b[0m";
46
-
47
- // -- Helpers ------------------------------------------------------------------
48
-
49
- function colorize(color: AnsiColor, text: string, enabled: boolean): string {
50
- if (!enabled) return text;
51
- return `${ANSI_CODES[color]}${text}${ANSI_RESET}`;
52
- }
53
-
54
- function writeStream(data: string, stream: NodeJS.WritableStream): void {
55
- const s = stream as NodeJS.WritableStream & { __write?: typeof stream.write };
56
- const write = s.__write ?? s.write;
57
- write.call(stream, data);
58
- }
59
-
60
- function detectColorSupport(): boolean {
61
- if (process.env["NO_COLOR"] != null) return false;
62
- if (process.env["FORCE_COLOR"] != null) return true;
63
- if (process.stdout.isTTY === true) return true;
64
- // 워커 스레드에서는 process.stdout.isTTY가 없음. Windows 터미널은 ANSI 지원.
65
- return process.platform === "win32";
66
- }
67
-
68
- // -- Reporter -----------------------------------------------------------------
69
-
70
- interface FormatOpts {
71
- date?: boolean;
72
- colors: boolean;
73
- compact?: boolean | number;
74
- errorLevel?: number;
75
- }
76
-
77
- /**
78
- * sd-cli 전용 consola reporter.
79
- * 모든 로그를 `[tag] icon message time` 형식으로 통일한다.
80
- */
81
- export class SdCliReporter implements ConsolaReporter {
82
- log(logObj: LogObject, ctx: { options: ConsolaOptions }): void {
83
- const opts: FormatOpts = {
84
- ...ctx.options.formatOptions,
85
- colors: detectColorSupport(),
86
- };
87
-
88
- const line = this._formatLogObj(logObj, opts);
89
- const stream =
90
- logObj.level < 2
91
- ? ctx.options.stderr ?? process.stderr
92
- : ctx.options.stdout ?? process.stdout;
93
-
94
- writeStream(line + "\n", stream);
95
- }
96
-
97
- private _formatLogObj(logObj: LogObject, opts: FormatOpts): string {
98
- const formattedArgs = this._formatArgs(logObj.args, opts);
99
- const [message, ...additional] = formattedArgs.split("\n");
100
-
101
- if (logObj.type === "box") {
102
- return this._formatBox(logObj, formattedArgs);
103
- }
104
-
105
- // Build: [tag] icon message time
106
- const tag = logObj.tag !== "" ? colorize("gray", `[${logObj.tag}]`, opts.colors) : "";
107
- const icon = this._formatIcon(logObj, opts.colors);
108
- const date = this._formatDate(logObj.date, opts);
109
- const coloredDate = date !== "" ? colorize("gray", date, opts.colors) : "";
110
-
111
- let fullLine = [tag, icon, message, coloredDate].filter(Boolean).join(" ");
112
-
113
- if (additional.length > 0) {
114
- fullLine += "\n" + additional.join("\n");
115
- }
116
-
117
- if (logObj.type === "trace") {
118
- const err = new Error("Trace: " + logObj.message);
119
- fullLine += this._formatStack(err.stack ?? "", err.message);
120
- }
121
-
122
- const isBadge = (logObj as LogObject & { badge?: boolean }).badge ?? logObj.level < 2;
123
- return isBadge ? "\n" + fullLine + "\n" : fullLine;
124
- }
125
-
126
- private _formatArgs(args: unknown[], opts: FormatOpts): string {
127
- const processed = args.map((arg) => {
128
- if (arg != null && typeof arg === "object" && typeof (arg as Error).stack === "string") {
129
- return this._formatError(arg as Error, opts);
130
- }
131
- return arg;
132
- });
133
- return formatWithOptions({ colors: opts.colors, compact: opts.compact }, ...processed);
134
- }
135
-
136
- private _formatError(err: Error, opts: FormatOpts): string {
137
- const message = err.message;
138
- const stack = err.stack != null ? this._formatStack(err.stack, message, opts) : "";
139
- const level = opts.errorLevel ?? 0;
140
- const prefix = level > 0 ? `${" ".repeat(level)}[cause]: ` : "";
141
- const cause =
142
- err.cause instanceof Error
143
- ? "\n\n" + this._formatError(err.cause, { ...opts, errorLevel: level + 1 })
144
- : "";
145
- return prefix + message + "\n" + stack + cause;
146
- }
147
-
148
- private _formatStack(stack: string, message: string, opts?: FormatOpts): string {
149
- const cwd = process.cwd() + sep;
150
- const indent = " ".repeat((opts?.errorLevel ?? 0) + 1);
151
- const lines = stack
152
- .split("\n")
153
- .splice(message.split("\n").length)
154
- .map((l) => l.trim().replace("file://", "").replace(cwd, ""));
155
- return `\n${indent}` + lines.map((l) => ` ${l}`).join(`\n${indent}`);
156
- }
157
-
158
- private _formatIcon(logObj: LogObject, useColors: boolean): string {
159
- const icon = TYPE_ICONS[logObj.type] ?? "";
160
- if (icon === "") return "";
161
- const color: AnsiColor = TYPE_COLORS[logObj.type] ?? LEVEL_COLORS[logObj.level] ?? "gray";
162
- return colorize(color, icon, useColors);
163
- }
164
-
165
- private _formatDate(date: Date, opts: FormatOpts): string {
166
- if (!opts.date) return "";
167
- const base = date.toLocaleTimeString();
168
- return `${base}.${String(date.getMilliseconds()).padStart(3, "0")}`;
169
- }
170
-
171
- private _formatBox(logObj: LogObject, message: string): string {
172
- const tag = logObj.tag !== "" ? `[${logObj.tag}]` : "";
173
- const title = (logObj as LogObject & { title?: string }).title;
174
- const lines = [tag, title, ...message.split("\n")].filter(Boolean);
175
- return "\n" + lines.map((l) => ` > ${l}`).join("\n") + "\n";
176
- }
177
- }
@@ -1,54 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import path from "path";
3
- import fs from "fs";
4
- import os from "os";
5
- import { compileScssFileAsync, compileScssStringAsync } from "../../src/utils/scss-compiler.js";
6
-
7
- const TMP_DIR = path.join(os.tmpdir(), "sd-cli-scss-test");
8
-
9
- function ensureTmpDir(): void {
10
- if (!fs.existsSync(TMP_DIR)) {
11
- fs.mkdirSync(TMP_DIR, { recursive: true });
12
- }
13
- }
14
-
15
- describe("scss-compiler async", () => {
16
- // Scenario: 외부 .scss 파일 변환
17
- it("compiles external .scss file asynchronously", async () => {
18
- ensureTmpDir();
19
- const scssPath = path.join(TMP_DIR, "test.scss");
20
- fs.writeFileSync(scssPath, "$color: red;\n.host { color: $color; }");
21
-
22
- const result = await compileScssFileAsync(scssPath, []);
23
-
24
- expect(result.css).toContain("color: red");
25
- expect(result.css).not.toContain("$color");
26
- expect(result.dependencies).toBeInstanceOf(Array);
27
- });
28
-
29
- // Scenario: 인라인 SCSS 문자열 변환
30
- it("compiles inline SCSS string asynchronously", async () => {
31
- ensureTmpDir();
32
- const containingFile = path.join(TMP_DIR, "component.ts");
33
-
34
- const result = await compileScssStringAsync(
35
- "$size: 16px;\n.text { font-size: $size; }",
36
- containingFile,
37
- [],
38
- );
39
-
40
- expect(result.css).toContain("font-size: 16px");
41
- expect(result.css).not.toContain("$size");
42
- expect(result.dependencies).toBeInstanceOf(Array);
43
- });
44
-
45
- // Scenario: SCSS 컴파일 에러 시 에러
46
- it("throws on invalid SCSS syntax", async () => {
47
- ensureTmpDir();
48
- const scssPath = path.join(TMP_DIR, "invalid.scss");
49
- fs.writeFileSync(scssPath, ".host { color: ; }"); // valid actually, let's use truly invalid
50
- fs.writeFileSync(scssPath, ".host { @include nonexistent-mixin(); }");
51
-
52
- await expect(compileScssFileAsync(scssPath, [])).rejects.toThrow();
53
- });
54
- });
@@ -1,53 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
-
3
- const mocks = vi.hoisted(() => ({
4
- initialize: vi.fn(async () => {}),
5
- start: vi.fn(async () => {}),
6
- awaitTermination: vi.fn(async () => {}),
7
- shutdown: vi.fn(async () => {}),
8
- ctor: vi.fn(),
9
- }));
10
-
11
- vi.mock("../../src/orchestrators/DevWatchOrchestrator", () => ({
12
- DevWatchOrchestrator: vi.fn().mockImplementation(function (this: any, options: any) {
13
- mocks.ctor(options);
14
- this.initialize = mocks.initialize;
15
- this.start = mocks.start;
16
- this.awaitTermination = mocks.awaitTermination;
17
- this.shutdown = mocks.shutdown;
18
- }),
19
- }));
20
-
21
- const { runDev } = await import("../../src/commands/dev");
22
-
23
- describe("runDev", () => {
24
- beforeEach(() => {
25
- vi.clearAllMocks();
26
- mocks.initialize.mockResolvedValue(undefined);
27
- mocks.start.mockResolvedValue(undefined);
28
- mocks.awaitTermination.mockResolvedValue(undefined);
29
- mocks.shutdown.mockResolvedValue(undefined);
30
- });
31
-
32
- it("creates DevWatchOrchestrator with mode:dev and runs lifecycle", async () => {
33
- await runDev({ targets: ["service-server"], options: [] });
34
-
35
- expect(mocks.ctor).toHaveBeenCalledWith({
36
- mode: "dev",
37
- targets: ["service-server"],
38
- options: [],
39
- });
40
-
41
- expect(mocks.initialize).toHaveBeenCalledOnce();
42
- expect(mocks.start).toHaveBeenCalledOnce();
43
- expect(mocks.awaitTermination).toHaveBeenCalledOnce();
44
- expect(mocks.shutdown).toHaveBeenCalledOnce();
45
- });
46
-
47
- it("calls shutdown even when start throws", async () => {
48
- mocks.start.mockRejectedValueOnce(new Error("build error"));
49
-
50
- await expect(runDev({ targets: [], options: [] })).rejects.toThrow("build error");
51
- expect(mocks.shutdown).toHaveBeenCalledOnce();
52
- });
53
- });