@simplysm/sd-cli 13.0.0-beta.27 → 13.0.0-beta.28
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/dist/utils/esbuild-config.d.ts +9 -0
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +42 -0
- package/dist/utils/esbuild-config.js.map +2 -2
- package/dist/workers/server.worker.d.ts.map +1 -1
- package/dist/workers/server.worker.js +13 -3
- package/dist/workers/server.worker.js.map +2 -2
- package/package.json +4 -4
- 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
|
@@ -20,6 +20,8 @@ export interface ServerEsbuildOptions {
|
|
|
20
20
|
entryPoints: string[];
|
|
21
21
|
compilerOptions: Record<string, unknown>;
|
|
22
22
|
env?: Record<string, string>;
|
|
23
|
+
/** 번들에서 제외할 외부 모듈 */
|
|
24
|
+
external?: string[];
|
|
23
25
|
}
|
|
24
26
|
/**
|
|
25
27
|
* Library용 esbuild 설정 생성
|
|
@@ -46,4 +48,11 @@ export declare function createServerEsbuildOptions(options: ServerEsbuildOptions
|
|
|
46
48
|
* (neutral 패키지는 Node/브라우저 공용이지만, 빌드 시에는 browser 환경 기준으로 처리)
|
|
47
49
|
*/
|
|
48
50
|
export declare function getTypecheckEnvFromTarget(target: "node" | "browser" | "neutral"): TypecheckEnv;
|
|
51
|
+
/**
|
|
52
|
+
* 의존성 트리에서 미설치 optional peer dep 수집
|
|
53
|
+
*
|
|
54
|
+
* 서버 빌드(bundle: true) 시 설치되지 않은 optional peer dependency를
|
|
55
|
+
* esbuild external로 지정하여 빌드 실패를 방지한다.
|
|
56
|
+
*/
|
|
57
|
+
export declare function collectUninstalledOptionalPeerDeps(pkgDir: string): string[];
|
|
49
58
|
//# sourceMappingURL=esbuild-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esbuild-config.d.ts","sourceRoot":"","sources":["../../src/utils/esbuild-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"esbuild-config.d.ts","sourceRoot":"","sources":["../../src/utils/esbuild-config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAsC/C;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACvC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAYhG;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAuB9F;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAE9F;AAUD;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAU3E"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
2
3
|
import fs from "fs/promises";
|
|
4
|
+
import { createRequire } from "module";
|
|
3
5
|
import { glob } from "glob";
|
|
4
6
|
function esmRelativeImportPlugin(outdir) {
|
|
5
7
|
return {
|
|
@@ -58,6 +60,7 @@ function createServerEsbuildOptions(options) {
|
|
|
58
60
|
banner: {
|
|
59
61
|
js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
|
|
60
62
|
},
|
|
63
|
+
external: options.external,
|
|
61
64
|
define,
|
|
62
65
|
tsconfigRaw: { compilerOptions: options.compilerOptions }
|
|
63
66
|
};
|
|
@@ -65,7 +68,46 @@ function createServerEsbuildOptions(options) {
|
|
|
65
68
|
function getTypecheckEnvFromTarget(target) {
|
|
66
69
|
return target === "node" ? "node" : "browser";
|
|
67
70
|
}
|
|
71
|
+
function collectUninstalledOptionalPeerDeps(pkgDir) {
|
|
72
|
+
const external = /* @__PURE__ */ new Set();
|
|
73
|
+
const visited = /* @__PURE__ */ new Set();
|
|
74
|
+
const pkgJson = JSON.parse(readFileSync(path.join(pkgDir, "package.json"), "utf-8"));
|
|
75
|
+
for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
|
|
76
|
+
scanOptionalPeerDeps(dep, pkgDir, external, visited);
|
|
77
|
+
}
|
|
78
|
+
return [...external];
|
|
79
|
+
}
|
|
80
|
+
function scanOptionalPeerDeps(pkgName, resolveDir, external, visited) {
|
|
81
|
+
if (visited.has(pkgName)) return;
|
|
82
|
+
visited.add(pkgName);
|
|
83
|
+
const req = createRequire(path.join(resolveDir, "noop.js"));
|
|
84
|
+
let pkgJsonPath;
|
|
85
|
+
try {
|
|
86
|
+
pkgJsonPath = req.resolve(`${pkgName}/package.json`);
|
|
87
|
+
} catch {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const depDir = path.dirname(pkgJsonPath);
|
|
91
|
+
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
92
|
+
if (pkgJson.peerDependenciesMeta != null) {
|
|
93
|
+
const peerDeps = pkgJson.peerDependencies ?? {};
|
|
94
|
+
const depReq = createRequire(path.join(depDir, "noop.js"));
|
|
95
|
+
for (const [name, meta] of Object.entries(pkgJson.peerDependenciesMeta)) {
|
|
96
|
+
if (meta.optional === true && name in peerDeps) {
|
|
97
|
+
try {
|
|
98
|
+
depReq.resolve(name);
|
|
99
|
+
} catch {
|
|
100
|
+
external.add(name);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
|
|
106
|
+
scanOptionalPeerDeps(dep, depDir, external, visited);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
68
109
|
export {
|
|
110
|
+
collectUninstalledOptionalPeerDeps,
|
|
69
111
|
createLibraryEsbuildOptions,
|
|
70
112
|
createServerEsbuildOptions,
|
|
71
113
|
getTypecheckEnvFromTarget
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/esbuild-config.ts"],
|
|
4
|
-
"sourcesContent": ["import path from \"path\";\nimport fs from \"fs/promises\";\nimport { glob } from \"glob\";\nimport type esbuild from \"esbuild\";\nimport type { TypecheckEnv } from \"./tsconfig\";\n\n/**\n * ESM \uC0C1\uB300 import \uACBD\uB85C\uC5D0 .js \uD655\uC7A5\uC790\uB97C \uCD94\uAC00\uD558\uB294 esbuild \uD50C\uB7EC\uADF8\uC778.\n *\n * bundle: false \uBAA8\uB4DC\uC5D0\uC11C esbuild\uB294 import \uACBD\uB85C\uB97C \uADF8\uB300\uB85C \uC720\uC9C0\uD558\uBBC0\uB85C,\n * Node.js ESM\uC5D0\uC11C \uC9C1\uC811 \uC2E4\uD589 \uC2DC \uD655\uC7A5\uC790 \uB204\uB77D\uC73C\uB85C \uBAA8\uB4C8\uC744 \uCC3E\uC9C0 \uBABB\uD558\uB294 \uBB38\uC81C\uB97C \uD574\uACB0\uD55C\uB2E4.\n */\nfunction esmRelativeImportPlugin(outdir: string): esbuild.Plugin {\n return {\n name: \"esm-relative-import\",\n setup(build) {\n build.onEnd(async () => {\n const files = await glob(\"**/*.js\", { cwd: outdir });\n\n await Promise.all(\n files.map(async (file) => {\n const filePath = path.join(outdir, file);\n const content = await fs.readFile(filePath, \"utf-8\");\n\n const rewritten = content.replace(\n /((?:from|import)\\s*[\"'])(\\.\\.?\\/[^\"']*?)([\"'])/g,\n (_match, prefix: string, importPath: string, suffix: string) => {\n if (/\\.(js|mjs|cjs|json|css|wasm|node)$/i.test(importPath)) return _match;\n return `${prefix}${importPath}.js${suffix}`;\n },\n );\n\n if (rewritten !== content) {\n await fs.writeFile(filePath, rewritten);\n }\n }),\n );\n });\n },\n };\n}\n\n/**\n * Library \uBE4C\uB4DC\uC6A9 esbuild \uC635\uC158\n * - bundle: false (\uAC1C\uBCC4 \uD30C\uC77C \uD2B8\uB79C\uC2A4\uD30C\uC77C)\n * - platform: target\uC5D0 \uB530\uB77C node \uB610\uB294 browser\n */\nexport interface LibraryEsbuildOptions {\n pkgDir: string;\n entryPoints: string[];\n target: \"node\" | \"browser\" | \"neutral\";\n compilerOptions: Record<string, unknown>;\n}\n\n/**\n * Server \uBE4C\uB4DC\uC6A9 esbuild \uC635\uC158\n * - bundle: true (\uBAA8\uB4E0 \uC758\uC874\uC131 \uD3EC\uD568\uD55C \uB2E8\uC77C \uBC88\uB4E4)\n */\nexport interface ServerEsbuildOptions {\n pkgDir: string;\n entryPoints: string[];\n compilerOptions: Record<string, unknown>;\n env?: Record<string, string>;\n}\n\n/**\n * Library\uC6A9 esbuild \uC124\uC815 \uC0DD\uC131\n *\n * node/browser/neutral \uD0C0\uAC9F\uC758 \uB77C\uC774\uBE0C\uB7EC\uB9AC \uD328\uD0A4\uC9C0 \uBE4C\uB4DC\uC5D0 \uC0AC\uC6A9\uD569\uB2C8\uB2E4.\n * - bundle: false (\uAC1C\uBCC4 \uD30C\uC77C\uC744 \uAC01\uAC01 \uD2B8\uB79C\uC2A4\uD30C\uC77C)\n * - platform: target\uC774 node\uBA74 node, \uADF8 \uC678\uB294 browser\n * - target: node\uBA74 node20, \uADF8 \uC678\uB294 chrome84\n */\nexport function createLibraryEsbuildOptions(options: LibraryEsbuildOptions): esbuild.BuildOptions {\n return {\n entryPoints: options.entryPoints,\n outdir: path.join(options.pkgDir, \"dist\"),\n format: \"esm\",\n sourcemap: true,\n platform: options.target === \"node\" ? \"node\" : \"browser\",\n target: options.target === \"node\" ? \"node20\" : \"chrome84\",\n bundle: false,\n tsconfigRaw: { compilerOptions: options.compilerOptions as esbuild.TsconfigRaw[\"compilerOptions\"] },\n plugins: [esmRelativeImportPlugin(path.join(options.pkgDir, \"dist\"))],\n };\n}\n\n/**\n * Server\uC6A9 esbuild \uC124\uC815 \uC0DD\uC131\n *\n * \uC11C\uBC84 \uD328\uD0A4\uC9C0 \uBE4C\uB4DC\uC5D0 \uC0AC\uC6A9\uD569\uB2C8\uB2E4.\n * - bundle: true (\uBAA8\uB4E0 \uC758\uC874\uC131 \uD3EC\uD568\uD55C \uB2E8\uC77C \uBC88\uB4E4)\n * - banner: CJS \uD328\uD0A4\uC9C0\uC758 require() \uC9C0\uC6D0\uC744 \uC704\uD55C createRequire shim\n * - env\uB97C define \uC635\uC158\uC73C\uB85C \uCE58\uD658 (process.env[\"KEY\"] \uD615\uD0DC)\n */\nexport function createServerEsbuildOptions(options: ServerEsbuildOptions): esbuild.BuildOptions {\n const define: Record<string, string> = {};\n if (options.env != null) {\n for (const [key, value] of Object.entries(options.env)) {\n define[`process.env[\"${key}\"]`] = JSON.stringify(value);\n }\n }\n\n return {\n entryPoints: options.entryPoints,\n outdir: path.join(options.pkgDir, \"dist\"),\n format: \"esm\",\n sourcemap: true,\n platform: \"node\",\n target: \"node20\",\n bundle: true,\n banner: {\n js: \"import { createRequire } from 'module'; const require = createRequire(import.meta.url);\",\n },\n define,\n tsconfigRaw: { compilerOptions: options.compilerOptions as esbuild.TsconfigRaw[\"compilerOptions\"] },\n };\n}\n\n/**\n * \uBE4C\uB4DC \uD0C0\uAC9F\uC5D0\uC11C TypecheckEnv \uCD94\uCD9C\n *\n * \uBE4C\uB4DC\uC6A9\uC774\uBBC0\uB85C neutral\uC740 browser\uB85C \uCC98\uB9AC\uD569\uB2C8\uB2E4.\n * (neutral \uD328\uD0A4\uC9C0\uB294 Node/\uBE0C\uB77C\uC6B0\uC800 \uACF5\uC6A9\uC774\uC9C0\uB9CC, \uBE4C\uB4DC \uC2DC\uC5D0\uB294 browser \uD658\uACBD \uAE30\uC900\uC73C\uB85C \uCC98\uB9AC)\n */\nexport function getTypecheckEnvFromTarget(target: \"node\" | \"browser\" | \"neutral\"): TypecheckEnv {\n return target === \"node\" ? \"node\" : \"browser\";\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,YAAY;AAUrB,SAAS,wBAAwB,QAAgC;AAC/D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,OAAO;AACX,YAAM,MAAM,YAAY;AACtB,cAAM,QAAQ,MAAM,KAAK,WAAW,EAAE,KAAK,OAAO,CAAC;AAEnD,cAAM,QAAQ;AAAA,UACZ,MAAM,IAAI,OAAO,SAAS;AACxB,kBAAM,WAAW,KAAK,KAAK,QAAQ,IAAI;AACvC,kBAAM,UAAU,MAAM,GAAG,SAAS,UAAU,OAAO;AAEnD,kBAAM,YAAY,QAAQ;AAAA,cACxB;AAAA,cACA,CAAC,QAAQ,QAAgB,YAAoB,WAAmB;AAC9D,oBAAI,sCAAsC,KAAK,UAAU,EAAG,QAAO;AACnE,uBAAO,GAAG,MAAM,GAAG,UAAU,MAAM,MAAM;AAAA,cAC3C;AAAA,YACF;AAEA,gBAAI,cAAc,SAAS;AACzB,oBAAM,GAAG,UAAU,UAAU,SAAS;AAAA,YACxC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;
|
|
4
|
+
"sourcesContent": ["import path from \"path\";\nimport { readFileSync } from \"fs\";\nimport fs from \"fs/promises\";\nimport { createRequire } from \"module\";\nimport { glob } from \"glob\";\nimport type esbuild from \"esbuild\";\nimport type { TypecheckEnv } from \"./tsconfig\";\n\n/**\n * ESM \uC0C1\uB300 import \uACBD\uB85C\uC5D0 .js \uD655\uC7A5\uC790\uB97C \uCD94\uAC00\uD558\uB294 esbuild \uD50C\uB7EC\uADF8\uC778.\n *\n * bundle: false \uBAA8\uB4DC\uC5D0\uC11C esbuild\uB294 import \uACBD\uB85C\uB97C \uADF8\uB300\uB85C \uC720\uC9C0\uD558\uBBC0\uB85C,\n * Node.js ESM\uC5D0\uC11C \uC9C1\uC811 \uC2E4\uD589 \uC2DC \uD655\uC7A5\uC790 \uB204\uB77D\uC73C\uB85C \uBAA8\uB4C8\uC744 \uCC3E\uC9C0 \uBABB\uD558\uB294 \uBB38\uC81C\uB97C \uD574\uACB0\uD55C\uB2E4.\n */\nfunction esmRelativeImportPlugin(outdir: string): esbuild.Plugin {\n return {\n name: \"esm-relative-import\",\n setup(build) {\n build.onEnd(async () => {\n const files = await glob(\"**/*.js\", { cwd: outdir });\n\n await Promise.all(\n files.map(async (file) => {\n const filePath = path.join(outdir, file);\n const content = await fs.readFile(filePath, \"utf-8\");\n\n const rewritten = content.replace(\n /((?:from|import)\\s*[\"'])(\\.\\.?\\/[^\"']*?)([\"'])/g,\n (_match, prefix: string, importPath: string, suffix: string) => {\n if (/\\.(js|mjs|cjs|json|css|wasm|node)$/i.test(importPath)) return _match;\n return `${prefix}${importPath}.js${suffix}`;\n },\n );\n\n if (rewritten !== content) {\n await fs.writeFile(filePath, rewritten);\n }\n }),\n );\n });\n },\n };\n}\n\n/**\n * Library \uBE4C\uB4DC\uC6A9 esbuild \uC635\uC158\n * - bundle: false (\uAC1C\uBCC4 \uD30C\uC77C \uD2B8\uB79C\uC2A4\uD30C\uC77C)\n * - platform: target\uC5D0 \uB530\uB77C node \uB610\uB294 browser\n */\nexport interface LibraryEsbuildOptions {\n pkgDir: string;\n entryPoints: string[];\n target: \"node\" | \"browser\" | \"neutral\";\n compilerOptions: Record<string, unknown>;\n}\n\n/**\n * Server \uBE4C\uB4DC\uC6A9 esbuild \uC635\uC158\n * - bundle: true (\uBAA8\uB4E0 \uC758\uC874\uC131 \uD3EC\uD568\uD55C \uB2E8\uC77C \uBC88\uB4E4)\n */\nexport interface ServerEsbuildOptions {\n pkgDir: string;\n entryPoints: string[];\n compilerOptions: Record<string, unknown>;\n env?: Record<string, string>;\n /** \uBC88\uB4E4\uC5D0\uC11C \uC81C\uC678\uD560 \uC678\uBD80 \uBAA8\uB4C8 */\n external?: string[];\n}\n\n/**\n * Library\uC6A9 esbuild \uC124\uC815 \uC0DD\uC131\n *\n * node/browser/neutral \uD0C0\uAC9F\uC758 \uB77C\uC774\uBE0C\uB7EC\uB9AC \uD328\uD0A4\uC9C0 \uBE4C\uB4DC\uC5D0 \uC0AC\uC6A9\uD569\uB2C8\uB2E4.\n * - bundle: false (\uAC1C\uBCC4 \uD30C\uC77C\uC744 \uAC01\uAC01 \uD2B8\uB79C\uC2A4\uD30C\uC77C)\n * - platform: target\uC774 node\uBA74 node, \uADF8 \uC678\uB294 browser\n * - target: node\uBA74 node20, \uADF8 \uC678\uB294 chrome84\n */\nexport function createLibraryEsbuildOptions(options: LibraryEsbuildOptions): esbuild.BuildOptions {\n return {\n entryPoints: options.entryPoints,\n outdir: path.join(options.pkgDir, \"dist\"),\n format: \"esm\",\n sourcemap: true,\n platform: options.target === \"node\" ? \"node\" : \"browser\",\n target: options.target === \"node\" ? \"node20\" : \"chrome84\",\n bundle: false,\n tsconfigRaw: { compilerOptions: options.compilerOptions as esbuild.TsconfigRaw[\"compilerOptions\"] },\n plugins: [esmRelativeImportPlugin(path.join(options.pkgDir, \"dist\"))],\n };\n}\n\n/**\n * Server\uC6A9 esbuild \uC124\uC815 \uC0DD\uC131\n *\n * \uC11C\uBC84 \uD328\uD0A4\uC9C0 \uBE4C\uB4DC\uC5D0 \uC0AC\uC6A9\uD569\uB2C8\uB2E4.\n * - bundle: true (\uBAA8\uB4E0 \uC758\uC874\uC131 \uD3EC\uD568\uD55C \uB2E8\uC77C \uBC88\uB4E4)\n * - banner: CJS \uD328\uD0A4\uC9C0\uC758 require() \uC9C0\uC6D0\uC744 \uC704\uD55C createRequire shim\n * - env\uB97C define \uC635\uC158\uC73C\uB85C \uCE58\uD658 (process.env[\"KEY\"] \uD615\uD0DC)\n */\nexport function createServerEsbuildOptions(options: ServerEsbuildOptions): esbuild.BuildOptions {\n const define: Record<string, string> = {};\n if (options.env != null) {\n for (const [key, value] of Object.entries(options.env)) {\n define[`process.env[\"${key}\"]`] = JSON.stringify(value);\n }\n }\n\n return {\n entryPoints: options.entryPoints,\n outdir: path.join(options.pkgDir, \"dist\"),\n format: \"esm\",\n sourcemap: true,\n platform: \"node\",\n target: \"node20\",\n bundle: true,\n banner: {\n js: \"import { createRequire } from 'module'; const require = createRequire(import.meta.url);\",\n },\n external: options.external,\n define,\n tsconfigRaw: { compilerOptions: options.compilerOptions as esbuild.TsconfigRaw[\"compilerOptions\"] },\n };\n}\n\n/**\n * \uBE4C\uB4DC \uD0C0\uAC9F\uC5D0\uC11C TypecheckEnv \uCD94\uCD9C\n *\n * \uBE4C\uB4DC\uC6A9\uC774\uBBC0\uB85C neutral\uC740 browser\uB85C \uCC98\uB9AC\uD569\uB2C8\uB2E4.\n * (neutral \uD328\uD0A4\uC9C0\uB294 Node/\uBE0C\uB77C\uC6B0\uC800 \uACF5\uC6A9\uC774\uC9C0\uB9CC, \uBE4C\uB4DC \uC2DC\uC5D0\uB294 browser \uD658\uACBD \uAE30\uC900\uC73C\uB85C \uCC98\uB9AC)\n */\nexport function getTypecheckEnvFromTarget(target: \"node\" | \"browser\" | \"neutral\"): TypecheckEnv {\n return target === \"node\" ? \"node\" : \"browser\";\n}\n\n//#region Optional Peer Deps\n\ninterface PkgJson {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n peerDependenciesMeta?: Record<string, { optional?: boolean }>;\n}\n\n/**\n * \uC758\uC874\uC131 \uD2B8\uB9AC\uC5D0\uC11C \uBBF8\uC124\uCE58 optional peer dep \uC218\uC9D1\n *\n * \uC11C\uBC84 \uBE4C\uB4DC(bundle: true) \uC2DC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 optional peer dependency\uB97C\n * esbuild external\uB85C \uC9C0\uC815\uD558\uC5EC \uBE4C\uB4DC \uC2E4\uD328\uB97C \uBC29\uC9C0\uD55C\uB2E4.\n */\nexport function collectUninstalledOptionalPeerDeps(pkgDir: string): string[] {\n const external = new Set<string>();\n const visited = new Set<string>();\n\n const pkgJson = JSON.parse(readFileSync(path.join(pkgDir, \"package.json\"), \"utf-8\")) as PkgJson;\n for (const dep of Object.keys(pkgJson.dependencies ?? {})) {\n scanOptionalPeerDeps(dep, pkgDir, external, visited);\n }\n\n return [...external];\n}\n\nfunction scanOptionalPeerDeps(pkgName: string, resolveDir: string, external: Set<string>, visited: Set<string>): void {\n if (visited.has(pkgName)) return;\n visited.add(pkgName);\n\n const req = createRequire(path.join(resolveDir, \"noop.js\"));\n\n let pkgJsonPath: string;\n try {\n pkgJsonPath = req.resolve(`${pkgName}/package.json`);\n } catch {\n return;\n }\n\n const depDir = path.dirname(pkgJsonPath);\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\")) as PkgJson;\n\n if (pkgJson.peerDependenciesMeta != null) {\n const peerDeps = pkgJson.peerDependencies ?? {};\n const depReq = createRequire(path.join(depDir, \"noop.js\"));\n for (const [name, meta] of Object.entries(pkgJson.peerDependenciesMeta)) {\n if (meta.optional === true && name in peerDeps) {\n try {\n depReq.resolve(name);\n } catch {\n external.add(name);\n }\n }\n }\n }\n\n for (const dep of Object.keys(pkgJson.dependencies ?? {})) {\n scanOptionalPeerDeps(dep, depDir, external, visited);\n }\n}\n\n//#endregion\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.worker.d.ts","sourceRoot":"","sources":["../../src/workers/server.worker.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACjE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAoDD;;GAEG;AACH,iBAAe,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"server.worker.d.ts","sourceRoot":"","sources":["../../src/workers/server.worker.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACjE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAoDD;;GAEG;AACH,iBAAe,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6CtE;AAKD;;;;GAIG;AACH,iBAAe,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiF9D;AAED;;;GAGG;AACH,iBAAe,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAExC;AAED,QAAA,MAAM,MAAM;;;eACD,OAAO,KAAK;oBAAc,OAAO,UAAU;mBAAa,OAAO,SAAS;;;CAMjF,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -4,7 +4,7 @@ import esbuild from "esbuild";
|
|
|
4
4
|
import { createWorker } from "@simplysm/core-node";
|
|
5
5
|
import { consola } from "consola";
|
|
6
6
|
import { parseRootTsconfig, getPackageSourceFiles, getCompilerOptionsForPackage } from "../utils/tsconfig.js";
|
|
7
|
-
import { createServerEsbuildOptions } from "../utils/esbuild-config.js";
|
|
7
|
+
import { createServerEsbuildOptions, collectUninstalledOptionalPeerDeps } from "../utils/esbuild-config.js";
|
|
8
8
|
const logger = consola.withTag("sd:cli:server:worker");
|
|
9
9
|
let esbuildContext;
|
|
10
10
|
async function cleanup() {
|
|
@@ -34,11 +34,16 @@ async function build(info) {
|
|
|
34
34
|
const parsedConfig = parseRootTsconfig(info.cwd);
|
|
35
35
|
const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);
|
|
36
36
|
const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, "node", info.pkgDir);
|
|
37
|
+
const external = collectUninstalledOptionalPeerDeps(info.pkgDir);
|
|
38
|
+
if (external.length > 0) {
|
|
39
|
+
logger.debug("\uBBF8\uC124\uCE58 optional peer deps (external):", external);
|
|
40
|
+
}
|
|
37
41
|
const esbuildOptions = createServerEsbuildOptions({
|
|
38
42
|
pkgDir: info.pkgDir,
|
|
39
43
|
entryPoints,
|
|
40
44
|
compilerOptions,
|
|
41
|
-
env: info.env
|
|
45
|
+
env: info.env,
|
|
46
|
+
external
|
|
42
47
|
});
|
|
43
48
|
const result = await esbuild.build(esbuildOptions);
|
|
44
49
|
const confDistPath = path.join(info.pkgDir, "dist", ".config.json");
|
|
@@ -73,11 +78,16 @@ async function startWatch(info) {
|
|
|
73
78
|
resolveFirstBuild = resolve;
|
|
74
79
|
});
|
|
75
80
|
let isFirstBuild = true;
|
|
81
|
+
const external = collectUninstalledOptionalPeerDeps(info.pkgDir);
|
|
82
|
+
if (external.length > 0) {
|
|
83
|
+
logger.debug("\uBBF8\uC124\uCE58 optional peer deps (external):", external);
|
|
84
|
+
}
|
|
76
85
|
const baseOptions = createServerEsbuildOptions({
|
|
77
86
|
pkgDir: info.pkgDir,
|
|
78
87
|
entryPoints,
|
|
79
88
|
compilerOptions,
|
|
80
|
-
env: info.env
|
|
89
|
+
env: info.env,
|
|
90
|
+
external
|
|
81
91
|
});
|
|
82
92
|
esbuildContext = await esbuild.context({
|
|
83
93
|
...baseOptions,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/workers/server.worker.ts"],
|
|
4
|
-
"sourcesContent": ["import path from \"path\";\nimport fs from \"fs\";\nimport esbuild from \"esbuild\";\nimport { createWorker } from \"@simplysm/core-node\";\nimport { consola } from \"consola\";\nimport { parseRootTsconfig, getPackageSourceFiles, getCompilerOptionsForPackage } from \"../utils/tsconfig\";\nimport { createServerEsbuildOptions } from \"../utils/esbuild-config\";\n\n//#region Types\n\n/**\n * Server \uBE4C\uB4DC \uC815\uBCF4 (\uC77C\uD68C\uC131 \uBE4C\uB4DC\uC6A9)\n */\nexport interface ServerBuildInfo {\n name: string;\n cwd: string;\n pkgDir: string;\n /** \uBE4C\uB4DC \uC2DC \uCE58\uD658\uD560 \uD658\uACBD\uBCC0\uC218 */\n env?: Record<string, string>;\n /** \uB7F0\uD0C0\uC784 \uC124\uC815 (dist/.config.json\uC5D0 \uAE30\uB85D) */\n configs?: Record<string, unknown>;\n}\n\n/**\n * Server \uBE4C\uB4DC \uACB0\uACFC\n */\nexport interface ServerBuildResult {\n success: boolean;\n mainJsPath: string;\n errors?: string[];\n}\n\n/**\n * Server Watch \uC815\uBCF4\n */\nexport interface ServerWatchInfo {\n name: string;\n cwd: string;\n pkgDir: string;\n /** \uBE4C\uB4DC \uC2DC \uCE58\uD658\uD560 \uD658\uACBD\uBCC0\uC218 */\n env?: Record<string, string>;\n /** \uB7F0\uD0C0\uC784 \uC124\uC815 (dist/.config.json\uC5D0 \uAE30\uB85D) */\n configs?: Record<string, unknown>;\n}\n\n/**\n * \uBE4C\uB4DC \uC774\uBCA4\uD2B8\n */\nexport interface ServerBuildEvent {\n success: boolean;\n mainJsPath: string;\n errors?: string[];\n}\n\n/**\n * \uC5D0\uB7EC \uC774\uBCA4\uD2B8\n */\nexport interface ServerErrorEvent {\n message: string;\n}\n\n/**\n * Worker \uC774\uBCA4\uD2B8 \uD0C0\uC785\n */\nexport interface ServerWorkerEvents extends Record<string, unknown> {\n buildStart: Record<string, never>;\n build: ServerBuildEvent;\n error: ServerErrorEvent;\n}\n\n//#endregion\n\n//#region \uB9AC\uC18C\uC2A4 \uAD00\uB9AC\n\nconst logger = consola.withTag(\"sd:cli:server:worker\");\n\n/** esbuild build context (\uC815\uB9AC \uB300\uC0C1) */\nlet esbuildContext: esbuild.BuildContext | undefined;\n\n/**\n * \uB9AC\uC18C\uC2A4 \uC815\uB9AC\n */\nasync function cleanup(): Promise<void> {\n // \uC804\uC5ED \uBCC0\uC218\uB97C \uC784\uC2DC \uBCC0\uC218\uB85C \uCEA1\uCC98 \uD6C4 \uCD08\uAE30\uD654\n // (Promise.all \uB300\uAE30 \uC911 \uB2E4\uB978 \uD638\uCD9C\uC5D0\uC11C \uC804\uC5ED \uBCC0\uC218\uB97C \uC218\uC815\uD560 \uC218 \uC788\uC73C\uBBC0\uB85C)\n const contextToDispose = esbuildContext;\n esbuildContext = undefined;\n\n if (contextToDispose != null) {\n await contextToDispose.dispose();\n }\n}\n\n// \uD504\uB85C\uC138\uC2A4 \uC885\uB8CC \uC804 \uB9AC\uC18C\uC2A4 \uC815\uB9AC (SIGTERM/SIGINT)\n// \uC8FC\uC758: worker.terminate()\uB294 \uC774 \uD578\uB4E4\uB7EC\uB4E4\uC744 \uD638\uCD9C\uD558\uC9C0 \uC54A\uACE0 \uC989\uC2DC \uC885\uB8CC\uB428.\n// \uADF8\uB7EC\uB098 watch \uBAA8\uB4DC\uC5D0\uC11C \uC815\uC0C1 \uC885\uB8CC\uB294 \uBA54\uC778 \uD504\uB85C\uC138\uC2A4\uC758 SIGINT/SIGTERM\uC744 \uD1B5\uD574 \uC774\uB8E8\uC5B4\uC9C0\uBBC0\uB85C \uBB38\uC81C\uC5C6\uC74C.\nprocess.on(\"SIGTERM\", () => {\n cleanup()\n .catch((err) => {\n logger.error(\"cleanup \uC2E4\uD328\", err);\n })\n .finally(() => {\n process.exit(0);\n });\n});\n\nprocess.on(\"SIGINT\", () => {\n cleanup()\n .catch((err) => {\n logger.error(\"cleanup \uC2E4\uD328\", err);\n })\n .finally(() => {\n process.exit(0);\n });\n});\n\n//#endregion\n\n//#region Worker\n\n/**\n * \uC77C\uD68C\uC131 \uBE4C\uB4DC\n */\nasync function build(info: ServerBuildInfo): Promise<ServerBuildResult> {\n const mainJsPath = path.join(info.pkgDir, \"dist\", \"main.js\");\n\n try {\n // tsconfig \uD30C\uC2F1\n const parsedConfig = parseRootTsconfig(info.cwd);\n const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);\n\n // \uC11C\uBC84\uB294 node \uD658\uACBD\n const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, \"node\", info.pkgDir);\n\n // esbuild \uC77C\uD68C\uC131 \uBE4C\uB4DC\n const esbuildOptions = createServerEsbuildOptions({\n pkgDir: info.pkgDir,\n entryPoints,\n compilerOptions,\n env: info.env,\n });\n\n const result = await esbuild.build(esbuildOptions);\n\n // Generate .config.json\n const confDistPath = path.join(info.pkgDir, \"dist\", \".config.json\");\n fs.writeFileSync(confDistPath, JSON.stringify(info.configs ?? {}, undefined, 2));\n\n const errors = result.errors.map((e) => e.text);\n return {\n success: result.errors.length === 0,\n mainJsPath,\n errors: errors.length > 0 ? errors : undefined,\n };\n } catch (err) {\n return {\n success: false,\n mainJsPath,\n errors: [err instanceof Error ? err.message : String(err)],\n };\n }\n}\n\n/** startWatch \uD638\uCD9C \uC5EC\uBD80 \uD50C\uB798\uADF8 */\nlet isWatchStarted = false;\n\n/**\n * watch \uC2DC\uC791\n * @remarks \uC774 \uD568\uC218\uB294 Worker\uB2F9 \uD55C \uBC88\uB9CC \uD638\uCD9C\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.\n * @throws \uC774\uBBF8 watch\uAC00 \uC2DC\uC791\uB41C \uACBD\uC6B0\n */\nasync function startWatch(info: ServerWatchInfo): Promise<void> {\n if (isWatchStarted) {\n throw new Error(\"startWatch\uB294 Worker\uB2F9 \uD55C \uBC88\uB9CC \uD638\uCD9C\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\");\n }\n isWatchStarted = true;\n\n try {\n // tsconfig \uD30C\uC2F1\n const parsedConfig = parseRootTsconfig(info.cwd);\n const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);\n\n // \uC11C\uBC84\uB294 node \uD658\uACBD\n const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, \"node\", info.pkgDir);\n\n const mainJsPath = path.join(info.pkgDir, \"dist\", \"main.js\");\n\n // \uCCAB \uBC88\uC9F8 \uBE4C\uB4DC \uC644\uB8CC \uB300\uAE30\uB97C \uC704\uD55C Promise\n let resolveFirstBuild!: () => void;\n const firstBuildPromise = new Promise<void>((resolve) => {\n resolveFirstBuild = resolve;\n });\n\n let isFirstBuild = true;\n\n // esbuild \uAE30\uBCF8 \uC635\uC158 \uC0DD\uC131\n const baseOptions = createServerEsbuildOptions({\n pkgDir: info.pkgDir,\n entryPoints,\n compilerOptions,\n env: info.env,\n });\n\n // watch\uC6A9 \uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00\n esbuildContext = await esbuild.context({\n ...baseOptions,\n plugins: [\n {\n name: \"watch-notify\",\n setup(pluginBuild) {\n pluginBuild.onStart(() => {\n sender.send(\"buildStart\", {});\n });\n\n pluginBuild.onEnd((result) => {\n const errors = result.errors.map((e) => e.text);\n const success = result.errors.length === 0;\n\n // Generate .config.json on first successful build\n if (isFirstBuild && success) {\n const confDistPath = path.join(info.pkgDir, \"dist\", \".config.json\");\n fs.writeFileSync(confDistPath, JSON.stringify(info.configs ?? {}, undefined, 2));\n }\n\n sender.send(\"build\", { success, mainJsPath, errors: errors.length > 0 ? errors : undefined });\n\n if (isFirstBuild) {\n isFirstBuild = false;\n resolveFirstBuild();\n }\n });\n },\n },\n ],\n });\n\n await esbuildContext.watch();\n\n // \uCCAB \uBC88\uC9F8 \uBE4C\uB4DC \uC644\uB8CC \uB300\uAE30\n await firstBuildPromise;\n } catch (err) {\n sender.send(\"error\", {\n message: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n/**\n * watch \uC911\uC9C0\n * @remarks esbuild context\uB97C \uC815\uB9AC\uD569\uB2C8\uB2E4.\n */\nasync function stopWatch(): Promise<void> {\n await cleanup();\n}\n\nconst sender = createWorker<\n { build: typeof build; startWatch: typeof startWatch; stopWatch: typeof stopWatch },\n ServerWorkerEvents\n>({\n build,\n startWatch,\n stopWatch,\n});\n\nexport default sender;\n\n//#endregion\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,aAAa;AACpB,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,mBAAmB,uBAAuB,oCAAoC;AACvF,SAAS,
|
|
4
|
+
"sourcesContent": ["import path from \"path\";\nimport fs from \"fs\";\nimport esbuild from \"esbuild\";\nimport { createWorker } from \"@simplysm/core-node\";\nimport { consola } from \"consola\";\nimport { parseRootTsconfig, getPackageSourceFiles, getCompilerOptionsForPackage } from \"../utils/tsconfig\";\nimport { createServerEsbuildOptions, collectUninstalledOptionalPeerDeps } from \"../utils/esbuild-config\";\n\n//#region Types\n\n/**\n * Server \uBE4C\uB4DC \uC815\uBCF4 (\uC77C\uD68C\uC131 \uBE4C\uB4DC\uC6A9)\n */\nexport interface ServerBuildInfo {\n name: string;\n cwd: string;\n pkgDir: string;\n /** \uBE4C\uB4DC \uC2DC \uCE58\uD658\uD560 \uD658\uACBD\uBCC0\uC218 */\n env?: Record<string, string>;\n /** \uB7F0\uD0C0\uC784 \uC124\uC815 (dist/.config.json\uC5D0 \uAE30\uB85D) */\n configs?: Record<string, unknown>;\n}\n\n/**\n * Server \uBE4C\uB4DC \uACB0\uACFC\n */\nexport interface ServerBuildResult {\n success: boolean;\n mainJsPath: string;\n errors?: string[];\n}\n\n/**\n * Server Watch \uC815\uBCF4\n */\nexport interface ServerWatchInfo {\n name: string;\n cwd: string;\n pkgDir: string;\n /** \uBE4C\uB4DC \uC2DC \uCE58\uD658\uD560 \uD658\uACBD\uBCC0\uC218 */\n env?: Record<string, string>;\n /** \uB7F0\uD0C0\uC784 \uC124\uC815 (dist/.config.json\uC5D0 \uAE30\uB85D) */\n configs?: Record<string, unknown>;\n}\n\n/**\n * \uBE4C\uB4DC \uC774\uBCA4\uD2B8\n */\nexport interface ServerBuildEvent {\n success: boolean;\n mainJsPath: string;\n errors?: string[];\n}\n\n/**\n * \uC5D0\uB7EC \uC774\uBCA4\uD2B8\n */\nexport interface ServerErrorEvent {\n message: string;\n}\n\n/**\n * Worker \uC774\uBCA4\uD2B8 \uD0C0\uC785\n */\nexport interface ServerWorkerEvents extends Record<string, unknown> {\n buildStart: Record<string, never>;\n build: ServerBuildEvent;\n error: ServerErrorEvent;\n}\n\n//#endregion\n\n//#region \uB9AC\uC18C\uC2A4 \uAD00\uB9AC\n\nconst logger = consola.withTag(\"sd:cli:server:worker\");\n\n/** esbuild build context (\uC815\uB9AC \uB300\uC0C1) */\nlet esbuildContext: esbuild.BuildContext | undefined;\n\n/**\n * \uB9AC\uC18C\uC2A4 \uC815\uB9AC\n */\nasync function cleanup(): Promise<void> {\n // \uC804\uC5ED \uBCC0\uC218\uB97C \uC784\uC2DC \uBCC0\uC218\uB85C \uCEA1\uCC98 \uD6C4 \uCD08\uAE30\uD654\n // (Promise.all \uB300\uAE30 \uC911 \uB2E4\uB978 \uD638\uCD9C\uC5D0\uC11C \uC804\uC5ED \uBCC0\uC218\uB97C \uC218\uC815\uD560 \uC218 \uC788\uC73C\uBBC0\uB85C)\n const contextToDispose = esbuildContext;\n esbuildContext = undefined;\n\n if (contextToDispose != null) {\n await contextToDispose.dispose();\n }\n}\n\n// \uD504\uB85C\uC138\uC2A4 \uC885\uB8CC \uC804 \uB9AC\uC18C\uC2A4 \uC815\uB9AC (SIGTERM/SIGINT)\n// \uC8FC\uC758: worker.terminate()\uB294 \uC774 \uD578\uB4E4\uB7EC\uB4E4\uC744 \uD638\uCD9C\uD558\uC9C0 \uC54A\uACE0 \uC989\uC2DC \uC885\uB8CC\uB428.\n// \uADF8\uB7EC\uB098 watch \uBAA8\uB4DC\uC5D0\uC11C \uC815\uC0C1 \uC885\uB8CC\uB294 \uBA54\uC778 \uD504\uB85C\uC138\uC2A4\uC758 SIGINT/SIGTERM\uC744 \uD1B5\uD574 \uC774\uB8E8\uC5B4\uC9C0\uBBC0\uB85C \uBB38\uC81C\uC5C6\uC74C.\nprocess.on(\"SIGTERM\", () => {\n cleanup()\n .catch((err) => {\n logger.error(\"cleanup \uC2E4\uD328\", err);\n })\n .finally(() => {\n process.exit(0);\n });\n});\n\nprocess.on(\"SIGINT\", () => {\n cleanup()\n .catch((err) => {\n logger.error(\"cleanup \uC2E4\uD328\", err);\n })\n .finally(() => {\n process.exit(0);\n });\n});\n\n//#endregion\n\n//#region Worker\n\n/**\n * \uC77C\uD68C\uC131 \uBE4C\uB4DC\n */\nasync function build(info: ServerBuildInfo): Promise<ServerBuildResult> {\n const mainJsPath = path.join(info.pkgDir, \"dist\", \"main.js\");\n\n try {\n // tsconfig \uD30C\uC2F1\n const parsedConfig = parseRootTsconfig(info.cwd);\n const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);\n\n // \uC11C\uBC84\uB294 node \uD658\uACBD\n const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, \"node\", info.pkgDir);\n\n // \uBBF8\uC124\uCE58 optional peer dep\uC744 external \uCC98\uB9AC\n const external = collectUninstalledOptionalPeerDeps(info.pkgDir);\n if (external.length > 0) {\n logger.debug(\"\uBBF8\uC124\uCE58 optional peer deps (external):\", external);\n }\n\n // esbuild \uC77C\uD68C\uC131 \uBE4C\uB4DC\n const esbuildOptions = createServerEsbuildOptions({\n pkgDir: info.pkgDir,\n entryPoints,\n compilerOptions,\n env: info.env,\n external,\n });\n\n const result = await esbuild.build(esbuildOptions);\n\n // Generate .config.json\n const confDistPath = path.join(info.pkgDir, \"dist\", \".config.json\");\n fs.writeFileSync(confDistPath, JSON.stringify(info.configs ?? {}, undefined, 2));\n\n const errors = result.errors.map((e) => e.text);\n return {\n success: result.errors.length === 0,\n mainJsPath,\n errors: errors.length > 0 ? errors : undefined,\n };\n } catch (err) {\n return {\n success: false,\n mainJsPath,\n errors: [err instanceof Error ? err.message : String(err)],\n };\n }\n}\n\n/** startWatch \uD638\uCD9C \uC5EC\uBD80 \uD50C\uB798\uADF8 */\nlet isWatchStarted = false;\n\n/**\n * watch \uC2DC\uC791\n * @remarks \uC774 \uD568\uC218\uB294 Worker\uB2F9 \uD55C \uBC88\uB9CC \uD638\uCD9C\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.\n * @throws \uC774\uBBF8 watch\uAC00 \uC2DC\uC791\uB41C \uACBD\uC6B0\n */\nasync function startWatch(info: ServerWatchInfo): Promise<void> {\n if (isWatchStarted) {\n throw new Error(\"startWatch\uB294 Worker\uB2F9 \uD55C \uBC88\uB9CC \uD638\uCD9C\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\");\n }\n isWatchStarted = true;\n\n try {\n // tsconfig \uD30C\uC2F1\n const parsedConfig = parseRootTsconfig(info.cwd);\n const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);\n\n // \uC11C\uBC84\uB294 node \uD658\uACBD\n const compilerOptions = await getCompilerOptionsForPackage(parsedConfig.options, \"node\", info.pkgDir);\n\n const mainJsPath = path.join(info.pkgDir, \"dist\", \"main.js\");\n\n // \uCCAB \uBC88\uC9F8 \uBE4C\uB4DC \uC644\uB8CC \uB300\uAE30\uB97C \uC704\uD55C Promise\n let resolveFirstBuild!: () => void;\n const firstBuildPromise = new Promise<void>((resolve) => {\n resolveFirstBuild = resolve;\n });\n\n let isFirstBuild = true;\n\n // \uBBF8\uC124\uCE58 optional peer dep\uC744 external \uCC98\uB9AC\n const external = collectUninstalledOptionalPeerDeps(info.pkgDir);\n if (external.length > 0) {\n logger.debug(\"\uBBF8\uC124\uCE58 optional peer deps (external):\", external);\n }\n\n // esbuild \uAE30\uBCF8 \uC635\uC158 \uC0DD\uC131\n const baseOptions = createServerEsbuildOptions({\n pkgDir: info.pkgDir,\n entryPoints,\n compilerOptions,\n env: info.env,\n external,\n });\n\n // watch\uC6A9 \uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00\n esbuildContext = await esbuild.context({\n ...baseOptions,\n plugins: [\n {\n name: \"watch-notify\",\n setup(pluginBuild) {\n pluginBuild.onStart(() => {\n sender.send(\"buildStart\", {});\n });\n\n pluginBuild.onEnd((result) => {\n const errors = result.errors.map((e) => e.text);\n const success = result.errors.length === 0;\n\n // Generate .config.json on first successful build\n if (isFirstBuild && success) {\n const confDistPath = path.join(info.pkgDir, \"dist\", \".config.json\");\n fs.writeFileSync(confDistPath, JSON.stringify(info.configs ?? {}, undefined, 2));\n }\n\n sender.send(\"build\", { success, mainJsPath, errors: errors.length > 0 ? errors : undefined });\n\n if (isFirstBuild) {\n isFirstBuild = false;\n resolveFirstBuild();\n }\n });\n },\n },\n ],\n });\n\n await esbuildContext.watch();\n\n // \uCCAB \uBC88\uC9F8 \uBE4C\uB4DC \uC644\uB8CC \uB300\uAE30\n await firstBuildPromise;\n } catch (err) {\n sender.send(\"error\", {\n message: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n/**\n * watch \uC911\uC9C0\n * @remarks esbuild context\uB97C \uC815\uB9AC\uD569\uB2C8\uB2E4.\n */\nasync function stopWatch(): Promise<void> {\n await cleanup();\n}\n\nconst sender = createWorker<\n { build: typeof build; startWatch: typeof startWatch; stopWatch: typeof stopWatch },\n ServerWorkerEvents\n>({\n build,\n startWatch,\n stopWatch,\n});\n\nexport default sender;\n\n//#endregion\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,OAAO,aAAa;AACpB,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,mBAAmB,uBAAuB,oCAAoC;AACvF,SAAS,4BAA4B,0CAA0C;AAoE/E,MAAM,SAAS,QAAQ,QAAQ,sBAAsB;AAGrD,IAAI;AAKJ,eAAe,UAAyB;AAGtC,QAAM,mBAAmB;AACzB,mBAAiB;AAEjB,MAAI,oBAAoB,MAAM;AAC5B,UAAM,iBAAiB,QAAQ;AAAA,EACjC;AACF;AAKA,QAAQ,GAAG,WAAW,MAAM;AAC1B,UAAQ,EACL,MAAM,CAAC,QAAQ;AACd,WAAO,MAAM,wBAAc,GAAG;AAAA,EAChC,CAAC,EACA,QAAQ,MAAM;AACb,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL,CAAC;AAED,QAAQ,GAAG,UAAU,MAAM;AACzB,UAAQ,EACL,MAAM,CAAC,QAAQ;AACd,WAAO,MAAM,wBAAc,GAAG;AAAA,EAChC,CAAC,EACA,QAAQ,MAAM;AACb,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL,CAAC;AASD,eAAe,MAAM,MAAmD;AACtE,QAAM,aAAa,KAAK,KAAK,KAAK,QAAQ,QAAQ,SAAS;AAE3D,MAAI;AAEF,UAAM,eAAe,kBAAkB,KAAK,GAAG;AAC/C,UAAM,cAAc,sBAAsB,KAAK,QAAQ,YAAY;AAGnE,UAAM,kBAAkB,MAAM,6BAA6B,aAAa,SAAS,QAAQ,KAAK,MAAM;AAGpG,UAAM,WAAW,mCAAmC,KAAK,MAAM;AAC/D,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO,MAAM,qDAAsC,QAAQ;AAAA,IAC7D;AAGA,UAAM,iBAAiB,2BAA2B;AAAA,MAChD,QAAQ,KAAK;AAAA,MACb;AAAA,MACA;AAAA,MACA,KAAK,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AAED,UAAM,SAAS,MAAM,QAAQ,MAAM,cAAc;AAGjD,UAAM,eAAe,KAAK,KAAK,KAAK,QAAQ,QAAQ,cAAc;AAClE,OAAG,cAAc,cAAc,KAAK,UAAU,KAAK,WAAW,CAAC,GAAG,QAAW,CAAC,CAAC;AAE/E,UAAM,SAAS,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAC9C,WAAO;AAAA,MACL,SAAS,OAAO,OAAO,WAAW;AAAA,MAClC;AAAA,MACA,QAAQ,OAAO,SAAS,IAAI,SAAS;AAAA,IACvC;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,QAAQ,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC3D;AAAA,EACF;AACF;AAGA,IAAI,iBAAiB;AAOrB,eAAe,WAAW,MAAsC;AAC9D,MAAI,gBAAgB;AAClB,UAAM,IAAI,MAAM,uGAAsC;AAAA,EACxD;AACA,mBAAiB;AAEjB,MAAI;AAEF,UAAM,eAAe,kBAAkB,KAAK,GAAG;AAC/C,UAAM,cAAc,sBAAsB,KAAK,QAAQ,YAAY;AAGnE,UAAM,kBAAkB,MAAM,6BAA6B,aAAa,SAAS,QAAQ,KAAK,MAAM;AAEpG,UAAM,aAAa,KAAK,KAAK,KAAK,QAAQ,QAAQ,SAAS;AAG3D,QAAI;AACJ,UAAM,oBAAoB,IAAI,QAAc,CAAC,YAAY;AACvD,0BAAoB;AAAA,IACtB,CAAC;AAED,QAAI,eAAe;AAGnB,UAAM,WAAW,mCAAmC,KAAK,MAAM;AAC/D,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO,MAAM,qDAAsC,QAAQ;AAAA,IAC7D;AAGA,UAAM,cAAc,2BAA2B;AAAA,MAC7C,QAAQ,KAAK;AAAA,MACb;AAAA,MACA;AAAA,MACA,KAAK,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AAGD,qBAAiB,MAAM,QAAQ,QAAQ;AAAA,MACrC,GAAG;AAAA,MACH,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,aAAa;AACjB,wBAAY,QAAQ,MAAM;AACxB,qBAAO,KAAK,cAAc,CAAC,CAAC;AAAA,YAC9B,CAAC;AAED,wBAAY,MAAM,CAAC,WAAW;AAC5B,oBAAM,SAAS,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAC9C,oBAAM,UAAU,OAAO,OAAO,WAAW;AAGzC,kBAAI,gBAAgB,SAAS;AAC3B,sBAAM,eAAe,KAAK,KAAK,KAAK,QAAQ,QAAQ,cAAc;AAClE,mBAAG,cAAc,cAAc,KAAK,UAAU,KAAK,WAAW,CAAC,GAAG,QAAW,CAAC,CAAC;AAAA,cACjF;AAEA,qBAAO,KAAK,SAAS,EAAE,SAAS,YAAY,QAAQ,OAAO,SAAS,IAAI,SAAS,OAAU,CAAC;AAE5F,kBAAI,cAAc;AAChB,+BAAe;AACf,kCAAkB;AAAA,cACpB;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,eAAe,MAAM;AAG3B,UAAM;AAAA,EACR,SAAS,KAAK;AACZ,WAAO,KAAK,SAAS;AAAA,MACnB,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;AAMA,eAAe,YAA2B;AACxC,QAAM,QAAQ;AAChB;AAEA,MAAM,SAAS,aAGb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAO,wBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/sd-cli",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "13.0.0-beta.
|
|
4
|
+
"version": "13.0.0-beta.28",
|
|
5
5
|
"description": "심플리즘 패키지 - CLI 도구",
|
|
6
6
|
"author": "김석래",
|
|
7
7
|
"repository": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"vite-plugin-solid": "^2.11.10",
|
|
42
42
|
"vite-tsconfig-paths": "^6.1.0",
|
|
43
43
|
"yargs": "^18.0.0",
|
|
44
|
-
"@simplysm/core-
|
|
45
|
-
"@simplysm/core-
|
|
46
|
-
"@simplysm/storage": "13.0.0-beta.
|
|
44
|
+
"@simplysm/core-common": "13.0.0-beta.28",
|
|
45
|
+
"@simplysm/core-node": "13.0.0-beta.28",
|
|
46
|
+
"@simplysm/storage": "13.0.0-beta.28"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/semver": "^7.7.1",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"vitest": "vitest"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@simplysm/sd-cli": "~13.0.0-beta.
|
|
19
|
-
"@simplysm/claude": "~13.0.0-beta.
|
|
20
|
-
"@simplysm/eslint-plugin": "~13.0.0-beta.
|
|
18
|
+
"@simplysm/sd-cli": "~13.0.0-beta.28",
|
|
19
|
+
"@simplysm/claude": "~13.0.0-beta.28",
|
|
20
|
+
"@simplysm/eslint-plugin": "~13.0.0-beta.28",
|
|
21
21
|
"@types/node": "^20.19.33",
|
|
22
22
|
"eslint": "^9.39.2",
|
|
23
23
|
"prettier": "^3.8.1",
|