@simplysm/sd-cli 13.0.11 → 13.0.13
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 +42 -2
- package/dist/builders/BaseBuilder.d.ts +15 -4
- package/dist/builders/BaseBuilder.d.ts.map +1 -1
- package/dist/builders/BaseBuilder.js +50 -0
- package/dist/builders/BaseBuilder.js.map +1 -1
- package/dist/builders/DtsBuilder.d.ts.map +1 -1
- package/dist/builders/DtsBuilder.js +2 -39
- package/dist/builders/DtsBuilder.js.map +1 -1
- package/dist/builders/LibraryBuilder.d.ts.map +1 -1
- package/dist/builders/LibraryBuilder.js +2 -39
- package/dist/builders/LibraryBuilder.js.map +1 -1
- package/dist/builders/types.d.ts +2 -2
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +2 -1
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/add-client.d.ts.map +1 -1
- package/dist/commands/add-client.js +1 -9
- package/dist/commands/add-client.js.map +1 -1
- package/dist/commands/add-server.d.ts.map +1 -1
- package/dist/commands/add-server.js +1 -9
- package/dist/commands/add-server.js.map +1 -1
- package/dist/commands/build.d.ts +1 -2
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +12 -311
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +11 -432
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +17 -32
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.d.ts +1 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +71 -118
- package/dist/commands/lint.js.map +2 -2
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +47 -69
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/typecheck.d.ts +1 -1
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +11 -24
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/infra/ResultCollector.d.ts +1 -1
- package/dist/infra/ResultCollector.d.ts.map +1 -1
- package/dist/infra/ResultCollector.js +1 -1
- package/dist/infra/ResultCollector.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts +53 -0
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -0
- package/dist/orchestrators/BuildOrchestrator.js +338 -0
- package/dist/orchestrators/BuildOrchestrator.js.map +6 -0
- package/dist/orchestrators/DevOrchestrator.d.ts +64 -0
- package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -0
- package/dist/orchestrators/DevOrchestrator.js +524 -0
- package/dist/orchestrators/DevOrchestrator.js.map +6 -0
- package/dist/orchestrators/WatchOrchestrator.d.ts +1 -1
- package/dist/orchestrators/WatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/WatchOrchestrator.js +30 -21
- package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
- package/dist/orchestrators/index.d.ts +2 -0
- package/dist/orchestrators/index.d.ts.map +1 -1
- package/dist/orchestrators/index.js +4 -0
- package/dist/orchestrators/index.js.map +1 -1
- package/dist/sd-cli-entry.js +14 -14
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.js +6 -4
- package/dist/sd-cli.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts +8 -0
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +23 -28
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/output-utils.d.ts +0 -1
- package/dist/utils/output-utils.d.ts.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.d.ts +5 -1
- package/dist/utils/package-utils.d.ts.map +1 -1
- package/dist/utils/package-utils.js +12 -0
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/rebuild-manager.d.ts +15 -0
- package/dist/utils/rebuild-manager.d.ts.map +1 -0
- package/dist/utils/rebuild-manager.js +50 -0
- package/dist/utils/rebuild-manager.js.map +6 -0
- package/dist/utils/replace-deps.d.ts.map +1 -1
- package/dist/utils/replace-deps.js +7 -13
- 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 +61 -7
- package/dist/utils/vite-config.js.map +1 -1
- package/dist/utils/worker-events.d.ts +5 -4
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-events.js +4 -0
- package/dist/utils/worker-events.js.map +1 -1
- package/dist/utils/worker-utils.d.ts +13 -0
- package/dist/utils/worker-utils.d.ts.map +1 -0
- package/dist/utils/worker-utils.js +15 -0
- package/dist/utils/worker-utils.js.map +6 -0
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +2 -14
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library.worker.d.ts.map +1 -1
- package/dist/workers/library.worker.js +14 -16
- package/dist/workers/library.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.d.ts.map +1 -1
- package/dist/workers/server-runtime.worker.js +11 -11
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/dist/workers/server.worker.d.ts.map +1 -1
- package/dist/workers/server.worker.js +2 -14
- package/dist/workers/server.worker.js.map +1 -1
- package/package.json +4 -5
- package/src/builders/BaseBuilder.ts +71 -4
- package/src/builders/DtsBuilder.ts +2 -49
- package/src/builders/LibraryBuilder.ts +2 -51
- package/src/builders/types.ts +2 -2
- package/src/capacitor/capacitor.ts +2 -1
- package/src/commands/add-client.ts +1 -14
- package/src/commands/add-server.ts +1 -13
- package/src/commands/build.ts +13 -443
- package/src/commands/dev.ts +12 -582
- package/src/commands/device.ts +17 -34
- package/src/commands/init.ts +1 -13
- package/src/commands/lint.ts +85 -146
- package/src/commands/publish.ts +58 -76
- package/src/commands/typecheck.ts +13 -46
- package/src/index.ts +1 -0
- package/src/infra/ResultCollector.ts +2 -2
- package/src/orchestrators/BuildOrchestrator.ts +499 -0
- package/src/orchestrators/DevOrchestrator.ts +703 -0
- package/src/orchestrators/WatchOrchestrator.ts +42 -25
- package/src/orchestrators/index.ts +2 -0
- package/src/sd-cli-entry.ts +14 -14
- package/src/sd-cli.ts +6 -4
- package/src/utils/esbuild-config.ts +31 -33
- package/src/utils/output-utils.ts +1 -2
- package/src/utils/package-utils.ts +16 -1
- package/src/utils/rebuild-manager.ts +65 -0
- package/src/utils/replace-deps.ts +25 -23
- package/src/utils/vite-config.ts +115 -9
- package/src/utils/worker-events.ts +13 -5
- package/src/utils/worker-utils.ts +26 -0
- package/src/workers/client.worker.ts +3 -19
- package/src/workers/library.worker.ts +16 -22
- package/src/workers/server-runtime.worker.ts +16 -17
- package/src/workers/server.worker.ts +2 -19
- 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
- package/dist/utils/listr-manager.d.ts +0 -37
- package/dist/utils/listr-manager.d.ts.map +0 -1
- package/dist/utils/listr-manager.js +0 -59
- package/dist/utils/listr-manager.js.map +0 -6
- package/src/utils/listr-manager.ts +0 -89
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { Listr } from "listr2";
|
|
3
2
|
import { consola } from "consola";
|
|
4
3
|
import type { BuildTarget, SdConfig, SdPackageConfig } from "../sd-config.types";
|
|
5
4
|
import { loadSdConfig } from "../utils/sd-config";
|
|
6
5
|
import { filterPackagesByTargets } from "../utils/package-utils";
|
|
7
6
|
import { setupReplaceDeps, watchReplaceDeps, type WatchReplaceDepResult } from "../utils/replace-deps";
|
|
8
7
|
import { printErrors } from "../utils/output-utils";
|
|
9
|
-
import {
|
|
8
|
+
import { RebuildManager } from "../utils/rebuild-manager";
|
|
10
9
|
import { ResultCollector } from "../infra/ResultCollector";
|
|
11
10
|
import { SignalHandler } from "../infra/SignalHandler";
|
|
12
11
|
import { LibraryBuilder } from "../builders/LibraryBuilder";
|
|
@@ -38,7 +37,7 @@ export class WatchOrchestrator {
|
|
|
38
37
|
|
|
39
38
|
private _resultCollector!: ResultCollector;
|
|
40
39
|
private _signalHandler!: SignalHandler;
|
|
41
|
-
private _rebuildManager!:
|
|
40
|
+
private _rebuildManager!: RebuildManager;
|
|
42
41
|
private _libraryBuilder!: LibraryBuilder;
|
|
43
42
|
private _dtsBuilder!: DtsBuilder;
|
|
44
43
|
private _packages: PackageInfo[] = [];
|
|
@@ -69,7 +68,7 @@ export class WatchOrchestrator {
|
|
|
69
68
|
});
|
|
70
69
|
this._logger.debug("sd.config.ts 로드 완료");
|
|
71
70
|
} catch (err) {
|
|
72
|
-
|
|
71
|
+
this._logger.error(`sd.config.ts 로드 실패: ${err instanceof Error ? err.message : err}`);
|
|
73
72
|
process.exitCode = 1;
|
|
74
73
|
throw err;
|
|
75
74
|
}
|
|
@@ -109,7 +108,7 @@ export class WatchOrchestrator {
|
|
|
109
108
|
// 인프라 초기화
|
|
110
109
|
this._resultCollector = new ResultCollector();
|
|
111
110
|
this._signalHandler = new SignalHandler();
|
|
112
|
-
this._rebuildManager = new
|
|
111
|
+
this._rebuildManager = new RebuildManager(this._logger);
|
|
113
112
|
|
|
114
113
|
// 배치 완료 시 에러 출력
|
|
115
114
|
this._rebuildManager.on("batchComplete", () => {
|
|
@@ -133,7 +132,7 @@ export class WatchOrchestrator {
|
|
|
133
132
|
|
|
134
133
|
/**
|
|
135
134
|
* Watch 모드 시작
|
|
136
|
-
* - 초기 빌드
|
|
135
|
+
* - 초기 빌드 실행
|
|
137
136
|
* - 결과 출력
|
|
138
137
|
*/
|
|
139
138
|
async start(): Promise<void> {
|
|
@@ -141,26 +140,10 @@ export class WatchOrchestrator {
|
|
|
141
140
|
return;
|
|
142
141
|
}
|
|
143
142
|
|
|
144
|
-
// 초기 빌드
|
|
143
|
+
// 초기 빌드 Promise 구성
|
|
145
144
|
const buildPromises = this._libraryBuilder.getInitialBuildPromises();
|
|
146
145
|
const dtsPromises = this._dtsBuilder.getInitialBuildPromises();
|
|
147
146
|
|
|
148
|
-
const initialListr = new Listr(
|
|
149
|
-
[
|
|
150
|
-
// Library 빌드 태스크
|
|
151
|
-
...this._packages.map((pkg) => ({
|
|
152
|
-
title: `${pkg.name} (${pkg.config.target})`,
|
|
153
|
-
task: () => buildPromises.get(`${pkg.name}:build`) ?? Promise.resolve(),
|
|
154
|
-
})),
|
|
155
|
-
// DTS 태스크
|
|
156
|
-
...this._packages.map((pkg) => ({
|
|
157
|
-
title: `${pkg.name} (dts)`,
|
|
158
|
-
task: () => dtsPromises.get(`${pkg.name}:dts`) ?? Promise.resolve(),
|
|
159
|
-
})),
|
|
160
|
-
],
|
|
161
|
-
{ concurrent: true },
|
|
162
|
-
);
|
|
163
|
-
|
|
164
147
|
// copySrc watch 시작
|
|
165
148
|
for (const pkg of this._packages) {
|
|
166
149
|
const buildConfig = pkg.config as SdBuildPackageConfig;
|
|
@@ -174,8 +157,42 @@ export class WatchOrchestrator {
|
|
|
174
157
|
void this._libraryBuilder.startWatch();
|
|
175
158
|
void this._dtsBuilder.startWatch();
|
|
176
159
|
|
|
177
|
-
//
|
|
178
|
-
|
|
160
|
+
// 초기 빌드 시작
|
|
161
|
+
this._logger.start("초기 빌드 진행 중...");
|
|
162
|
+
|
|
163
|
+
// Library 빌드 및 DTS 빌드 전체 Promise 배열 구성
|
|
164
|
+
const allBuildTasks: Array<{ name: string; promise: Promise<void> }> = [];
|
|
165
|
+
|
|
166
|
+
// Library 빌드 태스크
|
|
167
|
+
for (const pkg of this._packages) {
|
|
168
|
+
const promise = buildPromises.get(`${pkg.name}:build`) ?? Promise.resolve();
|
|
169
|
+
allBuildTasks.push({
|
|
170
|
+
name: `${pkg.name}:build`,
|
|
171
|
+
promise: (async () => {
|
|
172
|
+
this._logger.debug(`${pkg.name} (${pkg.config.target}) 빌드 시작`);
|
|
173
|
+
await promise;
|
|
174
|
+
this._logger.debug(`${pkg.name} (${pkg.config.target}) 빌드 완료`);
|
|
175
|
+
})(),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// DTS 태스크
|
|
180
|
+
for (const pkg of this._packages) {
|
|
181
|
+
const promise = dtsPromises.get(`${pkg.name}:dts`) ?? Promise.resolve();
|
|
182
|
+
allBuildTasks.push({
|
|
183
|
+
name: `${pkg.name}:dts`,
|
|
184
|
+
promise: (async () => {
|
|
185
|
+
this._logger.debug(`${pkg.name} (dts) 시작`);
|
|
186
|
+
await promise;
|
|
187
|
+
this._logger.debug(`${pkg.name} (dts) 완료`);
|
|
188
|
+
})(),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 모든 빌드 작업 동시 실행 (초기 빌드 완료까지 대기)
|
|
193
|
+
await Promise.allSettled(allBuildTasks.map((task) => task.promise));
|
|
194
|
+
|
|
195
|
+
this._logger.success("초기 빌드 완료");
|
|
179
196
|
|
|
180
197
|
// 초기 빌드 결과 출력
|
|
181
198
|
printErrors(this._resultCollector.toMap());
|
package/src/sd-cli-entry.ts
CHANGED
|
@@ -85,7 +85,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
85
85
|
default: [],
|
|
86
86
|
})
|
|
87
87
|
.options({
|
|
88
|
-
|
|
88
|
+
configOpt: {
|
|
89
89
|
type: "string",
|
|
90
90
|
array: true,
|
|
91
91
|
alias: "o",
|
|
@@ -96,7 +96,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
96
96
|
async (args) => {
|
|
97
97
|
await runTypecheck({
|
|
98
98
|
targets: args.targets,
|
|
99
|
-
options: args.
|
|
99
|
+
options: args.configOpt,
|
|
100
100
|
});
|
|
101
101
|
},
|
|
102
102
|
)
|
|
@@ -114,7 +114,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
114
114
|
default: [],
|
|
115
115
|
})
|
|
116
116
|
.options({
|
|
117
|
-
|
|
117
|
+
configOpt: {
|
|
118
118
|
type: "string",
|
|
119
119
|
array: true,
|
|
120
120
|
alias: "o",
|
|
@@ -125,7 +125,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
125
125
|
async (args) => {
|
|
126
126
|
await runWatch({
|
|
127
127
|
targets: args.targets,
|
|
128
|
-
options: args.
|
|
128
|
+
options: args.configOpt,
|
|
129
129
|
});
|
|
130
130
|
},
|
|
131
131
|
)
|
|
@@ -143,7 +143,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
143
143
|
default: [],
|
|
144
144
|
})
|
|
145
145
|
.options({
|
|
146
|
-
|
|
146
|
+
configOpt: {
|
|
147
147
|
type: "string",
|
|
148
148
|
array: true,
|
|
149
149
|
alias: "o",
|
|
@@ -154,7 +154,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
154
154
|
async (args) => {
|
|
155
155
|
await runDev({
|
|
156
156
|
targets: args.targets,
|
|
157
|
-
options: args.
|
|
157
|
+
options: args.configOpt,
|
|
158
158
|
});
|
|
159
159
|
},
|
|
160
160
|
)
|
|
@@ -172,7 +172,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
172
172
|
default: [],
|
|
173
173
|
})
|
|
174
174
|
.options({
|
|
175
|
-
|
|
175
|
+
configOpt: {
|
|
176
176
|
type: "string",
|
|
177
177
|
array: true,
|
|
178
178
|
alias: "o",
|
|
@@ -183,7 +183,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
183
183
|
async (args) => {
|
|
184
184
|
await runBuild({
|
|
185
185
|
targets: args.targets,
|
|
186
|
-
options: args.
|
|
186
|
+
options: args.configOpt,
|
|
187
187
|
});
|
|
188
188
|
},
|
|
189
189
|
)
|
|
@@ -206,7 +206,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
206
206
|
alias: "u",
|
|
207
207
|
describe: "개발 서버 URL (미지정 시 sd.config.ts의 server 설정 사용)",
|
|
208
208
|
},
|
|
209
|
-
|
|
209
|
+
configOpt: {
|
|
210
210
|
type: "string",
|
|
211
211
|
array: true,
|
|
212
212
|
alias: "o",
|
|
@@ -218,7 +218,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
218
218
|
await runDevice({
|
|
219
219
|
package: args.package,
|
|
220
220
|
url: args.url,
|
|
221
|
-
options: args.
|
|
221
|
+
options: args.configOpt,
|
|
222
222
|
});
|
|
223
223
|
},
|
|
224
224
|
)
|
|
@@ -279,7 +279,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
279
279
|
describe: "실제 배포 없이 시뮬레이션",
|
|
280
280
|
default: false,
|
|
281
281
|
},
|
|
282
|
-
"
|
|
282
|
+
"configOpt": {
|
|
283
283
|
type: "string",
|
|
284
284
|
array: true,
|
|
285
285
|
alias: "o",
|
|
@@ -292,7 +292,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
292
292
|
targets: args.targets,
|
|
293
293
|
noBuild: !args.build,
|
|
294
294
|
dryRun: args.dryRun,
|
|
295
|
-
options: args.
|
|
295
|
+
options: args.configOpt,
|
|
296
296
|
});
|
|
297
297
|
},
|
|
298
298
|
)
|
|
@@ -304,7 +304,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
304
304
|
.version(false)
|
|
305
305
|
.hide("help")
|
|
306
306
|
.options({
|
|
307
|
-
|
|
307
|
+
configOpt: {
|
|
308
308
|
type: "string",
|
|
309
309
|
array: true,
|
|
310
310
|
alias: "o",
|
|
@@ -314,7 +314,7 @@ export function createCliParser(argv: string[]): Argv {
|
|
|
314
314
|
}),
|
|
315
315
|
async (args) => {
|
|
316
316
|
await runReplaceDeps({
|
|
317
|
-
options: args.
|
|
317
|
+
options: args.configOpt,
|
|
318
318
|
});
|
|
319
319
|
},
|
|
320
320
|
)
|
package/src/sd-cli.ts
CHANGED
|
@@ -12,15 +12,16 @@ import os from "os";
|
|
|
12
12
|
import path from "path";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = path.dirname(__filename);
|
|
17
|
+
const isDev = path.extname(__filename) === ".ts";
|
|
17
18
|
|
|
18
|
-
if (
|
|
19
|
+
if (isDev) {
|
|
19
20
|
// 개발 모드 (.ts): affinity 적용 후 직접 실행
|
|
20
21
|
// import만으로는 메인 모듈 감지가 실패하므로 (process.argv[1] ≠ sd-cli-entry)
|
|
21
22
|
// createCliParser를 명시적으로 호출한다.
|
|
22
23
|
configureAffinityAndPriority(process.pid);
|
|
23
|
-
const { createCliParser } = await import(
|
|
24
|
+
const { createCliParser } = await import("./sd-cli-entry.js");
|
|
24
25
|
await createCliParser(process.argv.slice(2)).parse();
|
|
25
26
|
} else {
|
|
26
27
|
// 배포 모드 (.js): 2단계 실행
|
|
@@ -38,6 +39,7 @@ if (path.extname(cliEntryFilePath) === ".ts") {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
// Phase 2: 새 프로세스로 실제 CLI 실행 (모듈 캐시 초기화)
|
|
42
|
+
const cliEntryFilePath = path.join(__dirname, "sd-cli-entry.js");
|
|
41
43
|
const child = spawn(
|
|
42
44
|
"node",
|
|
43
45
|
["--max-old-space-size=8192", "--max-semi-space-size=16", cliEntryFilePath, ...process.argv.slice(2)],
|
|
@@ -2,45 +2,42 @@ import path from "path";
|
|
|
2
2
|
import { readFileSync, existsSync } from "fs";
|
|
3
3
|
import fs from "fs/promises";
|
|
4
4
|
import { createRequire } from "module";
|
|
5
|
-
import { glob } from "glob";
|
|
6
5
|
import type esbuild from "esbuild";
|
|
7
6
|
import { solidPlugin } from "esbuild-plugin-solid";
|
|
8
7
|
import type { TypecheckEnv } from "./tsconfig";
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
* esbuild outputFiles 중 실제로 변경된 파일만 디스크에 쓴다.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* - .js 파일: ESM 상대 import 경로에 .js 확장자를 추가한 후 비교
|
|
13
|
+
* - 그 외 파일(.js.map 등): 원본 그대로 비교
|
|
14
|
+
* - 기존 파일과 내용이 동일하면 쓰기를 건너뛰어 타임스탬프를 유지한다.
|
|
15
15
|
*/
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
};
|
|
16
|
+
export async function writeChangedOutputFiles(outputFiles: esbuild.OutputFile[]): Promise<void> {
|
|
17
|
+
await Promise.all(
|
|
18
|
+
outputFiles.map(async (file) => {
|
|
19
|
+
const finalText = file.path.endsWith(".js")
|
|
20
|
+
? file.text.replace(
|
|
21
|
+
/((?:from|import)\s*["'])(\.\.?\/[^"']*?)(["'])/g,
|
|
22
|
+
(_match, prefix: string, importPath: string, suffix: string) => {
|
|
23
|
+
if (/\.(js|mjs|cjs|json|css|wasm|node)$/i.test(importPath)) return _match;
|
|
24
|
+
return `${prefix}${importPath}.js${suffix}`;
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
: file.text;
|
|
28
|
+
|
|
29
|
+
// Compare with existing file — skip write if unchanged
|
|
30
|
+
try {
|
|
31
|
+
const existing = await fs.readFile(file.path, "utf-8");
|
|
32
|
+
if (existing === finalText) return;
|
|
33
|
+
} catch {
|
|
34
|
+
// File doesn't exist yet
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await fs.mkdir(path.dirname(file.path), { recursive: true });
|
|
38
|
+
await fs.writeFile(file.path, finalText);
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
/**
|
|
@@ -86,7 +83,7 @@ function hasSolidDependency(pkgDir: string): boolean {
|
|
|
86
83
|
* - target: node면 node20, 그 외는 chrome84
|
|
87
84
|
*/
|
|
88
85
|
export function createLibraryEsbuildOptions(options: LibraryEsbuildOptions): esbuild.BuildOptions {
|
|
89
|
-
const plugins: esbuild.Plugin[] = [
|
|
86
|
+
const plugins: esbuild.Plugin[] = [];
|
|
90
87
|
|
|
91
88
|
if (hasSolidDependency(options.pkgDir)) {
|
|
92
89
|
plugins.unshift(solidPlugin());
|
|
@@ -101,6 +98,7 @@ export function createLibraryEsbuildOptions(options: LibraryEsbuildOptions): esb
|
|
|
101
98
|
platform: options.target === "node" ? "node" : "browser",
|
|
102
99
|
target: options.target === "node" ? "node20" : "chrome84",
|
|
103
100
|
bundle: false,
|
|
101
|
+
write: false,
|
|
104
102
|
tsconfigRaw: { compilerOptions: options.compilerOptions as esbuild.TsconfigRaw["compilerOptions"] },
|
|
105
103
|
plugins,
|
|
106
104
|
};
|
|
@@ -10,7 +10,6 @@ type ErrorResult = PackageResult | BuildResult;
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* 에러만 출력한다.
|
|
13
|
-
* 성공한 빌드는 listr의 체크마크로 이미 표시되므로 별도 출력하지 않음.
|
|
14
13
|
* @param results 패키지별 빌드 결과 상태
|
|
15
14
|
*/
|
|
16
15
|
export function printErrors(results: Map<string, ErrorResult>): void {
|
|
@@ -35,7 +34,7 @@ export function printErrors(results: Map<string, ErrorResult>): void {
|
|
|
35
34
|
*/
|
|
36
35
|
export function printServers(results: Map<string, PackageResult>, serverClientsMap?: Map<string, string[]>): void {
|
|
37
36
|
// 서버 정보 수집
|
|
38
|
-
const servers = [...results.values()].filter((r) => r.status === "
|
|
37
|
+
const servers = [...results.values()].filter((r) => r.status === "running" && r.port != null);
|
|
39
38
|
|
|
40
39
|
// 서버 정보 출력 (있으면 앞에 빈 줄 추가)
|
|
41
40
|
if (servers.length > 0) {
|
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
1
3
|
import type { SdPackageConfig } from "../sd-config.types";
|
|
2
4
|
|
|
5
|
+
/**
|
|
6
|
+
* import.meta.dirname에서 상위로 올라가며 package.json을 찾아 패키지 루트를 반환한다.
|
|
7
|
+
*/
|
|
8
|
+
export function findPackageRoot(startDir: string): string {
|
|
9
|
+
let dir = startDir;
|
|
10
|
+
while (!fs.existsSync(path.join(dir, "package.json"))) {
|
|
11
|
+
const parent = path.dirname(dir);
|
|
12
|
+
if (parent === dir) throw new Error("package.json을 찾을 수 없습니다.");
|
|
13
|
+
dir = parent;
|
|
14
|
+
}
|
|
15
|
+
return dir;
|
|
16
|
+
}
|
|
17
|
+
|
|
3
18
|
/**
|
|
4
19
|
* 패키지명에서 watch scope 목록을 생성한다.
|
|
5
20
|
* - 패키지명의 scope (예: "@myapp/root" → "@myapp")
|
|
@@ -23,7 +38,7 @@ export interface PackageResult {
|
|
|
23
38
|
name: string;
|
|
24
39
|
target: string;
|
|
25
40
|
type: "build" | "dts" | "server" | "capacitor";
|
|
26
|
-
status: "success" | "error" | "
|
|
41
|
+
status: "success" | "error" | "running";
|
|
27
42
|
message?: string;
|
|
28
43
|
port?: number;
|
|
29
44
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { consola } from "consola";
|
|
3
|
+
|
|
4
|
+
interface RebuildManagerEvents {
|
|
5
|
+
batchComplete: [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
9
|
+
private _isRunning = false;
|
|
10
|
+
private readonly _pendingBuilds = new Map<string, { title: string; promise: Promise<void>; resolver: () => void }>();
|
|
11
|
+
private readonly _logger: ReturnType<typeof consola.withTag>;
|
|
12
|
+
|
|
13
|
+
constructor(logger: ReturnType<typeof consola.withTag>) {
|
|
14
|
+
super();
|
|
15
|
+
this._logger = logger;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
registerBuild(key: string, title: string): () => void {
|
|
19
|
+
let resolver!: () => void;
|
|
20
|
+
const promise = new Promise<void>((resolve) => {
|
|
21
|
+
resolver = resolve;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
this._pendingBuilds.set(key, { title, promise, resolver });
|
|
25
|
+
|
|
26
|
+
if (!this._isRunning) {
|
|
27
|
+
void Promise.resolve().then(() => void this._runBatch());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return resolver;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private async _runBatch(): Promise<void> {
|
|
34
|
+
if (this._isRunning || this._pendingBuilds.size === 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this._isRunning = true;
|
|
39
|
+
|
|
40
|
+
const batchBuilds = new Map(this._pendingBuilds);
|
|
41
|
+
this._pendingBuilds.clear();
|
|
42
|
+
|
|
43
|
+
const tasks = Array.from(batchBuilds.entries());
|
|
44
|
+
for (const [, { title }] of tasks) {
|
|
45
|
+
this._logger.debug(`리빌드 시작: ${title}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const results = await Promise.allSettled(tasks.map(([, { promise }]) => promise));
|
|
49
|
+
|
|
50
|
+
const failed = results.filter((r): r is PromiseRejectedResult => r.status === "rejected");
|
|
51
|
+
if (failed.length > 0) {
|
|
52
|
+
for (const result of failed) {
|
|
53
|
+
this._logger.error("리빌드 중 오류 발생", { error: String(result.reason) });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.emit("batchComplete");
|
|
58
|
+
|
|
59
|
+
this._isRunning = false;
|
|
60
|
+
|
|
61
|
+
if (this._pendingBuilds.size > 0) {
|
|
62
|
+
void this._runBatch();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -120,19 +120,15 @@ export interface WatchReplaceDepResult {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
*
|
|
123
|
+
* 프로젝트 루트와 workspace 패키지 경로 목록을 수집한다.
|
|
124
124
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* 3. 기존 symlink/디렉토리 제거 → 소스 경로를 복사 (node_modules, package.json, .cache, tests 제외)
|
|
125
|
+
* pnpm-workspace.yaml을 파싱하여 workspace 패키지들의 절대 경로를 수집한다.
|
|
126
|
+
* 파일이 없거나 파싱 실패 시 루트 경로만 반환한다.
|
|
128
127
|
*
|
|
129
128
|
* @param projectRoot - 프로젝트 루트 경로
|
|
130
|
-
* @
|
|
129
|
+
* @returns [루트, ...workspace 패키지 경로] 배열
|
|
131
130
|
*/
|
|
132
|
-
|
|
133
|
-
const logger = consola.withTag("sd:cli:replace-deps");
|
|
134
|
-
|
|
135
|
-
// 1. Workspace 패키지 경로 목록 수집
|
|
131
|
+
async function collectSearchRoots(projectRoot: string): Promise<string[]> {
|
|
136
132
|
const searchRoots = [projectRoot];
|
|
137
133
|
|
|
138
134
|
const workspaceYamlPath = path.join(projectRoot, "pnpm-workspace.yaml");
|
|
@@ -148,6 +144,25 @@ export async function setupReplaceDeps(projectRoot: string, replaceDeps: Record<
|
|
|
148
144
|
// pnpm-workspace.yaml가 없으면 루트만 처리
|
|
149
145
|
}
|
|
150
146
|
|
|
147
|
+
return searchRoots;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* replaceDeps 설정에 따라 node_modules 내 패키지를 소스 디렉토리로 복사 교체한다.
|
|
152
|
+
*
|
|
153
|
+
* 1. pnpm-workspace.yaml 파싱 → workspace 패키지 경로 목록
|
|
154
|
+
* 2. [루트, ...workspace 패키지]의 node_modules에서 매칭되는 패키지 찾기
|
|
155
|
+
* 3. 기존 symlink/디렉토리 제거 → 소스 경로를 복사 (node_modules, package.json, .cache, tests 제외)
|
|
156
|
+
*
|
|
157
|
+
* @param projectRoot - 프로젝트 루트 경로
|
|
158
|
+
* @param replaceDeps - sd.config.ts의 replaceDeps 설정
|
|
159
|
+
*/
|
|
160
|
+
export async function setupReplaceDeps(projectRoot: string, replaceDeps: Record<string, string>): Promise<void> {
|
|
161
|
+
const logger = consola.withTag("sd:cli:replace-deps");
|
|
162
|
+
|
|
163
|
+
// 1. Workspace 패키지 경로 목록 수집
|
|
164
|
+
const searchRoots = await collectSearchRoots(projectRoot);
|
|
165
|
+
|
|
151
166
|
// 2. 각 searchRoot의 node_modules에서 매칭되는 패키지 찾기
|
|
152
167
|
for (const searchRoot of searchRoots) {
|
|
153
168
|
const nodeModulesDir = path.join(searchRoot, "node_modules");
|
|
@@ -226,20 +241,7 @@ export async function watchReplaceDeps(
|
|
|
226
241
|
const entries: ReplaceDepEntry[] = [];
|
|
227
242
|
|
|
228
243
|
// 1. Workspace 패키지 경로 목록 수집
|
|
229
|
-
const searchRoots =
|
|
230
|
-
|
|
231
|
-
const workspaceYamlPath = path.join(projectRoot, "pnpm-workspace.yaml");
|
|
232
|
-
try {
|
|
233
|
-
const yamlContent = await fs.promises.readFile(workspaceYamlPath, "utf-8");
|
|
234
|
-
const workspaceGlobs = parseWorkspaceGlobs(yamlContent);
|
|
235
|
-
|
|
236
|
-
for (const pattern of workspaceGlobs) {
|
|
237
|
-
const dirs = await glob(pattern, { cwd: projectRoot, absolute: true });
|
|
238
|
-
searchRoots.push(...dirs);
|
|
239
|
-
}
|
|
240
|
-
} catch {
|
|
241
|
-
// pnpm-workspace.yaml가 없으면 루트만 처리
|
|
242
|
-
}
|
|
244
|
+
const searchRoots = await collectSearchRoots(projectRoot);
|
|
243
245
|
|
|
244
246
|
// 2. 각 searchRoot의 node_modules에서 매칭되는 패키지 찾기
|
|
245
247
|
for (const searchRoot of searchRoots) {
|