@simplysm/sd-cli 13.0.68 → 13.0.70
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 +10 -957
- package/dist/builders/BaseBuilder.d.ts +23 -23
- package/dist/builders/BaseBuilder.d.ts.map +1 -1
- package/dist/builders/BaseBuilder.js +15 -15
- package/dist/builders/DtsBuilder.d.ts +4 -4
- package/dist/builders/DtsBuilder.js +1 -1
- package/dist/builders/LibraryBuilder.d.ts +3 -3
- package/dist/builders/types.d.ts +10 -10
- package/dist/capacitor/capacitor.d.ts +36 -36
- package/dist/capacitor/capacitor.js +63 -63
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/add-client.d.ts +8 -8
- package/dist/commands/add-client.js +15 -15
- package/dist/commands/add-client.js.map +1 -1
- package/dist/commands/add-server.d.ts +9 -9
- package/dist/commands/add-server.js +13 -13
- package/dist/commands/add-server.js.map +1 -1
- package/dist/commands/build.d.ts +9 -9
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +9 -9
- package/dist/commands/device.d.ts +9 -9
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +17 -17
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/init.d.ts +6 -6
- package/dist/commands/init.js +12 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.d.ts +23 -23
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +25 -25
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/publish.d.ts +13 -13
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +61 -61
- 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/replace-deps.js.map +1 -1
- package/dist/commands/typecheck.d.ts +20 -20
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +20 -20
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/watch.d.ts +7 -7
- package/dist/electron/electron.d.ts +27 -27
- package/dist/electron/electron.js +32 -32
- package/dist/electron/electron.js.map +1 -1
- package/dist/infra/ResultCollector.d.ts +9 -9
- package/dist/infra/ResultCollector.js +5 -5
- package/dist/infra/SignalHandler.d.ts +7 -7
- package/dist/infra/SignalHandler.js +4 -4
- package/dist/infra/WorkerManager.d.ts +14 -14
- package/dist/infra/WorkerManager.js +11 -11
- package/dist/orchestrators/BuildOrchestrator.d.ts +19 -19
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +26 -26
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevOrchestrator.d.ts +25 -25
- package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevOrchestrator.js +30 -30
- package/dist/orchestrators/DevOrchestrator.js.map +1 -1
- package/dist/orchestrators/WatchOrchestrator.d.ts +13 -13
- package/dist/orchestrators/WatchOrchestrator.js +17 -17
- package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +2 -2
- package/dist/sd-cli-entry.js +38 -38
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.d.ts +2 -2
- package/dist/sd-cli.js +1 -1
- package/dist/sd-cli.js.map +1 -1
- package/dist/sd-config.types.d.ts +84 -84
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/build-env.d.ts +1 -1
- package/dist/utils/config-editor.d.ts +5 -5
- package/dist/utils/config-editor.js +2 -2
- package/dist/utils/config-editor.js.map +1 -1
- package/dist/utils/copy-public.d.ts +9 -9
- package/dist/utils/copy-src.d.ts +9 -9
- package/dist/utils/esbuild-config.d.ts +30 -30
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/output-utils.d.ts +6 -6
- package/dist/utils/package-utils.d.ts +6 -6
- package/dist/utils/package-utils.js +1 -1
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/rebuild-manager.js +3 -3
- package/dist/utils/rebuild-manager.js.map +1 -1
- package/dist/utils/replace-deps.d.ts +25 -25
- package/dist/utils/replace-deps.js +3 -3
- 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/sd-config.js.map +1 -1
- package/dist/utils/tailwind-config-deps.d.ts +3 -3
- package/dist/utils/template.d.ts +8 -8
- package/dist/utils/tsconfig.d.ts +16 -16
- package/dist/utils/tsconfig.js +2 -2
- package/dist/utils/tsconfig.js.map +1 -1
- package/dist/utils/typecheck-serialization.d.ts +8 -8
- package/dist/utils/vite-config.d.ts +8 -8
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +3 -3
- package/dist/utils/worker-events.d.ts +12 -12
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-utils.d.ts +3 -3
- package/dist/utils/worker-utils.js +2 -2
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/workers/client.worker.d.ts +14 -14
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +1 -1
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/dts.worker.d.ts +13 -13
- package/dist/workers/dts.worker.d.ts.map +1 -1
- package/dist/workers/dts.worker.js +3 -3
- package/dist/workers/dts.worker.js.map +1 -1
- package/dist/workers/library.worker.d.ts +12 -12
- package/dist/workers/library.worker.js +1 -1
- package/dist/workers/library.worker.js.map +1 -1
- package/dist/workers/lint.worker.d.ts +1 -1
- package/dist/workers/server-runtime.worker.d.ts +6 -6
- package/dist/workers/server-runtime.worker.js +6 -6
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/dist/workers/server.worker.d.ts +20 -20
- package/dist/workers/server.worker.d.ts.map +1 -1
- package/dist/workers/server.worker.js +6 -6
- package/dist/workers/server.worker.js.map +1 -1
- package/package.json +8 -7
- package/src/builders/BaseBuilder.ts +33 -33
- package/src/builders/DtsBuilder.ts +5 -5
- package/src/builders/LibraryBuilder.ts +9 -9
- package/src/builders/types.ts +10 -10
- package/src/capacitor/capacitor.ts +119 -119
- package/src/commands/add-client.ts +31 -31
- package/src/commands/add-server.ts +34 -34
- package/src/commands/build.ts +9 -9
- package/src/commands/check.ts +5 -5
- package/src/commands/dev.ts +9 -9
- package/src/commands/device.ts +30 -30
- package/src/commands/init.ts +25 -25
- package/src/commands/lint.ts +64 -64
- package/src/commands/publish.ts +139 -139
- package/src/commands/replace-deps.ts +4 -4
- package/src/commands/typecheck.ts +74 -74
- package/src/commands/watch.ts +7 -7
- package/src/electron/electron.ts +51 -51
- 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 +76 -76
- package/src/orchestrators/DevOrchestrator.ts +88 -88
- package/src/orchestrators/WatchOrchestrator.ts +39 -39
- package/src/sd-cli-entry.ts +43 -43
- package/src/sd-cli.ts +15 -15
- package/src/sd-config.types.ts +85 -85
- package/src/utils/build-env.ts +1 -1
- package/src/utils/config-editor.ts +19 -19
- package/src/utils/copy-public.ts +17 -17
- package/src/utils/copy-src.ts +11 -11
- package/src/utils/esbuild-config.ts +33 -33
- package/src/utils/output-utils.ts +11 -11
- package/src/utils/package-utils.ts +12 -12
- package/src/utils/rebuild-manager.ts +3 -3
- package/src/utils/replace-deps.ts +361 -361
- package/src/utils/sd-config.ts +44 -44
- package/src/utils/tailwind-config-deps.ts +98 -98
- package/src/utils/template.ts +56 -56
- package/src/utils/tsconfig.ts +127 -127
- package/src/utils/typecheck-serialization.ts +86 -86
- package/src/utils/vite-config.ts +341 -341
- package/src/utils/worker-events.ts +16 -16
- package/src/utils/worker-utils.ts +45 -45
- package/src/workers/client.worker.ts +34 -34
- package/src/workers/dts.worker.ts +467 -467
- package/src/workers/library.worker.ts +314 -314
- package/src/workers/lint.worker.ts +16 -16
- package/src/workers/server-runtime.worker.ts +157 -157
- package/src/workers/server.worker.ts +572 -572
- 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/tests/config-editor.spec.ts +160 -0
- package/tests/copy-src.spec.ts +50 -0
- package/tests/get-compiler-options-for-package.spec.ts +139 -0
- package/tests/get-package-source-files.spec.ts +181 -0
- package/tests/get-types-from-package-json.spec.ts +107 -0
- package/tests/infra/ResultCollector.spec.ts +39 -0
- package/tests/infra/SignalHandler.spec.ts +38 -0
- package/tests/infra/WorkerManager.spec.ts +97 -0
- package/tests/load-ignore-patterns.spec.ts +188 -0
- package/tests/load-sd-config.spec.ts +137 -0
- package/tests/package-utils.spec.ts +188 -0
- package/tests/parse-root-tsconfig.spec.ts +89 -0
- package/tests/replace-deps.spec.ts +308 -0
- package/tests/run-lint.spec.ts +415 -0
- package/tests/run-typecheck.spec.ts +653 -0
- package/tests/run-watch.spec.ts +75 -0
- package/tests/sd-cli.spec.ts +330 -0
- package/tests/tailwind-config-deps.spec.ts +30 -0
- package/tests/template.spec.ts +70 -0
- package/tests/utils/rebuild-manager.spec.ts +43 -0
- package/tests/write-changed-output-files.spec.ts +97 -0
|
@@ -1,314 +1,314 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import esbuild from "esbuild";
|
|
3
|
-
import { createWorker, FsWatcher } from "@simplysm/core-node";
|
|
4
|
-
import { errorMessage } from "@simplysm/core-common";
|
|
5
|
-
import { consola } from "consola";
|
|
6
|
-
import type { SdBuildPackageConfig } from "../sd-config.types";
|
|
7
|
-
import {
|
|
8
|
-
parseRootTsconfig,
|
|
9
|
-
getPackageSourceFiles,
|
|
10
|
-
getCompilerOptionsForPackage,
|
|
11
|
-
} from "../utils/tsconfig";
|
|
12
|
-
import {
|
|
13
|
-
createLibraryEsbuildOptions,
|
|
14
|
-
getTypecheckEnvFromTarget,
|
|
15
|
-
writeChangedOutputFiles,
|
|
16
|
-
} from "../utils/esbuild-config";
|
|
17
|
-
import { registerCleanupHandlers, createOnceGuard } from "../utils/worker-utils";
|
|
18
|
-
|
|
19
|
-
//#region Types
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Library
|
|
23
|
-
*/
|
|
24
|
-
export interface LibraryBuildInfo {
|
|
25
|
-
name: string;
|
|
26
|
-
config: SdBuildPackageConfig;
|
|
27
|
-
cwd: string;
|
|
28
|
-
pkgDir: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Library
|
|
33
|
-
*/
|
|
34
|
-
export interface LibraryBuildResult {
|
|
35
|
-
success: boolean;
|
|
36
|
-
errors?: string[];
|
|
37
|
-
warnings?: string[];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Library
|
|
42
|
-
*/
|
|
43
|
-
export interface LibraryWatchInfo {
|
|
44
|
-
name: string;
|
|
45
|
-
config: SdBuildPackageConfig;
|
|
46
|
-
cwd: string;
|
|
47
|
-
pkgDir: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
*/
|
|
53
|
-
export interface LibraryBuildEvent {
|
|
54
|
-
success: boolean;
|
|
55
|
-
errors?: string[];
|
|
56
|
-
warnings?: string[];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
*/
|
|
62
|
-
export interface LibraryErrorEvent {
|
|
63
|
-
message: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Worker
|
|
68
|
-
*/
|
|
69
|
-
export interface LibraryWorkerEvents extends Record<string, unknown> {
|
|
70
|
-
buildStart: Record<string, never>;
|
|
71
|
-
build: LibraryBuildEvent;
|
|
72
|
-
error: LibraryErrorEvent;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
//#endregion
|
|
76
|
-
|
|
77
|
-
//#region
|
|
78
|
-
|
|
79
|
-
const logger = consola.withTag("sd:cli:library:worker");
|
|
80
|
-
|
|
81
|
-
/** esbuild build context (
|
|
82
|
-
let esbuildContext: esbuild.BuildContext | undefined;
|
|
83
|
-
|
|
84
|
-
/** FsWatcher (
|
|
85
|
-
let fsWatcher: FsWatcher | undefined;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
*
|
|
89
|
-
*/
|
|
90
|
-
async function cleanup(): Promise<void> {
|
|
91
|
-
//
|
|
92
|
-
// (
|
|
93
|
-
const contextToDispose = esbuildContext;
|
|
94
|
-
esbuildContext = undefined;
|
|
95
|
-
|
|
96
|
-
const watcherToClose = fsWatcher;
|
|
97
|
-
fsWatcher = undefined;
|
|
98
|
-
|
|
99
|
-
await Promise.all([contextToDispose?.dispose(), watcherToClose?.close()]);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
registerCleanupHandlers(cleanup, logger);
|
|
106
|
-
|
|
107
|
-
//#endregion
|
|
108
|
-
|
|
109
|
-
//#region Worker
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
*
|
|
113
|
-
*/
|
|
114
|
-
async function build(info: LibraryBuildInfo): Promise<LibraryBuildResult> {
|
|
115
|
-
try {
|
|
116
|
-
// tsconfig
|
|
117
|
-
const parsedConfig = parseRootTsconfig(info.cwd);
|
|
118
|
-
const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
const env = getTypecheckEnvFromTarget(info.config.target);
|
|
122
|
-
const compilerOptions = await getCompilerOptionsForPackage(
|
|
123
|
-
parsedConfig.options,
|
|
124
|
-
env,
|
|
125
|
-
info.pkgDir,
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
// esbuild
|
|
129
|
-
const esbuildOptions = createLibraryEsbuildOptions({
|
|
130
|
-
pkgDir: info.pkgDir,
|
|
131
|
-
entryPoints,
|
|
132
|
-
target: info.config.target,
|
|
133
|
-
compilerOptions,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
const result = await esbuild.build(esbuildOptions);
|
|
137
|
-
if (result.outputFiles) {
|
|
138
|
-
await writeChangedOutputFiles(result.outputFiles);
|
|
139
|
-
}
|
|
140
|
-
const errors = result.errors.map((e) => e.text);
|
|
141
|
-
const warnings = result.warnings.map((w) => w.text);
|
|
142
|
-
return {
|
|
143
|
-
success: result.errors.length === 0,
|
|
144
|
-
errors: errors.length > 0 ? errors : undefined,
|
|
145
|
-
warnings: warnings.length > 0 ? warnings : undefined,
|
|
146
|
-
};
|
|
147
|
-
} catch (err) {
|
|
148
|
-
return {
|
|
149
|
-
success: false,
|
|
150
|
-
errors: [errorMessage(err)],
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const guardStartWatch = createOnceGuard("startWatch");
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* esbuild context
|
|
159
|
-
*/
|
|
160
|
-
async function createAndBuildContext(
|
|
161
|
-
pkgDir: string,
|
|
162
|
-
cwd: string,
|
|
163
|
-
config: SdBuildPackageConfig,
|
|
164
|
-
isFirstBuild: boolean,
|
|
165
|
-
resolveFirstBuild?: () => void,
|
|
166
|
-
): Promise<esbuild.BuildContext> {
|
|
167
|
-
// tsconfig
|
|
168
|
-
const parsedConfig = parseRootTsconfig(cwd);
|
|
169
|
-
const entryPoints = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
170
|
-
|
|
171
|
-
//
|
|
172
|
-
const env = getTypecheckEnvFromTarget(config.target);
|
|
173
|
-
const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, env, pkgDir);
|
|
174
|
-
|
|
175
|
-
// esbuild
|
|
176
|
-
const baseOptions = createLibraryEsbuildOptions({
|
|
177
|
-
pkgDir,
|
|
178
|
-
entryPoints,
|
|
179
|
-
target: config.target,
|
|
180
|
-
compilerOptions,
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
let isBuildFirstTime = isFirstBuild;
|
|
184
|
-
|
|
185
|
-
// context
|
|
186
|
-
const context = await esbuild.context({
|
|
187
|
-
...baseOptions,
|
|
188
|
-
plugins: [
|
|
189
|
-
...(baseOptions.plugins ?? []),
|
|
190
|
-
{
|
|
191
|
-
name: "watch-notify",
|
|
192
|
-
setup(pluginBuild) {
|
|
193
|
-
pluginBuild.onStart(() => {
|
|
194
|
-
sender.send("buildStart", {});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
pluginBuild.onEnd(async (result) => {
|
|
198
|
-
// Write only changed files to disk
|
|
199
|
-
if (result.outputFiles) {
|
|
200
|
-
await writeChangedOutputFiles(result.outputFiles);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const errors = result.errors.map((e) => e.text);
|
|
204
|
-
const warnings = result.warnings.map((w) => w.text);
|
|
205
|
-
const success = result.errors.length === 0;
|
|
206
|
-
|
|
207
|
-
sender.send("build", {
|
|
208
|
-
success,
|
|
209
|
-
errors: errors.length > 0 ? errors : undefined,
|
|
210
|
-
warnings: warnings.length > 0 ? warnings : undefined,
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
if (isBuildFirstTime) {
|
|
214
|
-
isBuildFirstTime = false;
|
|
215
|
-
resolveFirstBuild?.();
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
],
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
//
|
|
224
|
-
await context.rebuild();
|
|
225
|
-
|
|
226
|
-
return context;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* watch
|
|
231
|
-
* @remarks
|
|
232
|
-
* @throws
|
|
233
|
-
*/
|
|
234
|
-
async function startWatch(info: LibraryWatchInfo): Promise<void> {
|
|
235
|
-
guardStartWatch();
|
|
236
|
-
|
|
237
|
-
try {
|
|
238
|
-
//
|
|
239
|
-
let resolveFirstBuild!: () => void;
|
|
240
|
-
const firstBuildPromise = new Promise<void>((resolve) => {
|
|
241
|
-
resolveFirstBuild = resolve;
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
//
|
|
245
|
-
esbuildContext = await createAndBuildContext(
|
|
246
|
-
info.pkgDir,
|
|
247
|
-
info.cwd,
|
|
248
|
-
info.config,
|
|
249
|
-
true,
|
|
250
|
-
resolveFirstBuild,
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
//
|
|
254
|
-
await firstBuildPromise;
|
|
255
|
-
|
|
256
|
-
// FsWatcher
|
|
257
|
-
const srcPattern = path.join(info.pkgDir, "src", "**", "*.{ts,tsx}");
|
|
258
|
-
fsWatcher = await FsWatcher.watch([srcPattern]);
|
|
259
|
-
|
|
260
|
-
//
|
|
261
|
-
fsWatcher.onChange({ delay: 300 }, async (changes) => {
|
|
262
|
-
try {
|
|
263
|
-
// add
|
|
264
|
-
const hasAddOrUnlink = changes.some((c) => c.event === "add" || c.event === "unlink");
|
|
265
|
-
|
|
266
|
-
if (hasAddOrUnlink) {
|
|
267
|
-
//
|
|
268
|
-
logger.debug("
|
|
269
|
-
|
|
270
|
-
const oldContext = esbuildContext;
|
|
271
|
-
esbuildContext = await createAndBuildContext(info.pkgDir, info.cwd, info.config, false);
|
|
272
|
-
|
|
273
|
-
if (oldContext != null) {
|
|
274
|
-
await oldContext.dispose();
|
|
275
|
-
}
|
|
276
|
-
} else {
|
|
277
|
-
//
|
|
278
|
-
if (esbuildContext != null) {
|
|
279
|
-
await esbuildContext.rebuild();
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
} catch (err) {
|
|
283
|
-
sender.send("error", {
|
|
284
|
-
message: errorMessage(err),
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
} catch (err) {
|
|
289
|
-
sender.send("error", {
|
|
290
|
-
message: errorMessage(err),
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* watch
|
|
297
|
-
* @remarks esbuild context
|
|
298
|
-
*/
|
|
299
|
-
async function stopWatch(): Promise<void> {
|
|
300
|
-
await cleanup();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const sender = createWorker<
|
|
304
|
-
{ build: typeof build; startWatch: typeof startWatch; stopWatch: typeof stopWatch },
|
|
305
|
-
LibraryWorkerEvents
|
|
306
|
-
>({
|
|
307
|
-
build,
|
|
308
|
-
startWatch,
|
|
309
|
-
stopWatch,
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
export default sender;
|
|
313
|
-
|
|
314
|
-
//#endregion
|
|
1
|
+
import path from "path";
|
|
2
|
+
import esbuild from "esbuild";
|
|
3
|
+
import { createWorker, FsWatcher } from "@simplysm/core-node";
|
|
4
|
+
import { errorMessage } from "@simplysm/core-common";
|
|
5
|
+
import { consola } from "consola";
|
|
6
|
+
import type { SdBuildPackageConfig } from "../sd-config.types";
|
|
7
|
+
import {
|
|
8
|
+
parseRootTsconfig,
|
|
9
|
+
getPackageSourceFiles,
|
|
10
|
+
getCompilerOptionsForPackage,
|
|
11
|
+
} from "../utils/tsconfig";
|
|
12
|
+
import {
|
|
13
|
+
createLibraryEsbuildOptions,
|
|
14
|
+
getTypecheckEnvFromTarget,
|
|
15
|
+
writeChangedOutputFiles,
|
|
16
|
+
} from "../utils/esbuild-config";
|
|
17
|
+
import { registerCleanupHandlers, createOnceGuard } from "../utils/worker-utils";
|
|
18
|
+
|
|
19
|
+
//#region Types
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Library build info (for one-time build)
|
|
23
|
+
*/
|
|
24
|
+
export interface LibraryBuildInfo {
|
|
25
|
+
name: string;
|
|
26
|
+
config: SdBuildPackageConfig;
|
|
27
|
+
cwd: string;
|
|
28
|
+
pkgDir: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Library build result
|
|
33
|
+
*/
|
|
34
|
+
export interface LibraryBuildResult {
|
|
35
|
+
success: boolean;
|
|
36
|
+
errors?: string[];
|
|
37
|
+
warnings?: string[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Library watch info
|
|
42
|
+
*/
|
|
43
|
+
export interface LibraryWatchInfo {
|
|
44
|
+
name: string;
|
|
45
|
+
config: SdBuildPackageConfig;
|
|
46
|
+
cwd: string;
|
|
47
|
+
pkgDir: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Build event
|
|
52
|
+
*/
|
|
53
|
+
export interface LibraryBuildEvent {
|
|
54
|
+
success: boolean;
|
|
55
|
+
errors?: string[];
|
|
56
|
+
warnings?: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Error event
|
|
61
|
+
*/
|
|
62
|
+
export interface LibraryErrorEvent {
|
|
63
|
+
message: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Worker event types
|
|
68
|
+
*/
|
|
69
|
+
export interface LibraryWorkerEvents extends Record<string, unknown> {
|
|
70
|
+
buildStart: Record<string, never>;
|
|
71
|
+
build: LibraryBuildEvent;
|
|
72
|
+
error: LibraryErrorEvent;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
|
|
77
|
+
//#region Resource Management
|
|
78
|
+
|
|
79
|
+
const logger = consola.withTag("sd:cli:library:worker");
|
|
80
|
+
|
|
81
|
+
/** esbuild build context (to be cleaned up) */
|
|
82
|
+
let esbuildContext: esbuild.BuildContext | undefined;
|
|
83
|
+
|
|
84
|
+
/** FsWatcher (to be cleaned up) */
|
|
85
|
+
let fsWatcher: FsWatcher | undefined;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Clean up resources
|
|
89
|
+
*/
|
|
90
|
+
async function cleanup(): Promise<void> {
|
|
91
|
+
// Capture global variables to temporary variables and initialize
|
|
92
|
+
// (other calls can modify global variables while Promise.all is waiting)
|
|
93
|
+
const contextToDispose = esbuildContext;
|
|
94
|
+
esbuildContext = undefined;
|
|
95
|
+
|
|
96
|
+
const watcherToClose = fsWatcher;
|
|
97
|
+
fsWatcher = undefined;
|
|
98
|
+
|
|
99
|
+
await Promise.all([contextToDispose?.dispose(), watcherToClose?.close()]);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Clean up resources before process termination (SIGTERM/SIGINT)
|
|
103
|
+
// Note: worker.terminate() does not call these handlers and terminates immediately.
|
|
104
|
+
// However, normal shutdown in watch mode is handled via SIGINT/SIGTERM from the main process, so this is fine.
|
|
105
|
+
registerCleanupHandlers(cleanup, logger);
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
|
|
109
|
+
//#region Worker
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* One-time build
|
|
113
|
+
*/
|
|
114
|
+
async function build(info: LibraryBuildInfo): Promise<LibraryBuildResult> {
|
|
115
|
+
try {
|
|
116
|
+
// Parse tsconfig
|
|
117
|
+
const parsedConfig = parseRootTsconfig(info.cwd);
|
|
118
|
+
const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);
|
|
119
|
+
|
|
120
|
+
// Create compilerOptions per target
|
|
121
|
+
const env = getTypecheckEnvFromTarget(info.config.target);
|
|
122
|
+
const compilerOptions = await getCompilerOptionsForPackage(
|
|
123
|
+
parsedConfig.options,
|
|
124
|
+
env,
|
|
125
|
+
info.pkgDir,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// One-time esbuild
|
|
129
|
+
const esbuildOptions = createLibraryEsbuildOptions({
|
|
130
|
+
pkgDir: info.pkgDir,
|
|
131
|
+
entryPoints,
|
|
132
|
+
target: info.config.target,
|
|
133
|
+
compilerOptions,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const result = await esbuild.build(esbuildOptions);
|
|
137
|
+
if (result.outputFiles) {
|
|
138
|
+
await writeChangedOutputFiles(result.outputFiles);
|
|
139
|
+
}
|
|
140
|
+
const errors = result.errors.map((e) => e.text);
|
|
141
|
+
const warnings = result.warnings.map((w) => w.text);
|
|
142
|
+
return {
|
|
143
|
+
success: result.errors.length === 0,
|
|
144
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
145
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
146
|
+
};
|
|
147
|
+
} catch (err) {
|
|
148
|
+
return {
|
|
149
|
+
success: false,
|
|
150
|
+
errors: [errorMessage(err)],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const guardStartWatch = createOnceGuard("startWatch");
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Create esbuild context and perform initial build
|
|
159
|
+
*/
|
|
160
|
+
async function createAndBuildContext(
|
|
161
|
+
pkgDir: string,
|
|
162
|
+
cwd: string,
|
|
163
|
+
config: SdBuildPackageConfig,
|
|
164
|
+
isFirstBuild: boolean,
|
|
165
|
+
resolveFirstBuild?: () => void,
|
|
166
|
+
): Promise<esbuild.BuildContext> {
|
|
167
|
+
// Parse tsconfig
|
|
168
|
+
const parsedConfig = parseRootTsconfig(cwd);
|
|
169
|
+
const entryPoints = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
170
|
+
|
|
171
|
+
// Create compilerOptions per target
|
|
172
|
+
const env = getTypecheckEnvFromTarget(config.target);
|
|
173
|
+
const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, env, pkgDir);
|
|
174
|
+
|
|
175
|
+
// Create esbuild options
|
|
176
|
+
const baseOptions = createLibraryEsbuildOptions({
|
|
177
|
+
pkgDir,
|
|
178
|
+
entryPoints,
|
|
179
|
+
target: config.target,
|
|
180
|
+
compilerOptions,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
let isBuildFirstTime = isFirstBuild;
|
|
184
|
+
|
|
185
|
+
// Create context + add watch-notify plugin
|
|
186
|
+
const context = await esbuild.context({
|
|
187
|
+
...baseOptions,
|
|
188
|
+
plugins: [
|
|
189
|
+
...(baseOptions.plugins ?? []),
|
|
190
|
+
{
|
|
191
|
+
name: "watch-notify",
|
|
192
|
+
setup(pluginBuild) {
|
|
193
|
+
pluginBuild.onStart(() => {
|
|
194
|
+
sender.send("buildStart", {});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
pluginBuild.onEnd(async (result) => {
|
|
198
|
+
// Write only changed files to disk
|
|
199
|
+
if (result.outputFiles) {
|
|
200
|
+
await writeChangedOutputFiles(result.outputFiles);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const errors = result.errors.map((e) => e.text);
|
|
204
|
+
const warnings = result.warnings.map((w) => w.text);
|
|
205
|
+
const success = result.errors.length === 0;
|
|
206
|
+
|
|
207
|
+
sender.send("build", {
|
|
208
|
+
success,
|
|
209
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
210
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
if (isBuildFirstTime) {
|
|
214
|
+
isBuildFirstTime = false;
|
|
215
|
+
resolveFirstBuild?.();
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Initial build
|
|
224
|
+
await context.rebuild();
|
|
225
|
+
|
|
226
|
+
return context;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Start watch
|
|
231
|
+
* @remarks This function should be called only once per Worker.
|
|
232
|
+
* @throws If watch has already been started
|
|
233
|
+
*/
|
|
234
|
+
async function startWatch(info: LibraryWatchInfo): Promise<void> {
|
|
235
|
+
guardStartWatch();
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
// Promise to wait for first build completion
|
|
239
|
+
let resolveFirstBuild!: () => void;
|
|
240
|
+
const firstBuildPromise = new Promise<void>((resolve) => {
|
|
241
|
+
resolveFirstBuild = resolve;
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Create initial esbuild context and build
|
|
245
|
+
esbuildContext = await createAndBuildContext(
|
|
246
|
+
info.pkgDir,
|
|
247
|
+
info.cwd,
|
|
248
|
+
info.config,
|
|
249
|
+
true,
|
|
250
|
+
resolveFirstBuild,
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
// Wait for first build completion
|
|
254
|
+
await firstBuildPromise;
|
|
255
|
+
|
|
256
|
+
// Start FsWatcher (watch src/**/*.{ts,tsx})
|
|
257
|
+
const srcPattern = path.join(info.pkgDir, "src", "**", "*.{ts,tsx}");
|
|
258
|
+
fsWatcher = await FsWatcher.watch([srcPattern]);
|
|
259
|
+
|
|
260
|
+
// Handle file changes
|
|
261
|
+
fsWatcher.onChange({ delay: 300 }, async (changes) => {
|
|
262
|
+
try {
|
|
263
|
+
// Check if there are add or unlink events
|
|
264
|
+
const hasAddOrUnlink = changes.some((c) => c.event === "add" || c.event === "unlink");
|
|
265
|
+
|
|
266
|
+
if (hasAddOrUnlink) {
|
|
267
|
+
// Entry points have changed, recreate context
|
|
268
|
+
logger.debug("File add/remove detected, recreating context");
|
|
269
|
+
|
|
270
|
+
const oldContext = esbuildContext;
|
|
271
|
+
esbuildContext = await createAndBuildContext(info.pkgDir, info.cwd, info.config, false);
|
|
272
|
+
|
|
273
|
+
if (oldContext != null) {
|
|
274
|
+
await oldContext.dispose();
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
// Only file content changed (change event)
|
|
278
|
+
if (esbuildContext != null) {
|
|
279
|
+
await esbuildContext.rebuild();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
sender.send("error", {
|
|
284
|
+
message: errorMessage(err),
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
} catch (err) {
|
|
289
|
+
sender.send("error", {
|
|
290
|
+
message: errorMessage(err),
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Stop watch
|
|
297
|
+
* @remarks Cleans up esbuild context.
|
|
298
|
+
*/
|
|
299
|
+
async function stopWatch(): Promise<void> {
|
|
300
|
+
await cleanup();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const sender = createWorker<
|
|
304
|
+
{ build: typeof build; startWatch: typeof startWatch; stopWatch: typeof stopWatch },
|
|
305
|
+
LibraryWorkerEvents
|
|
306
|
+
>({
|
|
307
|
+
build,
|
|
308
|
+
startWatch,
|
|
309
|
+
stopWatch,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
export default sender;
|
|
313
|
+
|
|
314
|
+
//#endregion
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { createWorker } from "@simplysm/core-node";
|
|
2
|
-
import { executeLint, type LintOptions, type LintResult } from "../commands/lint";
|
|
3
|
-
|
|
4
|
-
//#region Worker
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Lint worker.
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
async function lint(options: LintOptions): Promise<LintResult> {
|
|
11
|
-
return executeLint(options);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default createWorker({ lint });
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
1
|
+
import { createWorker } from "@simplysm/core-node";
|
|
2
|
+
import { executeLint, type LintOptions, type LintResult } from "../commands/lint";
|
|
3
|
+
|
|
4
|
+
//#region Worker
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lint worker.
|
|
8
|
+
* Worker to run lint in separate thread from check command and BuildOrchestrator
|
|
9
|
+
*/
|
|
10
|
+
async function lint(options: LintOptions): Promise<LintResult> {
|
|
11
|
+
return executeLint(options);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default createWorker({ lint });
|
|
15
|
+
|
|
16
|
+
//#endregion
|