@simplysm/sd-cli 13.0.0-beta.28 → 13.0.0-beta.30

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.
@@ -48,6 +48,8 @@ export interface SdBuildPackageConfig {
48
48
  target: BuildTarget;
49
49
  /** publish 설정 */
50
50
  publish?: SdPublishConfig;
51
+ /** src/에서 dist/로 복사할 파일 glob 패턴 (src/ 기준 상대 경로) */
52
+ copySrc?: string[];
51
53
  }
52
54
  /**
53
55
  * Capacitor Android 서명 설정
@@ -174,6 +176,17 @@ export interface SdServerPackageConfig {
174
176
  publish?: SdPublishConfig;
175
177
  /** runtime config (written to dist/.config.json during build) */
176
178
  configs?: Record<string, unknown>;
179
+ /** esbuild에서 번들에 포함하지 않을 외부 모듈 (binding.gyp 자동 감지에 더해 수동 지정) */
180
+ externals?: string[];
181
+ /** PM2 설정 (지정 시 dist/pm2.config.cjs 생성) */
182
+ pm2?: {
183
+ /** PM2 프로세스 이름 (미지정 시 package.json name에서 생성) */
184
+ name?: string;
185
+ /** PM2 watch에서 제외할 경로 */
186
+ ignoreWatchPaths?: string[];
187
+ /** true면 interpreter 경로 생략 (시스템 PATH의 node 사용) */
188
+ noInterpreter?: boolean;
189
+ };
177
190
  }
178
191
  /**
179
192
  * 스크립트 전용 패키지 설정 (watch/typecheck 제외)
@@ -1 +1 @@
1
- {"version":3,"file":"sd-config.types.d.ts","sourceRoot":"","sources":["../src/sd-config.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sd-config.types.d.ts","sourceRoot":"","sources":["../src/sd-config.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { FsWatcher } from "@simplysm/core-node";
2
+ /**
3
+ * src/에서 glob 패턴에 매칭되는 파일을 dist/로 복사한다.
4
+ * 상대 경로가 유지된다: src/a/b.css → dist/a/b.css
5
+ *
6
+ * @param pkgDir 패키지 루트 디렉토리
7
+ * @param patterns glob 패턴 배열 (src/ 기준 상대 경로)
8
+ */
9
+ export declare function copySrcFiles(pkgDir: string, patterns: string[]): Promise<void>;
10
+ /**
11
+ * src/에서 glob 패턴에 매칭되는 파일을 감시하여 dist/로 복사한다.
12
+ * 초기 복사 후 변경/추가/삭제를 자동 반영한다.
13
+ *
14
+ * @param pkgDir 패키지 루트 디렉토리
15
+ * @param patterns glob 패턴 배열 (src/ 기준 상대 경로)
16
+ * @returns FsWatcher 인스턴스 (shutdown 시 close() 호출 필요)
17
+ */
18
+ export declare function watchCopySrcFiles(pkgDir: string, patterns: string[]): Promise<FsWatcher>;
19
+ //# sourceMappingURL=copy-src.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-src.d.ts","sourceRoot":"","sources":["../../src/utils/copy-src.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAapF;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CA0B9F"}
@@ -0,0 +1,40 @@
1
+ import path from "path";
2
+ import { fsGlob, fsCopy, fsMkdir, fsRm, FsWatcher } from "@simplysm/core-node";
3
+ async function copySrcFiles(pkgDir, patterns) {
4
+ const srcDir = path.join(pkgDir, "src");
5
+ const distDir = path.join(pkgDir, "dist");
6
+ for (const pattern of patterns) {
7
+ const files = await fsGlob(pattern, { cwd: srcDir, absolute: true });
8
+ for (const file of files) {
9
+ const relativePath = path.relative(srcDir, file);
10
+ const distPath = path.join(distDir, relativePath);
11
+ await fsMkdir(path.dirname(distPath));
12
+ await fsCopy(file, distPath);
13
+ }
14
+ }
15
+ }
16
+ async function watchCopySrcFiles(pkgDir, patterns) {
17
+ const srcDir = path.join(pkgDir, "src");
18
+ const distDir = path.join(pkgDir, "dist");
19
+ await copySrcFiles(pkgDir, patterns);
20
+ const watchPaths = patterns.map((p) => path.join(srcDir, p));
21
+ const watcher = await FsWatcher.watch(watchPaths);
22
+ watcher.onChange({ delay: 300 }, async (changes) => {
23
+ for (const { event, path: filePath } of changes) {
24
+ const relPath = path.relative(srcDir, filePath);
25
+ const distPath = path.join(distDir, relPath);
26
+ if (event === "unlink") {
27
+ await fsRm(distPath);
28
+ } else if (event === "add" || event === "change") {
29
+ await fsMkdir(path.dirname(distPath));
30
+ await fsCopy(filePath, distPath);
31
+ }
32
+ }
33
+ });
34
+ return watcher;
35
+ }
36
+ export {
37
+ copySrcFiles,
38
+ watchCopySrcFiles
39
+ };
40
+ //# sourceMappingURL=copy-src.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/copy-src.ts"],
4
+ "sourcesContent": ["import path from \"path\";\nimport { fsGlob, fsCopy, fsMkdir, fsRm, FsWatcher } from \"@simplysm/core-node\";\n\n/**\n * src/\uC5D0\uC11C glob \uD328\uD134\uC5D0 \uB9E4\uCE6D\uB418\uB294 \uD30C\uC77C\uC744 dist/\uB85C \uBCF5\uC0AC\uD55C\uB2E4.\n * \uC0C1\uB300 \uACBD\uB85C\uAC00 \uC720\uC9C0\uB41C\uB2E4: src/a/b.css \u2192 dist/a/b.css\n *\n * @param pkgDir \uD328\uD0A4\uC9C0 \uB8E8\uD2B8 \uB514\uB809\uD1A0\uB9AC\n * @param patterns glob \uD328\uD134 \uBC30\uC5F4 (src/ \uAE30\uC900 \uC0C1\uB300 \uACBD\uB85C)\n */\nexport async function copySrcFiles(pkgDir: string, patterns: string[]): Promise<void> {\n const srcDir = path.join(pkgDir, \"src\");\n const distDir = path.join(pkgDir, \"dist\");\n\n for (const pattern of patterns) {\n const files = await fsGlob(pattern, { cwd: srcDir, absolute: true });\n for (const file of files) {\n const relativePath = path.relative(srcDir, file);\n const distPath = path.join(distDir, relativePath);\n await fsMkdir(path.dirname(distPath));\n await fsCopy(file, distPath);\n }\n }\n}\n\n/**\n * src/\uC5D0\uC11C glob \uD328\uD134\uC5D0 \uB9E4\uCE6D\uB418\uB294 \uD30C\uC77C\uC744 \uAC10\uC2DC\uD558\uC5EC dist/\uB85C \uBCF5\uC0AC\uD55C\uB2E4.\n * \uCD08\uAE30 \uBCF5\uC0AC \uD6C4 \uBCC0\uACBD/\uCD94\uAC00/\uC0AD\uC81C\uB97C \uC790\uB3D9 \uBC18\uC601\uD55C\uB2E4.\n *\n * @param pkgDir \uD328\uD0A4\uC9C0 \uB8E8\uD2B8 \uB514\uB809\uD1A0\uB9AC\n * @param patterns glob \uD328\uD134 \uBC30\uC5F4 (src/ \uAE30\uC900 \uC0C1\uB300 \uACBD\uB85C)\n * @returns FsWatcher \uC778\uC2A4\uD134\uC2A4 (shutdown \uC2DC close() \uD638\uCD9C \uD544\uC694)\n */\nexport async function watchCopySrcFiles(pkgDir: string, patterns: string[]): Promise<FsWatcher> {\n const srcDir = path.join(pkgDir, \"src\");\n const distDir = path.join(pkgDir, \"dist\");\n\n // \uCD08\uAE30 \uBCF5\uC0AC\n await copySrcFiles(pkgDir, patterns);\n\n // watch \uC2DC\uC791\n const watchPaths = patterns.map((p) => path.join(srcDir, p));\n const watcher = await FsWatcher.watch(watchPaths);\n\n watcher.onChange({ delay: 300 }, async (changes) => {\n for (const { event, path: filePath } of changes) {\n const relPath = path.relative(srcDir, filePath);\n const distPath = path.join(distDir, relPath);\n\n if (event === \"unlink\") {\n await fsRm(distPath);\n } else if (event === \"add\" || event === \"change\") {\n await fsMkdir(path.dirname(distPath));\n await fsCopy(filePath, distPath);\n }\n }\n });\n\n return watcher;\n}\n"],
5
+ "mappings": "AAAA,OAAO,UAAU;AACjB,SAAS,QAAQ,QAAQ,SAAS,MAAM,iBAAiB;AASzD,eAAsB,aAAa,QAAgB,UAAmC;AACpF,QAAM,SAAS,KAAK,KAAK,QAAQ,KAAK;AACtC,QAAM,UAAU,KAAK,KAAK,QAAQ,MAAM;AAExC,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,MAAM,OAAO,SAAS,EAAE,KAAK,QAAQ,UAAU,KAAK,CAAC;AACnE,eAAW,QAAQ,OAAO;AACxB,YAAM,eAAe,KAAK,SAAS,QAAQ,IAAI;AAC/C,YAAM,WAAW,KAAK,KAAK,SAAS,YAAY;AAChD,YAAM,QAAQ,KAAK,QAAQ,QAAQ,CAAC;AACpC,YAAM,OAAO,MAAM,QAAQ;AAAA,IAC7B;AAAA,EACF;AACF;AAUA,eAAsB,kBAAkB,QAAgB,UAAwC;AAC9F,QAAM,SAAS,KAAK,KAAK,QAAQ,KAAK;AACtC,QAAM,UAAU,KAAK,KAAK,QAAQ,MAAM;AAGxC,QAAM,aAAa,QAAQ,QAAQ;AAGnC,QAAM,aAAa,SAAS,IAAI,CAAC,MAAM,KAAK,KAAK,QAAQ,CAAC,CAAC;AAC3D,QAAM,UAAU,MAAM,UAAU,MAAM,UAAU;AAEhD,UAAQ,SAAS,EAAE,OAAO,IAAI,GAAG,OAAO,YAAY;AAClD,eAAW,EAAE,OAAO,MAAM,SAAS,KAAK,SAAS;AAC/C,YAAM,UAAU,KAAK,SAAS,QAAQ,QAAQ;AAC9C,YAAM,WAAW,KAAK,KAAK,SAAS,OAAO;AAE3C,UAAI,UAAU,UAAU;AACtB,cAAM,KAAK,QAAQ;AAAA,MACrB,WAAW,UAAU,SAAS,UAAU,UAAU;AAChD,cAAM,QAAQ,KAAK,QAAQ,QAAQ,CAAC;AACpC,cAAM,OAAO,UAAU,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -55,4 +55,11 @@ export declare function getTypecheckEnvFromTarget(target: "node" | "browser" | "
55
55
  * esbuild external로 지정하여 빌드 실패를 방지한다.
56
56
  */
57
57
  export declare function collectUninstalledOptionalPeerDeps(pkgDir: string): string[];
58
+ /**
59
+ * 의존성 중 binding.gyp가 있는 네이티브 모듈 수집
60
+ *
61
+ * node-gyp로 빌드되는 네이티브 모듈은 esbuild가 번들링할 수 없으므로
62
+ * external로 지정해야 한다.
63
+ */
64
+ export declare function collectNativeModuleExternals(pkgDir: string): string[];
58
65
  //# 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":"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
+ {"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;AAyCD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAUrE"}
@@ -1,5 +1,5 @@
1
1
  import path from "path";
2
- import { readFileSync } from "fs";
2
+ import { readFileSync, existsSync } from "fs";
3
3
  import fs from "fs/promises";
4
4
  import { createRequire } from "module";
5
5
  import { glob } from "glob";
@@ -106,7 +106,36 @@ function scanOptionalPeerDeps(pkgName, resolveDir, external, visited) {
106
106
  scanOptionalPeerDeps(dep, depDir, external, visited);
107
107
  }
108
108
  }
109
+ function collectNativeModuleExternals(pkgDir) {
110
+ const external = /* @__PURE__ */ new Set();
111
+ const visited = /* @__PURE__ */ new Set();
112
+ const pkgJson = JSON.parse(readFileSync(path.join(pkgDir, "package.json"), "utf-8"));
113
+ for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
114
+ scanNativeModules(dep, pkgDir, external, visited);
115
+ }
116
+ return [...external];
117
+ }
118
+ function scanNativeModules(pkgName, resolveDir, external, visited) {
119
+ if (visited.has(pkgName)) return;
120
+ visited.add(pkgName);
121
+ const req = createRequire(path.join(resolveDir, "noop.js"));
122
+ let pkgJsonPath;
123
+ try {
124
+ pkgJsonPath = req.resolve(`${pkgName}/package.json`);
125
+ } catch {
126
+ return;
127
+ }
128
+ const depDir = path.dirname(pkgJsonPath);
129
+ if (existsSync(path.join(depDir, "binding.gyp"))) {
130
+ external.add(pkgName);
131
+ }
132
+ const depPkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
133
+ for (const dep of Object.keys(depPkgJson.dependencies ?? {})) {
134
+ scanNativeModules(dep, depDir, external, visited);
135
+ }
136
+ }
109
137
  export {
138
+ collectNativeModuleExternals,
110
139
  collectUninstalledOptionalPeerDeps,
111
140
  createLibraryEsbuildOptions,
112
141
  createServerEsbuildOptions,
@@ -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 { 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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",
4
+ "sourcesContent": ["import path from \"path\";\nimport { readFileSync, existsSync } 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\n//#region Native Module Externals\n\n/**\n * \uC758\uC874\uC131 \uC911 binding.gyp\uAC00 \uC788\uB294 \uB124\uC774\uD2F0\uBE0C \uBAA8\uB4C8 \uC218\uC9D1\n *\n * node-gyp\uB85C \uBE4C\uB4DC\uB418\uB294 \uB124\uC774\uD2F0\uBE0C \uBAA8\uB4C8\uC740 esbuild\uAC00 \uBC88\uB4E4\uB9C1\uD560 \uC218 \uC5C6\uC73C\uBBC0\uB85C\n * external\uB85C \uC9C0\uC815\uD574\uC57C \uD55C\uB2E4.\n */\nexport function collectNativeModuleExternals(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 scanNativeModules(dep, pkgDir, external, visited);\n }\n\n return [...external];\n}\n\nfunction scanNativeModules(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\n // binding.gyp \uC874\uC7AC \uC5EC\uBD80\uB85C \uB124\uC774\uD2F0\uBE0C \uBAA8\uB4C8 \uAC10\uC9C0\n if (existsSync(path.join(depDir, \"binding.gyp\"))) {\n external.add(pkgName);\n }\n\n // \uD558\uC704 dependencies\uB3C4 \uC7AC\uADC0 \uD0D0\uC0C9\n const depPkgJson = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\")) as PkgJson;\n for (const dep of Object.keys(depPkgJson.dependencies ?? {})) {\n scanNativeModules(dep, depDir, external, visited);\n }\n}\n\n//#endregion\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -9,6 +9,14 @@ export interface ServerBuildInfo {
9
9
  env?: Record<string, string>;
10
10
  /** 런타임 설정 (dist/.config.json에 기록) */
11
11
  configs?: Record<string, unknown>;
12
+ /** sd.config.ts에서 수동 지정한 external 모듈 */
13
+ externals?: string[];
14
+ /** PM2 설정 (지정 시 dist/pm2.config.cjs 생성) */
15
+ pm2?: {
16
+ name?: string;
17
+ ignoreWatchPaths?: string[];
18
+ noInterpreter?: boolean;
19
+ };
12
20
  }
13
21
  /**
14
22
  * Server 빌드 결과
@@ -29,6 +37,8 @@ export interface ServerWatchInfo {
29
37
  env?: Record<string, string>;
30
38
  /** 런타임 설정 (dist/.config.json에 기록) */
31
39
  configs?: Record<string, unknown>;
40
+ /** sd.config.ts에서 수동 지정한 external 모듈 */
41
+ externals?: string[];
32
42
  }
33
43
  /**
34
44
  * 빌드 이벤트
@@ -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,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"}
1
+ {"version":3,"file":"server.worker.d.ts","sourceRoot":"","sources":["../../src/workers/server.worker.ts"],"names":[],"mappings":"AAcA;;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;IAClC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,2CAA2C;IAC3C,GAAG,CAAC,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;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;IAClC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;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;AA6LD;;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,CA8E9D;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,11 @@ 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, collectUninstalledOptionalPeerDeps } from "../utils/esbuild-config.js";
7
+ import {
8
+ createServerEsbuildOptions,
9
+ collectUninstalledOptionalPeerDeps,
10
+ collectNativeModuleExternals
11
+ } from "../utils/esbuild-config.js";
8
12
  const logger = consola.withTag("sd:cli:server:worker");
9
13
  let esbuildContext;
10
14
  async function cleanup() {
@@ -14,6 +18,111 @@ async function cleanup() {
14
18
  await contextToDispose.dispose();
15
19
  }
16
20
  }
21
+ function collectAllExternals(pkgDir, manualExternals) {
22
+ const optionalPeerDeps = collectUninstalledOptionalPeerDeps(pkgDir);
23
+ const nativeModules = collectNativeModuleExternals(pkgDir);
24
+ const manual = manualExternals ?? [];
25
+ const merged = [.../* @__PURE__ */ new Set([...optionalPeerDeps, ...nativeModules, ...manual])];
26
+ if (optionalPeerDeps.length > 0) {
27
+ logger.debug("\uBBF8\uC124\uCE58 optional peer deps (external):", optionalPeerDeps);
28
+ }
29
+ if (nativeModules.length > 0) {
30
+ logger.debug("\uB124\uC774\uD2F0\uBE0C \uBAA8\uB4C8 (external):", nativeModules);
31
+ }
32
+ if (manual.length > 0) {
33
+ logger.debug("\uC218\uB3D9 \uC9C0\uC815 (external):", manual);
34
+ }
35
+ return merged;
36
+ }
37
+ function generateProductionFiles(info, externals) {
38
+ const distDir = path.join(info.pkgDir, "dist");
39
+ const pkgJson = JSON.parse(fs.readFileSync(path.join(info.pkgDir, "package.json"), "utf-8"));
40
+ logger.debug("GEN package.json...");
41
+ const distPkgJson = {
42
+ name: pkgJson.name,
43
+ version: pkgJson.version,
44
+ type: pkgJson.type
45
+ };
46
+ if (externals.length > 0) {
47
+ const deps = {};
48
+ for (const ext of externals) {
49
+ deps[ext] = "*";
50
+ }
51
+ distPkgJson["dependencies"] = deps;
52
+ }
53
+ fs.writeFileSync(path.join(distDir, "package.json"), JSON.stringify(distPkgJson, void 0, 2));
54
+ logger.debug("GEN mise.toml...");
55
+ const rootMiseTomlPath = path.join(info.cwd, "mise.toml");
56
+ let nodeVersion = "20";
57
+ if (fs.existsSync(rootMiseTomlPath)) {
58
+ const miseContent = fs.readFileSync(rootMiseTomlPath, "utf-8");
59
+ const match = /node\s*=\s*"([^"]+)"/.exec(miseContent);
60
+ if (match != null) {
61
+ nodeVersion = match[1];
62
+ }
63
+ }
64
+ fs.writeFileSync(path.join(distDir, "mise.toml"), `[tools]
65
+ node = "${nodeVersion}"
66
+ `);
67
+ logger.debug("GEN openssl.cnf...");
68
+ fs.writeFileSync(
69
+ path.join(distDir, "openssl.cnf"),
70
+ [
71
+ "nodejs_conf = openssl_init",
72
+ "",
73
+ "[openssl_init]",
74
+ "providers = provider_sect",
75
+ "ssl_conf = ssl_sect",
76
+ "",
77
+ "[provider_sect]",
78
+ "default = default_sect",
79
+ "legacy = legacy_sect",
80
+ "",
81
+ "[default_sect]",
82
+ "activate = 1",
83
+ "",
84
+ "[legacy_sect]",
85
+ "activate = 1",
86
+ "",
87
+ "[ssl_sect]",
88
+ "system_default = system_default_sect",
89
+ "",
90
+ "[system_default_sect]",
91
+ "Options = UnsafeLegacyRenegotiation"
92
+ ].join("\n")
93
+ );
94
+ if (info.pm2 != null) {
95
+ logger.debug("GEN pm2.config.cjs...");
96
+ const pm2Name = info.pm2.name ?? pkgJson.name.replace(/@/g, "").replace(/[/\\]/g, "-");
97
+ const ignoreWatch = JSON.stringify(["node_modules", "www", ...info.pm2.ignoreWatchPaths ?? []]);
98
+ const envObj = {
99
+ NODE_ENV: "production",
100
+ TZ: "Asia/Seoul",
101
+ SD_VERSION: pkgJson.version,
102
+ ...info.env ?? {}
103
+ };
104
+ const envStr = JSON.stringify(envObj, void 0, 4);
105
+ const interpreterLine = info.pm2.noInterpreter ? "" : ` interpreter: cp.execSync("mise which node").toString().trim(),
106
+ `;
107
+ const pm2Config = [
108
+ `const cp = require("child_process");`,
109
+ ``,
110
+ `module.exports = {`,
111
+ ` name: ${JSON.stringify(pm2Name)},`,
112
+ ` script: "main.js",`,
113
+ ` watch: true,`,
114
+ ` watch_delay: 2000,`,
115
+ ` ignore_watch: ${ignoreWatch},`,
116
+ interpreterLine.trimEnd(),
117
+ ` interpreter_args: "--openssl-config=openssl.cnf",`,
118
+ ` env: ${envStr.replace(/\n/g, "\n ")},`,
119
+ ` arrayProcess: "concat",`,
120
+ ` useDelTargetNull: true,`,
121
+ `};`
122
+ ].filter((line) => line !== "").join("\n");
123
+ fs.writeFileSync(path.join(distDir, "pm2.config.cjs"), pm2Config);
124
+ }
125
+ }
17
126
  process.on("SIGTERM", () => {
18
127
  cleanup().catch((err) => {
19
128
  logger.error("cleanup \uC2E4\uD328", err);
@@ -34,10 +143,7 @@ async function build(info) {
34
143
  const parsedConfig = parseRootTsconfig(info.cwd);
35
144
  const entryPoints = getPackageSourceFiles(info.pkgDir, parsedConfig);
36
145
  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
- }
146
+ const external = collectAllExternals(info.pkgDir, info.externals);
41
147
  const esbuildOptions = createServerEsbuildOptions({
42
148
  pkgDir: info.pkgDir,
43
149
  entryPoints,
@@ -48,6 +154,7 @@ async function build(info) {
48
154
  const result = await esbuild.build(esbuildOptions);
49
155
  const confDistPath = path.join(info.pkgDir, "dist", ".config.json");
50
156
  fs.writeFileSync(confDistPath, JSON.stringify(info.configs ?? {}, void 0, 2));
157
+ generateProductionFiles(info, external);
51
158
  const errors = result.errors.map((e) => e.text);
52
159
  return {
53
160
  success: result.errors.length === 0,
@@ -78,10 +185,7 @@ async function startWatch(info) {
78
185
  resolveFirstBuild = resolve;
79
186
  });
80
187
  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
- }
188
+ const external = collectAllExternals(info.pkgDir, info.externals);
85
189
  const baseOptions = createServerEsbuildOptions({
86
190
  pkgDir: info.pkgDir,
87
191
  entryPoints,
@@ -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, 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": "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",
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 {\n createServerEsbuildOptions,\n collectUninstalledOptionalPeerDeps,\n collectNativeModuleExternals,\n} 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 /** sd.config.ts\uC5D0\uC11C \uC218\uB3D9 \uC9C0\uC815\uD55C external \uBAA8\uB4C8 */\n externals?: string[];\n /** PM2 \uC124\uC815 (\uC9C0\uC815 \uC2DC dist/pm2.config.cjs \uC0DD\uC131) */\n pm2?: {\n name?: string;\n ignoreWatchPaths?: string[];\n noInterpreter?: boolean;\n };\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 /** sd.config.ts\uC5D0\uC11C \uC218\uB3D9 \uC9C0\uC815\uD55C external \uBAA8\uB4C8 */\n externals?: string[];\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/**\n * \uC138 \uAC00\uC9C0 \uC18C\uC2A4\uC5D0\uC11C external \uBAA8\uB4C8\uC744 \uC218\uC9D1\uD558\uC5EC \uD569\uCE5C\uB2E4.\n * 1. \uBBF8\uC124\uCE58 optional peer deps\n * 2. binding.gyp \uB124\uC774\uD2F0\uBE0C \uBAA8\uB4C8\n * 3. sd.config.ts \uC218\uB3D9 \uC9C0\uC815\n */\nfunction collectAllExternals(pkgDir: string, manualExternals?: string[]): string[] {\n const optionalPeerDeps = collectUninstalledOptionalPeerDeps(pkgDir);\n const nativeModules = collectNativeModuleExternals(pkgDir);\n const manual = manualExternals ?? [];\n\n const merged = [...new Set([...optionalPeerDeps, ...nativeModules, ...manual])];\n\n if (optionalPeerDeps.length > 0) {\n logger.debug(\"\uBBF8\uC124\uCE58 optional peer deps (external):\", optionalPeerDeps);\n }\n if (nativeModules.length > 0) {\n logger.debug(\"\uB124\uC774\uD2F0\uBE0C \uBAA8\uB4C8 (external):\", nativeModules);\n }\n if (manual.length > 0) {\n logger.debug(\"\uC218\uB3D9 \uC9C0\uC815 (external):\", manual);\n }\n\n return merged;\n}\n\n/**\n * \uD504\uB85C\uB355\uC158 \uBC30\uD3EC\uC6A9 \uD30C\uC77C \uC0DD\uC131 (\uC77C\uD68C\uC131 \uBE4C\uB4DC\uC5D0\uC11C\uB9CC \uD638\uCD9C)\n *\n * - dist/package.json: external \uBAA8\uB4C8\uC744 dependencies\uB85C \uD3EC\uD568\n * - dist/mise.toml: Node \uBC84\uC804 \uC9C0\uC815\n * - dist/openssl.cnf: \uB808\uAC70\uC2DC OpenSSL \uD504\uB85C\uBC14\uC774\uB354 \uD65C\uC131\uD654\n * - dist/pm2.config.cjs: PM2 \uD504\uB85C\uC138\uC2A4 \uC124\uC815 (pm2 \uC635\uC158\uC774 \uC788\uC744 \uB54C\uB9CC)\n */\nfunction generateProductionFiles(info: ServerBuildInfo, externals: string[]): void {\n const distDir = path.join(info.pkgDir, \"dist\");\n const pkgJson = JSON.parse(fs.readFileSync(path.join(info.pkgDir, \"package.json\"), \"utf-8\"));\n\n // dist/package.json\n logger.debug(\"GEN package.json...\");\n const distPkgJson: Record<string, unknown> = {\n name: pkgJson.name,\n version: pkgJson.version,\n type: pkgJson.type,\n };\n if (externals.length > 0) {\n const deps: Record<string, string> = {};\n for (const ext of externals) {\n deps[ext] = \"*\";\n }\n distPkgJson[\"dependencies\"] = deps;\n }\n fs.writeFileSync(path.join(distDir, \"package.json\"), JSON.stringify(distPkgJson, undefined, 2));\n\n // dist/mise.toml\n logger.debug(\"GEN mise.toml...\");\n const rootMiseTomlPath = path.join(info.cwd, \"mise.toml\");\n let nodeVersion = \"20\";\n if (fs.existsSync(rootMiseTomlPath)) {\n const miseContent = fs.readFileSync(rootMiseTomlPath, \"utf-8\");\n const match = /node\\s*=\\s*\"([^\"]+)\"/.exec(miseContent);\n if (match != null) {\n nodeVersion = match[1];\n }\n }\n fs.writeFileSync(path.join(distDir, \"mise.toml\"), `[tools]\\nnode = \"${nodeVersion}\"\\n`);\n\n // dist/openssl.cnf\n logger.debug(\"GEN openssl.cnf...\");\n fs.writeFileSync(\n path.join(distDir, \"openssl.cnf\"),\n [\n \"nodejs_conf = openssl_init\",\n \"\",\n \"[openssl_init]\",\n \"providers = provider_sect\",\n \"ssl_conf = ssl_sect\",\n \"\",\n \"[provider_sect]\",\n \"default = default_sect\",\n \"legacy = legacy_sect\",\n \"\",\n \"[default_sect]\",\n \"activate = 1\",\n \"\",\n \"[legacy_sect]\",\n \"activate = 1\",\n \"\",\n \"[ssl_sect]\",\n \"system_default = system_default_sect\",\n \"\",\n \"[system_default_sect]\",\n \"Options = UnsafeLegacyRenegotiation\",\n ].join(\"\\n\"),\n );\n\n // dist/pm2.config.cjs (pm2 \uC124\uC815\uC774 \uC788\uC744 \uB54C\uB9CC)\n if (info.pm2 != null) {\n logger.debug(\"GEN pm2.config.cjs...\");\n\n const pm2Name = info.pm2.name ?? pkgJson.name.replace(/@/g, \"\").replace(/[/\\\\]/g, \"-\");\n const ignoreWatch = JSON.stringify([\"node_modules\", \"www\", ...(info.pm2.ignoreWatchPaths ?? [])]);\n const envObj: Record<string, string> = {\n NODE_ENV: \"production\",\n TZ: \"Asia/Seoul\",\n SD_VERSION: pkgJson.version,\n ...(info.env ?? {}),\n };\n const envStr = JSON.stringify(envObj, undefined, 4);\n\n const interpreterLine = info.pm2.noInterpreter\n ? \"\"\n : ` interpreter: cp.execSync(\"mise which node\").toString().trim(),\\n`;\n\n const pm2Config = [\n `const cp = require(\"child_process\");`,\n ``,\n `module.exports = {`,\n ` name: ${JSON.stringify(pm2Name)},`,\n ` script: \"main.js\",`,\n ` watch: true,`,\n ` watch_delay: 2000,`,\n ` ignore_watch: ${ignoreWatch},`,\n interpreterLine.trimEnd(),\n ` interpreter_args: \"--openssl-config=openssl.cnf\",`,\n ` env: ${envStr.replace(/\\n/g, \"\\n \")},`,\n ` arrayProcess: \"concat\",`,\n ` useDelTargetNull: true,`,\n `};`,\n ]\n .filter((line) => line !== \"\")\n .join(\"\\n\");\n\n fs.writeFileSync(path.join(distDir, \"pm2.config.cjs\"), pm2Config);\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 // \uBAA8\uB4E0 external \uC218\uC9D1 (optional peer deps + native modules + manual)\n const external = collectAllExternals(info.pkgDir, info.externals);\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 // Generate production files (package.json, mise.toml, openssl.cnf, pm2.config.cjs)\n generateProductionFiles(info, external);\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 // \uBAA8\uB4E0 external \uC218\uC9D1 (optional peer deps + native modules + manual)\n const external = collectAllExternals(info.pkgDir, info.externals);\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": "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",
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.28",
4
+ "version": "13.0.0-beta.30",
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-common": "13.0.0-beta.28",
45
- "@simplysm/core-node": "13.0.0-beta.28",
46
- "@simplysm/storage": "13.0.0-beta.28"
44
+ "@simplysm/core-common": "13.0.0-beta.30",
45
+ "@simplysm/core-node": "13.0.0-beta.30",
46
+ "@simplysm/storage": "13.0.0-beta.30"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/semver": "^7.7.1",
@@ -4,7 +4,7 @@
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "dependencies": {
7
- "@simplysm/solid": "~13.0.0-beta.28",
7
+ "@simplysm/solid": "~13.0.0-beta.30",
8
8
  {{#if router}}
9
9
  "@solidjs/router": "^0.15.4",
10
10
  {{/if}}
@@ -4,7 +4,7 @@
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "dependencies": {
7
- "@simplysm/core-common": "~13.0.0-beta.28",
8
- "@simplysm/service-server": "~13.0.0-beta.28"
7
+ "@simplysm/core-common": "~13.0.0-beta.30",
8
+ "@simplysm/service-server": "~13.0.0-beta.30"
9
9
  }
10
10
  }
@@ -15,9 +15,9 @@
15
15
  "vitest": "vitest"
16
16
  },
17
17
  "devDependencies": {
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",
18
+ "@simplysm/sd-cli": "~13.0.0-beta.30",
19
+ "@simplysm/claude": "~13.0.0-beta.30",
20
+ "@simplysm/eslint-plugin": "~13.0.0-beta.30",
21
21
  "@types/node": "^20.19.33",
22
22
  "eslint": "^9.39.2",
23
23
  "prettier": "^3.8.1",