@simplysm/sd-cli 13.0.0-beta.45 → 13.0.0-beta.47
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 +3 -3
- package/dist/builders/BaseBuilder.js.map +0 -1
- package/dist/builders/DtsBuilder.js.map +0 -1
- package/dist/builders/LibraryBuilder.js.map +0 -1
- package/dist/builders/index.js.map +0 -1
- package/dist/builders/types.js.map +0 -1
- package/dist/capacitor/capacitor.js.map +0 -1
- package/dist/commands/add-client.js.map +0 -1
- package/dist/commands/add-server.js.map +0 -1
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/device.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/lint.js.map +0 -1
- package/dist/commands/publish.js.map +0 -1
- package/dist/commands/typecheck.js.map +0 -1
- package/dist/commands/watch.js.map +0 -1
- package/dist/electron/electron.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/infra/ResultCollector.js.map +0 -1
- package/dist/infra/SignalHandler.js.map +0 -1
- package/dist/infra/WorkerManager.js.map +0 -1
- package/dist/infra/index.js.map +0 -1
- package/dist/orchestrators/WatchOrchestrator.js.map +0 -1
- package/dist/orchestrators/index.js.map +0 -1
- package/dist/sd-cli.js.map +0 -1
- package/dist/sd-config.types.js.map +0 -1
- package/dist/utils/build-env.js.map +0 -1
- package/dist/utils/config-editor.js.map +0 -1
- package/dist/utils/copy-src.js.map +0 -1
- package/dist/utils/esbuild-config.d.ts +1 -0
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +13 -2
- package/dist/utils/esbuild-config.js.map +1 -2
- package/dist/utils/listr-manager.js.map +0 -1
- package/dist/utils/output-utils.js.map +0 -1
- package/dist/utils/package-utils.js.map +0 -1
- package/dist/utils/replace-deps.js.map +0 -1
- package/dist/utils/sd-config.js.map +0 -1
- package/dist/utils/spawn.js.map +0 -1
- package/dist/utils/tailwind-config-deps.js.map +0 -1
- package/dist/utils/template.js.map +0 -1
- package/dist/utils/tsconfig.js.map +0 -1
- package/dist/utils/typecheck-serialization.js.map +0 -1
- package/dist/utils/vite-config.js.map +0 -1
- package/dist/utils/worker-events.js.map +0 -1
- package/dist/workers/client.worker.js.map +0 -1
- package/dist/workers/dts.worker.js.map +0 -1
- package/dist/workers/library.worker.js.map +0 -1
- package/dist/workers/server-runtime.worker.js.map +0 -1
- package/dist/workers/server.worker.js.map +0 -1
- package/package.json +6 -4
- package/src/builders/BaseBuilder.ts +141 -0
- package/src/builders/DtsBuilder.ts +138 -0
- package/src/builders/LibraryBuilder.ts +161 -0
- package/src/builders/index.ts +4 -0
- package/src/builders/types.ts +55 -0
- package/src/capacitor/capacitor.ts +827 -0
- package/src/commands/add-client.ts +135 -0
- package/src/commands/add-server.ts +150 -0
- package/src/commands/build.ts +475 -0
- package/src/commands/dev.ts +602 -0
- package/src/commands/device.ts +151 -0
- package/src/commands/init.ts +104 -0
- package/src/commands/lint.ts +216 -0
- package/src/commands/publish.ts +836 -0
- package/src/commands/typecheck.ts +329 -0
- package/src/commands/watch.ts +38 -0
- package/src/electron/electron.ts +329 -0
- package/src/index.ts +1 -0
- package/src/infra/ResultCollector.ts +81 -0
- package/src/infra/SignalHandler.ts +52 -0
- package/src/infra/WorkerManager.ts +65 -0
- package/src/infra/index.ts +3 -0
- package/src/orchestrators/WatchOrchestrator.ts +211 -0
- package/src/orchestrators/index.ts +1 -0
- package/src/sd-cli.ts +307 -0
- package/src/sd-config.types.ts +271 -0
- package/src/utils/build-env.ts +12 -0
- package/src/utils/config-editor.ts +131 -0
- package/src/utils/copy-src.ts +60 -0
- package/src/utils/esbuild-config.ts +263 -0
- package/src/utils/listr-manager.ts +89 -0
- package/src/utils/output-utils.ts +61 -0
- package/src/utils/package-utils.ts +63 -0
- package/src/utils/replace-deps.ts +163 -0
- package/src/utils/sd-config.ts +44 -0
- package/src/utils/spawn.ts +79 -0
- package/src/utils/tailwind-config-deps.ts +95 -0
- package/src/utils/template.ts +51 -0
- package/src/utils/tsconfig.ts +111 -0
- package/src/utils/typecheck-serialization.ts +82 -0
- package/src/utils/vite-config.ts +184 -0
- package/src/utils/worker-events.ts +102 -0
- package/src/workers/client.worker.ts +236 -0
- package/src/workers/dts.worker.ts +416 -0
- package/src/workers/library.worker.ts +245 -0
- package/src/workers/server-runtime.worker.ts +154 -0
- package/src/workers/server.worker.ts +435 -0
- package/templates/add-client/__CLIENT__/package.json.hbs +1 -1
- package/templates/add-server/__SERVER__/package.json.hbs +2 -2
- package/templates/init/package.json.hbs +3 -3
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type * as DtsWorkerModule from "../workers/dts.worker";
|
|
2
|
+
import type { BuildResult } from "../infra/ResultCollector";
|
|
3
|
+
import type { TypecheckEnv } from "../utils/tsconfig";
|
|
4
|
+
import type { BuildEventData, ErrorEventData } from "../utils/worker-events";
|
|
5
|
+
import { BaseBuilder } from "./BaseBuilder";
|
|
6
|
+
import type { PackageInfo } from "./types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* .d.ts 파일 생성을 담당하는 Builder
|
|
10
|
+
*
|
|
11
|
+
* Library 패키지의 TypeScript 선언 파일 생성을 처리한다.
|
|
12
|
+
* Watch 모드와 프로덕션 빌드를 모두 지원한다.
|
|
13
|
+
*/
|
|
14
|
+
export class DtsBuilder extends BaseBuilder {
|
|
15
|
+
private readonly _workerPath: string;
|
|
16
|
+
|
|
17
|
+
constructor(options: ConstructorParameters<typeof BaseBuilder>[0]) {
|
|
18
|
+
super(options);
|
|
19
|
+
this._workerPath = import.meta.resolve("../workers/dts.worker");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected getBuilderType(): string {
|
|
23
|
+
return "dts";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 패키지 타겟에서 TypecheckEnv 결정
|
|
28
|
+
*/
|
|
29
|
+
private _getEnv(pkg: PackageInfo): TypecheckEnv {
|
|
30
|
+
const target = pkg.config.target;
|
|
31
|
+
if (target === "node") return "node";
|
|
32
|
+
return "browser"; // browser, neutral, client 모두 browser 환경
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected createWorkers(): void {
|
|
36
|
+
for (const pkg of this.packages) {
|
|
37
|
+
this.workerManager.create<typeof DtsWorkerModule>(`${pkg.name}:dts`, this._workerPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected registerEventHandlers(): void {
|
|
42
|
+
for (const pkg of this.packages) {
|
|
43
|
+
const worker = this.workerManager.get<typeof DtsWorkerModule>(`${pkg.name}:dts`)!;
|
|
44
|
+
const resultKey = `${pkg.name}:dts`;
|
|
45
|
+
const listrTitle = `${pkg.name} (dts)`;
|
|
46
|
+
|
|
47
|
+
let isInitialBuild = true;
|
|
48
|
+
|
|
49
|
+
// 빌드 시작 (리빌드 시)
|
|
50
|
+
worker.on("buildStart", () => {
|
|
51
|
+
if (!isInitialBuild && this.rebuildManager != null) {
|
|
52
|
+
const resolver = this.rebuildManager.registerBuild(resultKey, listrTitle);
|
|
53
|
+
this.buildResolvers.set(resultKey, resolver);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 빌드 완료
|
|
58
|
+
worker.on("build", (data) => {
|
|
59
|
+
const event = data as BuildEventData;
|
|
60
|
+
const result: BuildResult = {
|
|
61
|
+
name: pkg.name,
|
|
62
|
+
target: pkg.config.target,
|
|
63
|
+
type: "dts",
|
|
64
|
+
status: event.success ? "success" : "error",
|
|
65
|
+
message: event.errors?.join("\n"),
|
|
66
|
+
};
|
|
67
|
+
this.resultCollector.add(result);
|
|
68
|
+
|
|
69
|
+
if (isInitialBuild) {
|
|
70
|
+
isInitialBuild = false;
|
|
71
|
+
}
|
|
72
|
+
this.completeBuild(pkg);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// 에러
|
|
76
|
+
worker.on("error", (data) => {
|
|
77
|
+
const event = data as ErrorEventData;
|
|
78
|
+
const result: BuildResult = {
|
|
79
|
+
name: pkg.name,
|
|
80
|
+
target: pkg.config.target,
|
|
81
|
+
type: "dts",
|
|
82
|
+
status: "error",
|
|
83
|
+
message: event.message,
|
|
84
|
+
};
|
|
85
|
+
this.resultCollector.add(result);
|
|
86
|
+
|
|
87
|
+
if (isInitialBuild) {
|
|
88
|
+
isInitialBuild = false;
|
|
89
|
+
}
|
|
90
|
+
this.completeBuild(pkg);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected async buildPackage(pkg: PackageInfo): Promise<void> {
|
|
96
|
+
const worker = this.workerManager.get<typeof DtsWorkerModule>(`${pkg.name}:dts`)!;
|
|
97
|
+
|
|
98
|
+
const buildPromise = new Promise<void>((resolve) => {
|
|
99
|
+
const originalResolver = this.buildResolvers.get(`${pkg.name}:dts`);
|
|
100
|
+
this.buildResolvers.set(`${pkg.name}:dts`, () => {
|
|
101
|
+
originalResolver?.();
|
|
102
|
+
resolve();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
void worker.startDtsWatch({
|
|
107
|
+
name: pkg.name,
|
|
108
|
+
cwd: this.cwd,
|
|
109
|
+
pkgDir: pkg.dir,
|
|
110
|
+
env: this._getEnv(pkg),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await buildPromise;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
protected startWatchPackage(pkg: PackageInfo): void {
|
|
117
|
+
const worker = this.workerManager.get<typeof DtsWorkerModule>(`${pkg.name}:dts`)!;
|
|
118
|
+
|
|
119
|
+
worker
|
|
120
|
+
.startDtsWatch({
|
|
121
|
+
name: pkg.name,
|
|
122
|
+
cwd: this.cwd,
|
|
123
|
+
pkgDir: pkg.dir,
|
|
124
|
+
env: this._getEnv(pkg),
|
|
125
|
+
})
|
|
126
|
+
.catch((err: unknown) => {
|
|
127
|
+
const result: BuildResult = {
|
|
128
|
+
name: pkg.name,
|
|
129
|
+
target: pkg.config.target,
|
|
130
|
+
type: "dts",
|
|
131
|
+
status: "error",
|
|
132
|
+
message: err instanceof Error ? err.message : String(err),
|
|
133
|
+
};
|
|
134
|
+
this.resultCollector.add(result);
|
|
135
|
+
this.completeBuild(pkg);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type * as LibraryWorkerModule from "../workers/library.worker";
|
|
2
|
+
import type { BuildResult } from "../infra/ResultCollector";
|
|
3
|
+
import type { SdBuildPackageConfig } from "../sd-config.types";
|
|
4
|
+
import type { BuildEventData, ErrorEventData } from "../utils/worker-events";
|
|
5
|
+
import { BaseBuilder } from "./BaseBuilder";
|
|
6
|
+
import type { PackageInfo } from "./types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Library 패키지 빌드를 담당하는 Builder
|
|
10
|
+
*
|
|
11
|
+
* node/browser/neutral 타겟 패키지의 esbuild 빌드를 처리한다.
|
|
12
|
+
* Watch 모드와 프로덕션 빌드를 모두 지원한다.
|
|
13
|
+
*/
|
|
14
|
+
export class LibraryBuilder extends BaseBuilder {
|
|
15
|
+
private readonly _workerPath: string;
|
|
16
|
+
|
|
17
|
+
constructor(options: ConstructorParameters<typeof BaseBuilder>[0]) {
|
|
18
|
+
super(options);
|
|
19
|
+
this._workerPath = import.meta.resolve("../workers/library.worker");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected getBuilderType(): string {
|
|
23
|
+
return "build";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
protected createWorkers(): void {
|
|
27
|
+
for (const pkg of this.packages) {
|
|
28
|
+
this.workerManager.create<typeof LibraryWorkerModule>(`${pkg.name}:build`, this._workerPath);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected registerEventHandlers(): void {
|
|
33
|
+
for (const pkg of this.packages) {
|
|
34
|
+
const worker = this.workerManager.get<typeof LibraryWorkerModule>(`${pkg.name}:build`)!;
|
|
35
|
+
const resultKey = `${pkg.name}:build`;
|
|
36
|
+
const listrTitle = `${pkg.name} (${pkg.config.target})`;
|
|
37
|
+
|
|
38
|
+
// 초기 빌드 여부 추적
|
|
39
|
+
let isInitialBuild = true;
|
|
40
|
+
|
|
41
|
+
// 빌드 시작 (리빌드 시)
|
|
42
|
+
worker.on("buildStart", () => {
|
|
43
|
+
if (!isInitialBuild && this.rebuildManager != null) {
|
|
44
|
+
// 리빌드 시 RebuildListrManager에 등록
|
|
45
|
+
const resolver = this.rebuildManager.registerBuild(resultKey, listrTitle);
|
|
46
|
+
this.buildResolvers.set(resultKey, resolver);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// 빌드 완료
|
|
51
|
+
worker.on("build", (data) => {
|
|
52
|
+
const event = data as BuildEventData;
|
|
53
|
+
const result: BuildResult = {
|
|
54
|
+
name: pkg.name,
|
|
55
|
+
target: pkg.config.target,
|
|
56
|
+
type: "build",
|
|
57
|
+
status: event.success ? "success" : "error",
|
|
58
|
+
message: event.errors?.join("\n"),
|
|
59
|
+
};
|
|
60
|
+
this.resultCollector.add(result);
|
|
61
|
+
|
|
62
|
+
if (isInitialBuild) {
|
|
63
|
+
isInitialBuild = false;
|
|
64
|
+
}
|
|
65
|
+
this.completeBuild(pkg);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 에러
|
|
69
|
+
worker.on("error", (data) => {
|
|
70
|
+
const event = data as ErrorEventData;
|
|
71
|
+
const result: BuildResult = {
|
|
72
|
+
name: pkg.name,
|
|
73
|
+
target: pkg.config.target,
|
|
74
|
+
type: "build",
|
|
75
|
+
status: "error",
|
|
76
|
+
message: event.message,
|
|
77
|
+
};
|
|
78
|
+
this.resultCollector.add(result);
|
|
79
|
+
|
|
80
|
+
if (isInitialBuild) {
|
|
81
|
+
isInitialBuild = false;
|
|
82
|
+
}
|
|
83
|
+
this.completeBuild(pkg);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
protected async buildPackage(pkg: PackageInfo): Promise<void> {
|
|
89
|
+
const worker = this.workerManager.get<typeof LibraryWorkerModule>(`${pkg.name}:build`)!;
|
|
90
|
+
|
|
91
|
+
// 빌드 완료 Promise 생성
|
|
92
|
+
const buildPromise = new Promise<void>((resolve) => {
|
|
93
|
+
const originalResolver = this.buildResolvers.get(`${pkg.name}:build`);
|
|
94
|
+
this.buildResolvers.set(`${pkg.name}:build`, () => {
|
|
95
|
+
originalResolver?.();
|
|
96
|
+
resolve();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// 빌드 시작 (await 없이 - 이벤트로 완료 감지)
|
|
101
|
+
// LibraryBuilder는 library 패키지(node/browser/neutral)만 받으므로 캐스팅 안전
|
|
102
|
+
void worker.startWatch({
|
|
103
|
+
name: pkg.name,
|
|
104
|
+
config: pkg.config as SdBuildPackageConfig,
|
|
105
|
+
cwd: this.cwd,
|
|
106
|
+
pkgDir: pkg.dir,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
await buildPromise;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
protected startWatchPackage(pkg: PackageInfo): void {
|
|
113
|
+
const worker = this.workerManager.get<typeof LibraryWorkerModule>(`${pkg.name}:build`)!;
|
|
114
|
+
|
|
115
|
+
// LibraryBuilder는 library 패키지(node/browser/neutral)만 받으므로 캐스팅 안전
|
|
116
|
+
worker
|
|
117
|
+
.startWatch({
|
|
118
|
+
name: pkg.name,
|
|
119
|
+
config: pkg.config as SdBuildPackageConfig,
|
|
120
|
+
cwd: this.cwd,
|
|
121
|
+
pkgDir: pkg.dir,
|
|
122
|
+
})
|
|
123
|
+
.catch((err: unknown) => {
|
|
124
|
+
const result: BuildResult = {
|
|
125
|
+
name: pkg.name,
|
|
126
|
+
target: pkg.config.target,
|
|
127
|
+
type: "build",
|
|
128
|
+
status: "error",
|
|
129
|
+
message: err instanceof Error ? err.message : String(err),
|
|
130
|
+
};
|
|
131
|
+
this.resultCollector.add(result);
|
|
132
|
+
this.completeBuild(pkg);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Graceful shutdown (esbuild context dispose)
|
|
138
|
+
*/
|
|
139
|
+
override async shutdown(): Promise<void> {
|
|
140
|
+
const shutdownTimeout = 3000;
|
|
141
|
+
|
|
142
|
+
// 각 Worker의 stopWatch 메서드 호출 후 terminate
|
|
143
|
+
await Promise.all(
|
|
144
|
+
this.workerManager.ids.map(async (id) => {
|
|
145
|
+
const worker = this.workerManager.get<typeof LibraryWorkerModule>(id);
|
|
146
|
+
if (worker != null) {
|
|
147
|
+
try {
|
|
148
|
+
await Promise.race([
|
|
149
|
+
worker.stopWatch(),
|
|
150
|
+
new Promise<void>((resolve) => setTimeout(resolve, shutdownTimeout)),
|
|
151
|
+
]);
|
|
152
|
+
} catch {
|
|
153
|
+
// stopWatch 실패해도 계속 진행
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
await super.shutdown();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { SdPackageConfig } from "../sd-config.types";
|
|
2
|
+
import type { ResultCollector } from "../infra/ResultCollector";
|
|
3
|
+
import type { RebuildListrManager } from "../utils/listr-manager";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 패키지 정보
|
|
7
|
+
*/
|
|
8
|
+
export interface PackageInfo {
|
|
9
|
+
name: string;
|
|
10
|
+
dir: string;
|
|
11
|
+
config: SdPackageConfig;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Builder 공통 옵션
|
|
16
|
+
*/
|
|
17
|
+
export interface BuilderOptions {
|
|
18
|
+
cwd: string;
|
|
19
|
+
packages: PackageInfo[];
|
|
20
|
+
resultCollector: ResultCollector;
|
|
21
|
+
rebuildManager?: RebuildListrManager;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Builder 인터페이스
|
|
26
|
+
*
|
|
27
|
+
* 모든 Builder가 구현해야 하는 공통 인터페이스
|
|
28
|
+
*/
|
|
29
|
+
export interface IBuilder {
|
|
30
|
+
/**
|
|
31
|
+
* Builder 초기화 (Worker 생성, 이벤트 핸들러 등록)
|
|
32
|
+
*/
|
|
33
|
+
initialize(): Promise<void>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 일회성 빌드 (프로덕션 빌드용)
|
|
37
|
+
*/
|
|
38
|
+
build(): Promise<void>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Watch 모드 시작
|
|
42
|
+
* Promise는 초기 빌드 완료 시 resolve됨
|
|
43
|
+
*/
|
|
44
|
+
startWatch(): Promise<void>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Builder 종료 (Worker 정리)
|
|
48
|
+
*/
|
|
49
|
+
shutdown(): Promise<void>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 초기 빌드 Promise 맵 반환 (Listr 태스크용)
|
|
53
|
+
*/
|
|
54
|
+
getInitialBuildPromises(): Map<string, Promise<void>>;
|
|
55
|
+
}
|