@obov/mext 0.3.1 → 0.4.0
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/build.js +67 -4
- package/dist/build.js.map +1 -1
- package/dist/cli/ask-url.d.ts +16 -0
- package/dist/cli/ask-url.js +27 -0
- package/dist/cli/ask-url.js.map +1 -0
- package/dist/cli/build.js +7 -1
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev-server.d.ts +7 -1
- package/dist/cli/dev-server.js +15 -2
- package/dist/cli/dev-server.js.map +1 -1
- package/dist/cli/dev.js +22 -7
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/login.d.ts +5 -0
- package/dist/cli/login.js +11 -7
- package/dist/cli/login.js.map +1 -1
- package/dist/cli/logout.js +4 -6
- package/dist/cli/logout.js.map +1 -1
- package/dist/cli/output.d.ts +1 -1
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/run.js +7 -3
- package/dist/cli/run.js.map +1 -1
- package/dist/client/cache.d.ts +14 -4
- package/dist/client/cache.js +10 -3
- package/dist/client/cache.js.map +1 -1
- package/dist/client/main.js +11 -10
- package/dist/client/main.js.map +1 -1
- package/dist/client/manifest.d.ts +13 -1
- package/dist/client/manifest.js +43 -0
- package/dist/client/manifest.js.map +1 -1
- package/dist/client/runner.d.ts +3 -1
- package/dist/client/runner.js +80 -19
- package/dist/client/runner.js.map +1 -1
- package/dist/client/task.d.ts +47 -0
- package/dist/client/task.js +126 -0
- package/dist/client/task.js.map +1 -0
- package/dist/command.d.ts +30 -3
- package/dist/command.js +16 -0
- package/dist/command.js.map +1 -1
- package/dist/config.d.ts +40 -6
- package/dist/config.js +57 -8
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +3 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +17 -5
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/instrumentation.d.ts +14 -2
- package/dist/instrumentation.js +12 -4
- package/dist/instrumentation.js.map +1 -1
- package/dist/invoke.d.ts +38 -0
- package/dist/invoke.js +72 -3
- package/dist/invoke.js.map +1 -1
- package/dist/local-bin.js +5 -3
- package/dist/local-bin.js.map +1 -1
- package/dist/manifest.d.ts +48 -3
- package/dist/manifest.js +14 -3
- package/dist/manifest.js.map +1 -1
- package/dist/mcp/constants.d.ts +4 -0
- package/dist/mcp/constants.js +4 -0
- package/dist/mcp/constants.js.map +1 -1
- package/dist/mcp/dispatch.d.ts +21 -7
- package/dist/mcp/dispatch.js +42 -7
- package/dist/mcp/dispatch.js.map +1 -1
- package/dist/mcp/http.d.ts +23 -5
- package/dist/mcp/http.js +64 -9
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/index.d.ts +14 -6
- package/dist/mcp/index.js +7 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mrtr.d.ts +40 -8
- package/dist/mcp/mrtr.js +32 -11
- package/dist/mcp/mrtr.js.map +1 -1
- package/dist/mcp/prompts.d.ts +25 -0
- package/dist/mcp/prompts.js +164 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +48 -0
- package/dist/mcp/resources.js +142 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +30 -5
- package/dist/mcp/server.js +143 -16
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +5 -0
- package/dist/mcp/stdio.js +16 -3
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp/subscriptions.d.ts +61 -0
- package/dist/mcp/subscriptions.js +188 -0
- package/dist/mcp/subscriptions.js.map +1 -0
- package/dist/mcp/tasks.d.ts +127 -0
- package/dist/mcp/tasks.js +448 -0
- package/dist/mcp/tasks.js.map +1 -0
- package/dist/module-files.d.ts +24 -0
- package/dist/module-files.js +97 -0
- package/dist/module-files.js.map +1 -0
- package/dist/prompt.d.ts +133 -0
- package/dist/prompt.js +222 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +6 -0
- package/dist/registry.js.map +1 -1
- package/dist/remote/client.d.ts +17 -1
- package/dist/remote/client.js +18 -2
- package/dist/remote/client.js.map +1 -1
- package/dist/resource.d.ts +169 -0
- package/dist/resource.js +301 -0
- package/dist/resource.js.map +1 -0
- package/dist/route.d.ts +71 -0
- package/dist/route.js +280 -0
- package/dist/route.js.map +1 -0
- package/dist/start.d.ts +14 -3
- package/dist/start.js +76 -11
- package/dist/start.js.map +1 -1
- package/dist/state.d.ts +38 -0
- package/dist/state.js +98 -0
- package/dist/state.js.map +1 -0
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -9,13 +9,16 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
10
|
import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { isBuiltin } from "node:module";
|
|
12
|
-
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
12
|
+
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
13
13
|
import { buildCustomerCli, CLI_DIR, customerCliIssues, projectVersion } from "./build-cli.js";
|
|
14
14
|
import { cliBuildIssues } from "./cli/args.js";
|
|
15
|
-
import { CONFIG_FILE, loadConfig, resolveCommandsDir } from "./config.js";
|
|
15
|
+
import { CONFIG_FILE, loadConfig, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from "./config.js";
|
|
16
16
|
import { MextBuildError } from "./errors.js";
|
|
17
17
|
import { buildManifest, manifestHash, MANIFEST_SCHEMA_VERSION } from "./manifest.js";
|
|
18
|
+
import { collectPrompts, collectPromptSet, describePrompt } from "./prompt.js";
|
|
18
19
|
import { collectRegistry } from "./registry.js";
|
|
20
|
+
import { collectResources, collectResourceSet, describeResource, resourceEntries } from "./resource.js";
|
|
21
|
+
import { collectRoutes } from "./route.js";
|
|
19
22
|
import { collectCommands } from "./scan.js";
|
|
20
23
|
import { mextVersion } from "./version.js";
|
|
21
24
|
/** mext build 산출 폴더 (도입 프로젝트 루트 기준) */
|
|
@@ -62,7 +65,25 @@ export async function buildProject(options = {}) {
|
|
|
62
65
|
const commandsDir = resolveCommandsDir(cwd, config);
|
|
63
66
|
const scanned = await collectCommands(commandsDir);
|
|
64
67
|
const { registry, issues: registryIssues } = collectRegistry(scanned);
|
|
65
|
-
const
|
|
68
|
+
const routesDir = resolveRoutesDir(cwd, config);
|
|
69
|
+
const routes = await collectRoutes(routesDir);
|
|
70
|
+
const resourcesDir = resolveResourcesDir(cwd, config);
|
|
71
|
+
const scannedResources = await collectResources(resourcesDir);
|
|
72
|
+
const { resources, issues: resourceIssues } = collectResourceSet(scannedResources.inputs, basename(resourcesDir));
|
|
73
|
+
const promptsDir = resolvePromptsDir(cwd, config);
|
|
74
|
+
const scannedPrompts = await collectPrompts(promptsDir);
|
|
75
|
+
const { prompts, issues: promptIssues } = collectPromptSet(scannedPrompts.inputs, basename(promptsDir));
|
|
76
|
+
const issues = [
|
|
77
|
+
...scanned.issues,
|
|
78
|
+
...registryIssues,
|
|
79
|
+
...cliBuildIssues(registry),
|
|
80
|
+
...customerCliIssues(config.cli, registry),
|
|
81
|
+
...scannedResources.issues,
|
|
82
|
+
...resourceIssues,
|
|
83
|
+
...scannedPrompts.issues,
|
|
84
|
+
...promptIssues,
|
|
85
|
+
...routes.issues,
|
|
86
|
+
];
|
|
66
87
|
if (issues.length > 0)
|
|
67
88
|
throw new MextBuildError(issues);
|
|
68
89
|
// 엔트리 이름 = 출력 경로 (확장자 제외). 명령어 = commands/ 아래 소스 경로 그대로
|
|
@@ -74,6 +95,24 @@ export async function buildProject(options = {}) {
|
|
|
74
95
|
input[name] = join(commandsDir, file);
|
|
75
96
|
moduleOf.set(entry.id, `${name}.js`);
|
|
76
97
|
}
|
|
98
|
+
// 자원 = resources/ 아래 소스 경로 그대로 (§12.3)
|
|
99
|
+
const resourceList = resourceEntries(resources).sort((a, b) => (a.uri < b.uri ? -1 : a.uri > b.uri ? 1 : 0));
|
|
100
|
+
const resourceModuleOf = new Map();
|
|
101
|
+
for (const entry of resourceList) {
|
|
102
|
+
const name = `resources/${entry.file.replace(/\.ts$/, "")}`;
|
|
103
|
+
input[name] = join(resourcesDir, entry.file);
|
|
104
|
+
resourceModuleOf.set(entry.uri, `${name}.js`);
|
|
105
|
+
}
|
|
106
|
+
// 프롬프트 = prompts/ 아래 소스 경로 그대로 (§12.3)
|
|
107
|
+
const promptList = [...prompts.values()];
|
|
108
|
+
const promptModuleOf = new Map();
|
|
109
|
+
for (const entry of promptList) {
|
|
110
|
+
const name = `prompts/${entry.file.replace(/\.ts$/, "")}`;
|
|
111
|
+
input[name] = join(promptsDir, entry.file);
|
|
112
|
+
promptModuleOf.set(entry.name, `${name}.js`);
|
|
113
|
+
}
|
|
114
|
+
for (const route of routes.routes)
|
|
115
|
+
input[routeModuleName(route.file)] = join(routesDir, route.file);
|
|
77
116
|
const hasConfig = existsSync(join(cwd, CONFIG_FILE));
|
|
78
117
|
if (hasConfig)
|
|
79
118
|
input.config = join(cwd, CONFIG_FILE);
|
|
@@ -140,18 +179,35 @@ export async function buildProject(options = {}) {
|
|
|
140
179
|
throw new Error(`mext build: rolldown did not emit ${name}.js`);
|
|
141
180
|
}
|
|
142
181
|
const base = buildManifest(registry);
|
|
143
|
-
const hash = manifestHash(base.commands
|
|
182
|
+
const hash = manifestHash(base.commands, {
|
|
183
|
+
resources: resourceList.map((r) => r.uri),
|
|
184
|
+
prompts: promptList.map((p) => ({ name: p.name, argsSchema: p.argsSchema })),
|
|
185
|
+
});
|
|
144
186
|
const version = mextVersion();
|
|
145
187
|
const manifest = {
|
|
146
188
|
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
147
189
|
mextVersion: version,
|
|
148
190
|
buildId: buildIdOf(version, hash, output),
|
|
149
191
|
manifestHash: hash,
|
|
192
|
+
tools: config.tools ?? "execute",
|
|
150
193
|
...(hasConfig ? { config: "config.js" } : {}),
|
|
151
194
|
...(hasInstrumentation ? { instrumentation: "instrumentation.js" } : {}),
|
|
152
195
|
...(base.description !== undefined ? { description: base.description } : {}),
|
|
153
196
|
namespaces: base.namespaces,
|
|
154
197
|
commands: base.commands.map((c) => ({ ...c, module: moduleOf.get(c.id) })),
|
|
198
|
+
...(resourceList.length > 0
|
|
199
|
+
? { resources: resourceList.map((r) => ({ ...describeResource(r), module: resourceModuleOf.get(r.uri) })) }
|
|
200
|
+
: {}),
|
|
201
|
+
...(promptList.length > 0
|
|
202
|
+
? { prompts: promptList.map((p) => ({ ...describePrompt(p), module: promptModuleOf.get(p.name) })) }
|
|
203
|
+
: {}),
|
|
204
|
+
...(routes.routes.length > 0
|
|
205
|
+
? {
|
|
206
|
+
routes: routes.routes
|
|
207
|
+
.map((r) => ({ path: r.path, file: r.file, methods: r.methods, module: `${routeModuleName(r.file)}.js` }))
|
|
208
|
+
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
|
|
209
|
+
}
|
|
210
|
+
: {}),
|
|
155
211
|
};
|
|
156
212
|
const generated = {
|
|
157
213
|
"package.json": `${JSON.stringify({ type: "module" }, null, 2)}\n`,
|
|
@@ -265,6 +321,13 @@ function cleanOutDir(outDir) {
|
|
|
265
321
|
rmSync(join(outDir, name), { recursive: true, force: true });
|
|
266
322
|
}
|
|
267
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* route 엔트리 이름 = routes/ 아래 소스 경로, [name] → _name_ (rolldown 이 [ ] 를 바꾸므로 직접 정한다).
|
|
326
|
+
* `_` 접두 파일 · 폴더는 route 가 아니라 충돌 없음. routes/items/[id].ts → routes/items/_id_
|
|
327
|
+
*/
|
|
328
|
+
function routeModuleName(file) {
|
|
329
|
+
return `routes/${file.replace(/\.ts$/, "").replace(/\[([^\]/]+)\]/g, "_$1_")}`;
|
|
330
|
+
}
|
|
268
331
|
/** "@scope/pkg/sub" → "@scope/pkg" · "pkg/sub" → "pkg" */
|
|
269
332
|
function packageName(specifier) {
|
|
270
333
|
const parts = specifier.split("/");
|
package/dist/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\"\nimport { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\"\nimport { isBuiltin } from \"node:module\"\nimport { isAbsolute, join, relative, resolve, sep } from \"node:path\"\nimport { buildCustomerCli, CLI_DIR, customerCliIssues, projectVersion, type CustomerCliBuild } from \"./build-cli.ts\"\nimport { cliBuildIssues } from \"./cli/args.ts\"\nimport { CONFIG_FILE, loadConfig, resolveCommandsDir } from \"./config.ts\"\nimport { MextBuildError } from \"./errors.ts\"\nimport { buildManifest, manifestHash, MANIFEST_SCHEMA_VERSION, type BuildManifest } from \"./manifest.ts\"\nimport { collectRegistry } from \"./registry.ts\"\nimport { collectCommands } from \"./scan.ts\"\nimport { mextVersion } from \"./version.ts\"\n\n/** mext build 산출 폴더 (도입 프로젝트 루트 기준) */\nexport const BUILD_DIR = \".mext\"\nexport const BUILD_MANIFEST_FILE = \"manifest.json\"\nexport const INSTRUMENTATION_FILE = \"instrumentation.ts\"\n/** 생성 파일 (server.js · handler.js) 이 import 하는 런타임 엔트리 */\nexport const START_ENTRY = \"@obov/mext/start\"\n/** 로컬 bin (cli.local) 실행 파일 · cli.errors 번들 */\nexport const LOCAL_BIN_FILE = \"bin.js\"\nexport const LOCAL_BIN_ERRORS = \"cli-errors\"\n/** 빌드가 지우지 않는 .mext/ 하위 (mext dev 산출 · 잠금) */\nconst PRESERVED_ENTRIES = new Set([\"dev\"])\n\n/** rolldown 모듈 중 mext build 가 쓰는 부분 */\nexport interface RolldownModule {\n build(options: Record<string, unknown>): Promise<{ output: readonly RolldownOutputItem[] }>\n}\n\nexport interface RolldownOutputItem {\n type: \"chunk\" | \"asset\"\n fileName: string\n /** chunk 코드 */\n code?: string\n isEntry?: boolean\n name?: string\n}\n\nexport interface BuildOptions {\n /** 도입 프로젝트 루트 (mext.config.ts · package.json · instrumentation.ts 위치). 기본 process.cwd() */\n cwd?: string\n /** 산출 폴더. 기본 <cwd>/.mext. 기존 내용은 dev/ 외 삭제 */\n outDir?: string\n /** rolldown 로더 (테스트 주입). 기본 import(\"rolldown\") (선택 peer dependency) */\n importRolldown?: () => Promise<RolldownModule>\n}\n\nexport interface BuildWarning {\n /**\n * UNDECLARED_DEPENDENCY = 외부로 남긴 패키지가 package.json dependencies · peerDependencies · optionalDependencies 에 없음.\n * LOCAL_BIN_UNDECLARED = cli.local 인데 package.json bin[\"<bin>\"] 이 .mext/bin.js 가 아님\n */\n code: \"UNDECLARED_DEPENDENCY\" | \"BUNDLER_WARNING\" | \"LOCAL_BIN_UNDECLARED\"\n message: string\n}\n\nexport interface BuildResult {\n /** 산출 폴더 절대 경로 */\n outDir: string\n manifest: BuildManifest\n /** outDir 기준 생성 파일 (posix, 정렬) */\n files: string[]\n warnings: BuildWarning[]\n /** 고객 CLI (.mext/cli/). config.cli 가 있고 local 이 아닐 때 */\n cli?: CustomerCliBuild\n /** 로컬 bin (.mext/bin.js). config.cli.local 일 때 */\n localBin?: { bin: string; version: string }\n}\n\n/** rolldown 을 찾을 수 없음. message 에 설치 명령 */\nexport class RolldownUnavailableError extends Error {\n readonly installCommand: string\n\n constructor(installCommand: string, cause?: unknown) {\n super(`mext build requires rolldown (optional peer dependency of @obov/mext). Install it: ${installCommand}`, { cause })\n this.name = \"RolldownUnavailableError\"\n this.installCommand = installCommand\n }\n}\n\n/**\n * mext build: commands/ → .mext/ (§10).\n * 1. rolldown 확인 (없으면 RolldownUnavailableError)\n * 2. 검증: 파일 규칙 · import · Registry (ID · 별칭 · 스키마) · CLI 변환 issue 를 모두 모아 MextBuildError 한 번\n * 3. rolldown 다중 엔트리 번들: commands/**\\/*.js (명령어별) · config.js · instrumentation.js · chunks/. 패키지 import 는 외부\n * 4. server.js · handler.js (얇은 생성 파일, 런타임 = @obov/mext/start) · package.json (type module) · manifest.json (마지막)\n */\nexport async function buildProject(options: BuildOptions = {}): Promise<BuildResult> {\n const cwd = resolve(options.cwd ?? process.cwd())\n const outDir = resolve(cwd, options.outDir ?? BUILD_DIR)\n // 빌드 전 outDir 을 비우므로 프로젝트 폴더 자체 · 상위는 거부\n const up = relative(outDir, cwd)\n if (up === \"\" || (!up.startsWith(\"..\") && !isAbsolute(up))) {\n throw new Error(`mext build: outDir must not be the project directory or its parent (${outDir})`)\n }\n const rolldown = await (options.importRolldown ?? importRolldown)().catch((error: unknown) => {\n if (isModuleNotFound(error, \"rolldown\")) throw new RolldownUnavailableError(installCommand(cwd), error)\n throw error\n })\n\n const config = await loadConfig(cwd)\n const commandsDir = resolveCommandsDir(cwd, config)\n const scanned = await collectCommands(commandsDir)\n const { registry, issues: registryIssues } = collectRegistry(scanned)\n const issues = [...scanned.issues, ...registryIssues, ...cliBuildIssues(registry), ...customerCliIssues(config.cli, registry)]\n if (issues.length > 0) throw new MextBuildError(issues)\n\n // 엔트리 이름 = 출력 경로 (확장자 제외). 명령어 = commands/ 아래 소스 경로 그대로\n const input: Record<string, string> = {}\n const moduleOf = new Map<string, string>()\n for (const entry of registry.commands.values()) {\n const file = entry.file!\n const name = `commands/${file.replace(/\\.ts$/, \"\")}`\n input[name] = join(commandsDir, file)\n moduleOf.set(entry.id, `${name}.js`)\n }\n const hasConfig = existsSync(join(cwd, CONFIG_FILE))\n if (hasConfig) input.config = join(cwd, CONFIG_FILE)\n const hasInstrumentation = existsSync(join(cwd, INSTRUMENTATION_FILE))\n if (hasInstrumentation) input.instrumentation = join(cwd, INSTRUMENTATION_FILE)\n const local = config.cli?.local === true ? config.cli : undefined\n if (local?.errors !== undefined) {\n const errorsFile = resolve(cwd, local.errors)\n if (!existsSync(errorsFile)) throw new MextBuildError([{ code: \"INVALID_CONFIG\", message: `cli.errors file not found: ${local.errors}` }])\n input[LOCAL_BIN_ERRORS] = errorsFile\n }\n\n cleanOutDir(outDir)\n\n const warnings: BuildWarning[] = []\n /** 외부 패키지 이름 → 처음 import 한 파일 */\n const externals = new Map<string, string | undefined>()\n let output: readonly RolldownOutputItem[]\n try {\n ;({ output } = await rolldown.build({\n cwd,\n input,\n platform: \"node\",\n // 상대 · 절대 경로 · # (package.json imports) = 번들. 그 외 bare import = 외부 (도입 프로젝트 node_modules 에서 해석)\n external: (id: string, importer: string | undefined): boolean => {\n if (id.startsWith(\".\") || id.startsWith(\"#\") || id.startsWith(\"\\0\") || isAbsolute(id)) return false\n if (id.startsWith(\"node:\") || isBuiltin(id)) return true\n const pkg = packageName(id)\n if (!externals.has(pkg) && importer !== undefined && !importer.startsWith(\"\\0\")) externals.set(pkg, importer)\n return true\n },\n transform: { target: \"node22\" },\n logLevel: \"warn\",\n onLog: (_level: string, log: { message: string }) => warnings.push({ code: \"BUNDLER_WARNING\", message: log.message }),\n output: {\n dir: outDir,\n format: \"esm\",\n entryFileNames: \"[name].js\",\n chunkFileNames: \"chunks/[name]-[hash].js\",\n sourcemap: true,\n },\n }))\n } catch (error) {\n throw new MextBuildError([{ code: \"BUNDLE_FAILED\", message: error instanceof Error ? error.message : String(error) }])\n }\n\n const declared = declaredDependencies(cwd)\n for (const [pkg, importer] of externals) {\n if (declared.has(pkg)) continue\n const from = importer === undefined ? \"\" : ` (imported by ${toPosix(relative(cwd, importer))})`\n warnings.push({\n code: \"UNDECLARED_DEPENDENCY\",\n message: `\"${pkg}\" is not in package.json dependencies${from}. It stays external and must be installed where .mext/ runs`,\n })\n }\n\n const emitted = new Set(output.map((o) => o.fileName))\n for (const name of Object.keys(input)) {\n if (!emitted.has(`${name}.js`)) throw new Error(`mext build: rolldown did not emit ${name}.js`)\n }\n\n const base = buildManifest(registry)\n const hash = manifestHash(base.commands)\n const version = mextVersion()\n const manifest: BuildManifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n mextVersion: version,\n buildId: buildIdOf(version, hash, output),\n manifestHash: hash,\n ...(hasConfig ? { config: \"config.js\" } : {}),\n ...(hasInstrumentation ? { instrumentation: \"instrumentation.js\" } : {}),\n ...(base.description !== undefined ? { description: base.description } : {}),\n namespaces: base.namespaces,\n commands: base.commands.map((c) => ({ ...c, module: moduleOf.get(c.id)! })),\n }\n\n const generated: Record<string, string> = {\n \"package.json\": `${JSON.stringify({ type: \"module\" }, null, 2)}\\n`,\n \"server.js\": SERVER_JS,\n \"handler.js\": HANDLER_JS,\n }\n const localBin = local ? { bin: local.bin, version: local.version ?? projectVersion(cwd) ?? \"0.0.0\" } : undefined\n if (localBin) {\n generated[LOCAL_BIN_FILE] = localBinJs({ ...localBin, ...(local?.errors !== undefined ? { errors: `${LOCAL_BIN_ERRORS}.js` } : {}) })\n const declaredBin = packageBin(cwd, localBin.bin)\n const expected = `${toPosix(relative(cwd, outDir))}/${LOCAL_BIN_FILE}`\n if (declaredBin === undefined || declaredBin.replace(/^\\.\\//, \"\") !== expected) {\n warnings.push({\n code: \"LOCAL_BIN_UNDECLARED\",\n message: `cli.local: add \"bin\": { \"${localBin.bin}\": \"${expected}\" } to package.json (and include ${toPosix(relative(cwd, outDir))} in \"files\")`,\n })\n }\n }\n for (const [file, content] of Object.entries(generated)) writeFileSync(join(outDir, file), content)\n if (localBin) chmodSync(join(outDir, LOCAL_BIN_FILE), 0o755)\n\n // 고객 CLI (.mext/cli/, §5): manifest · buildId 확정 후, manifest.json 쓰기 전. 로컬 bin 이면 만들지 않는다\n const cli = config.cli && !local ? await buildCustomerCli({ rolldown, cwd, outDir, cli: config.cli, manifest }) : undefined\n\n // manifest.json 은 마지막: 중간 실패한 빌드는 manifest 가 없어 mext start 가 \"mext build 먼저\" 로 거부\n writeFileSync(join(outDir, BUILD_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\\n`)\n\n const files = [\n ...emitted,\n ...Object.keys(generated),\n BUILD_MANIFEST_FILE,\n ...(cli?.files.map((f) => `${CLI_DIR}/${f}`) ?? []),\n ].sort()\n return { outDir, manifest, files, warnings, ...(cli ? { cli } : {}), ...(localBin ? { localBin } : {}) }\n}\n\n/**\n * .mext/bin.js (로컬 bin, cli.local). 계약: mainLocalBin(.mext 폴더 URL, { bin, version, errors? }).\n * 도입 프로젝트 package.json bin 이 이 파일을 가리킨다 (npm 이 symlink 해도 import.meta.url = 실제 경로)\n */\nexport function localBinJs(options: { bin: string; version: string; errors?: string }): string {\n return `#!/usr/bin/env node\n// Generated by mext build. Do not edit.\n// Local bin (cli.local): ${options.bin} help · ${options.bin} <namespace> <command> · ${options.bin} mcp serve\nimport { mainLocalBin } from \"${START_ENTRY}\"\n\nawait mainLocalBin(new URL(\".\", import.meta.url), ${JSON.stringify(options)})\n`\n}\n\n/** package.json bin[name] (문자열 bin = 패키지 이름이 name 일 때) */\nfunction packageBin(cwd: string, name: string): string | undefined {\n try {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as { name?: unknown; bin?: unknown }\n if (typeof pkg.bin === \"string\") return pkg.name === name ? pkg.bin : undefined\n if (typeof pkg.bin === \"object\" && pkg.bin !== null) {\n const v = (pkg.bin as Record<string, unknown>)[name]\n return typeof v === \"string\" ? v : undefined\n }\n } catch {\n // package.json 없음 · 형식 오류 = 미선언\n }\n return undefined\n}\n\n/**\n * .mext/server.js. 계약: startFromBuild(.mext 폴더 URL, { argv, env }) → exit code.\n * argv = server.js 뒤 인자 (--stdio), env = PORT · HOST\n */\nexport const SERVER_JS = `// Generated by mext build. Do not edit.\n// node .mext/server.js [--stdio] (= mext start). Environment: PORT · HOST\nimport { startFromBuild } from \"${START_ENTRY}\"\n\nprocess.exitCode = await startFromBuild(new URL(\".\", import.meta.url), { argv: process.argv.slice(2), env: process.env })\n`\n\n/** .mext/handler.js. 계약: createFetchHandler(.mext 폴더 URL) → { fetch(request: Request): Promise<Response> } (동기 반환) */\nexport const HANDLER_JS = `// Generated by mext build. Do not edit.\n// Web fetch handler (Request → Response) for other runtimes and platforms\nimport { createFetchHandler } from \"${START_ENTRY}\"\n\nexport default createFetchHandler(new URL(\".\", import.meta.url))\n`\n\nasync function importRolldown(): Promise<RolldownModule> {\n // 문자열 변수: 타입 검사 · 번들러가 선택 peer 를 정적 의존으로 취급하지 않게\n const specifier = \"rolldown\"\n return (await import(specifier)) as RolldownModule\n}\n\nfunction isModuleNotFound(error: unknown, pkg: string): boolean {\n const e = error as { code?: unknown; message?: unknown } | null\n if (typeof e !== \"object\" || e === null) return false\n if (e.code !== \"ERR_MODULE_NOT_FOUND\" && e.code !== \"MODULE_NOT_FOUND\") return false\n return typeof e.message !== \"string\" || e.message.includes(`'${pkg}'`) || e.message.includes(`\"${pkg}\"`)\n}\n\n/** 도입 프로젝트의 lock 파일로 패키지 관리자 추정 */\nfunction installCommand(cwd: string): string {\n for (let dir = cwd; ; dir = resolve(dir, \"..\")) {\n if (existsSync(join(dir, \"pnpm-lock.yaml\"))) return \"pnpm add -D rolldown\"\n if (existsSync(join(dir, \"yarn.lock\"))) return \"yarn add -D rolldown\"\n if (existsSync(join(dir, \"bun.lock\")) || existsSync(join(dir, \"bun.lockb\"))) return \"bun add -d rolldown\"\n if (existsSync(join(dir, \"package-lock.json\")) || resolve(dir, \"..\") === dir) return \"npm install --save-dev rolldown\"\n }\n}\n\nfunction cleanOutDir(outDir: string): void {\n mkdirSync(outDir, { recursive: true })\n for (const name of readdirSync(outDir)) {\n if (!PRESERVED_ENTRIES.has(name)) rmSync(join(outDir, name), { recursive: true, force: true })\n }\n}\n\n/** \"@scope/pkg/sub\" → \"@scope/pkg\" · \"pkg/sub\" → \"pkg\" */\nfunction packageName(specifier: string): string {\n const parts = specifier.split(\"/\")\n return specifier.startsWith(\"@\") ? parts.slice(0, 2).join(\"/\") : parts[0]!\n}\n\nfunction declaredDependencies(cwd: string): Set<string> {\n let pkg: Record<string, unknown>\n try {\n pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as Record<string, unknown>\n } catch {\n return new Set()\n }\n const names = new Set<string>()\n if (typeof pkg.name === \"string\") names.add(pkg.name)\n for (const field of [\"dependencies\", \"peerDependencies\", \"optionalDependencies\"]) {\n const deps = pkg[field]\n if (typeof deps === \"object\" && deps !== null) for (const name of Object.keys(deps)) names.add(name)\n }\n return names\n}\n\n/** D3: mextVersion · manifestHash · 번들 chunk (파일 이름 · 코드) 의 sha256 앞 16자. 같은 입력 = 같은 buildId */\nfunction buildIdOf(version: string, hash: string, output: readonly RolldownOutputItem[]): string {\n const h = createHash(\"sha256\").update(`${version}\\n${hash}\\n`)\n for (const item of [...output].sort((a, b) => (a.fileName < b.fileName ? -1 : 1))) {\n if (item.type !== \"chunk\") continue\n h.update(`${item.fileName}\\0${item.code ?? \"\"}\\0`)\n }\n return h.digest(\"hex\").slice(0, 16)\n}\n\nfunction toPosix(path: string): string {\n return path.split(sep).join(\"/\")\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\"\nimport { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\"\nimport { isBuiltin } from \"node:module\"\nimport { basename, isAbsolute, join, relative, resolve, sep } from \"node:path\"\nimport { buildCustomerCli, CLI_DIR, customerCliIssues, projectVersion, type CustomerCliBuild } from \"./build-cli.ts\"\nimport { cliBuildIssues } from \"./cli/args.ts\"\nimport { CONFIG_FILE, loadConfig, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from \"./config.ts\"\nimport { MextBuildError } from \"./errors.ts\"\nimport { buildManifest, manifestHash, MANIFEST_SCHEMA_VERSION, type BuildManifest } from \"./manifest.ts\"\nimport { collectPrompts, collectPromptSet, describePrompt } from \"./prompt.ts\"\nimport { collectRegistry } from \"./registry.ts\"\nimport { collectResources, collectResourceSet, describeResource, resourceEntries } from \"./resource.ts\"\nimport { collectRoutes } from \"./route.ts\"\nimport { collectCommands } from \"./scan.ts\"\nimport { mextVersion } from \"./version.ts\"\n\n/** mext build 산출 폴더 (도입 프로젝트 루트 기준) */\nexport const BUILD_DIR = \".mext\"\nexport const BUILD_MANIFEST_FILE = \"manifest.json\"\nexport const INSTRUMENTATION_FILE = \"instrumentation.ts\"\n/** 생성 파일 (server.js · handler.js) 이 import 하는 런타임 엔트리 */\nexport const START_ENTRY = \"@obov/mext/start\"\n/** 로컬 bin (cli.local) 실행 파일 · cli.errors 번들 */\nexport const LOCAL_BIN_FILE = \"bin.js\"\nexport const LOCAL_BIN_ERRORS = \"cli-errors\"\n/** 빌드가 지우지 않는 .mext/ 하위 (mext dev 산출 · 잠금) */\nconst PRESERVED_ENTRIES = new Set([\"dev\"])\n\n/** rolldown 모듈 중 mext build 가 쓰는 부분 */\nexport interface RolldownModule {\n build(options: Record<string, unknown>): Promise<{ output: readonly RolldownOutputItem[] }>\n}\n\nexport interface RolldownOutputItem {\n type: \"chunk\" | \"asset\"\n fileName: string\n /** chunk 코드 */\n code?: string\n isEntry?: boolean\n name?: string\n}\n\nexport interface BuildOptions {\n /** 도입 프로젝트 루트 (mext.config.ts · package.json · instrumentation.ts 위치). 기본 process.cwd() */\n cwd?: string\n /** 산출 폴더. 기본 <cwd>/.mext. 기존 내용은 dev/ 외 삭제 */\n outDir?: string\n /** rolldown 로더 (테스트 주입). 기본 import(\"rolldown\") (선택 peer dependency) */\n importRolldown?: () => Promise<RolldownModule>\n}\n\nexport interface BuildWarning {\n /**\n * UNDECLARED_DEPENDENCY = 외부로 남긴 패키지가 package.json dependencies · peerDependencies · optionalDependencies 에 없음.\n * LOCAL_BIN_UNDECLARED = cli.local 인데 package.json bin[\"<bin>\"] 이 .mext/bin.js 가 아님\n */\n code: \"UNDECLARED_DEPENDENCY\" | \"BUNDLER_WARNING\" | \"LOCAL_BIN_UNDECLARED\"\n message: string\n}\n\nexport interface BuildResult {\n /** 산출 폴더 절대 경로 */\n outDir: string\n manifest: BuildManifest\n /** outDir 기준 생성 파일 (posix, 정렬) */\n files: string[]\n warnings: BuildWarning[]\n /** 고객 CLI (.mext/cli/). config.cli 가 있고 local 이 아닐 때 */\n cli?: CustomerCliBuild\n /** 로컬 bin (.mext/bin.js). config.cli.local 일 때 */\n localBin?: { bin: string; version: string }\n}\n\n/** rolldown 을 찾을 수 없음. message 에 설치 명령 */\nexport class RolldownUnavailableError extends Error {\n readonly installCommand: string\n\n constructor(installCommand: string, cause?: unknown) {\n super(`mext build requires rolldown (optional peer dependency of @obov/mext). Install it: ${installCommand}`, { cause })\n this.name = \"RolldownUnavailableError\"\n this.installCommand = installCommand\n }\n}\n\n/**\n * mext build: commands/ → .mext/ (§10).\n * 1. rolldown 확인 (없으면 RolldownUnavailableError)\n * 2. 검증: 파일 규칙 · import · Registry (ID · 별칭 · 스키마) · CLI 변환 issue 를 모두 모아 MextBuildError 한 번\n * 3. rolldown 다중 엔트리 번들: commands/**\\/*.js (명령어별) · config.js · instrumentation.js · chunks/. 패키지 import 는 외부\n * 4. server.js · handler.js (얇은 생성 파일, 런타임 = @obov/mext/start) · package.json (type module) · manifest.json (마지막)\n */\nexport async function buildProject(options: BuildOptions = {}): Promise<BuildResult> {\n const cwd = resolve(options.cwd ?? process.cwd())\n const outDir = resolve(cwd, options.outDir ?? BUILD_DIR)\n // 빌드 전 outDir 을 비우므로 프로젝트 폴더 자체 · 상위는 거부\n const up = relative(outDir, cwd)\n if (up === \"\" || (!up.startsWith(\"..\") && !isAbsolute(up))) {\n throw new Error(`mext build: outDir must not be the project directory or its parent (${outDir})`)\n }\n const rolldown = await (options.importRolldown ?? importRolldown)().catch((error: unknown) => {\n if (isModuleNotFound(error, \"rolldown\")) throw new RolldownUnavailableError(installCommand(cwd), error)\n throw error\n })\n\n const config = await loadConfig(cwd)\n const commandsDir = resolveCommandsDir(cwd, config)\n const scanned = await collectCommands(commandsDir)\n const { registry, issues: registryIssues } = collectRegistry(scanned)\n const routesDir = resolveRoutesDir(cwd, config)\n const routes = await collectRoutes(routesDir)\n const resourcesDir = resolveResourcesDir(cwd, config)\n const scannedResources = await collectResources(resourcesDir)\n const { resources, issues: resourceIssues } = collectResourceSet(scannedResources.inputs, basename(resourcesDir))\n const promptsDir = resolvePromptsDir(cwd, config)\n const scannedPrompts = await collectPrompts(promptsDir)\n const { prompts, issues: promptIssues } = collectPromptSet(scannedPrompts.inputs, basename(promptsDir))\n const issues = [\n ...scanned.issues,\n ...registryIssues,\n ...cliBuildIssues(registry),\n ...customerCliIssues(config.cli, registry),\n ...scannedResources.issues,\n ...resourceIssues,\n ...scannedPrompts.issues,\n ...promptIssues,\n ...routes.issues,\n ]\n if (issues.length > 0) throw new MextBuildError(issues)\n\n // 엔트리 이름 = 출력 경로 (확장자 제외). 명령어 = commands/ 아래 소스 경로 그대로\n const input: Record<string, string> = {}\n const moduleOf = new Map<string, string>()\n for (const entry of registry.commands.values()) {\n const file = entry.file!\n const name = `commands/${file.replace(/\\.ts$/, \"\")}`\n input[name] = join(commandsDir, file)\n moduleOf.set(entry.id, `${name}.js`)\n }\n // 자원 = resources/ 아래 소스 경로 그대로 (§12.3)\n const resourceList = resourceEntries(resources).sort((a, b) => (a.uri < b.uri ? -1 : a.uri > b.uri ? 1 : 0))\n const resourceModuleOf = new Map<string, string>()\n for (const entry of resourceList) {\n const name = `resources/${entry.file!.replace(/\\.ts$/, \"\")}`\n input[name] = join(resourcesDir, entry.file!)\n resourceModuleOf.set(entry.uri, `${name}.js`)\n }\n // 프롬프트 = prompts/ 아래 소스 경로 그대로 (§12.3)\n const promptList = [...prompts.values()]\n const promptModuleOf = new Map<string, string>()\n for (const entry of promptList) {\n const name = `prompts/${entry.file!.replace(/\\.ts$/, \"\")}`\n input[name] = join(promptsDir, entry.file!)\n promptModuleOf.set(entry.name, `${name}.js`)\n }\n for (const route of routes.routes) input[routeModuleName(route.file)] = join(routesDir, route.file)\n const hasConfig = existsSync(join(cwd, CONFIG_FILE))\n if (hasConfig) input.config = join(cwd, CONFIG_FILE)\n const hasInstrumentation = existsSync(join(cwd, INSTRUMENTATION_FILE))\n if (hasInstrumentation) input.instrumentation = join(cwd, INSTRUMENTATION_FILE)\n const local = config.cli?.local === true ? config.cli : undefined\n if (local?.errors !== undefined) {\n const errorsFile = resolve(cwd, local.errors)\n if (!existsSync(errorsFile)) throw new MextBuildError([{ code: \"INVALID_CONFIG\", message: `cli.errors file not found: ${local.errors}` }])\n input[LOCAL_BIN_ERRORS] = errorsFile\n }\n\n cleanOutDir(outDir)\n\n const warnings: BuildWarning[] = []\n /** 외부 패키지 이름 → 처음 import 한 파일 */\n const externals = new Map<string, string | undefined>()\n let output: readonly RolldownOutputItem[]\n try {\n ;({ output } = await rolldown.build({\n cwd,\n input,\n platform: \"node\",\n // 상대 · 절대 경로 · # (package.json imports) = 번들. 그 외 bare import = 외부 (도입 프로젝트 node_modules 에서 해석)\n external: (id: string, importer: string | undefined): boolean => {\n if (id.startsWith(\".\") || id.startsWith(\"#\") || id.startsWith(\"\\0\") || isAbsolute(id)) return false\n if (id.startsWith(\"node:\") || isBuiltin(id)) return true\n const pkg = packageName(id)\n if (!externals.has(pkg) && importer !== undefined && !importer.startsWith(\"\\0\")) externals.set(pkg, importer)\n return true\n },\n transform: { target: \"node22\" },\n logLevel: \"warn\",\n onLog: (_level: string, log: { message: string }) => warnings.push({ code: \"BUNDLER_WARNING\", message: log.message }),\n output: {\n dir: outDir,\n format: \"esm\",\n entryFileNames: \"[name].js\",\n chunkFileNames: \"chunks/[name]-[hash].js\",\n sourcemap: true,\n },\n }))\n } catch (error) {\n throw new MextBuildError([{ code: \"BUNDLE_FAILED\", message: error instanceof Error ? error.message : String(error) }])\n }\n\n const declared = declaredDependencies(cwd)\n for (const [pkg, importer] of externals) {\n if (declared.has(pkg)) continue\n const from = importer === undefined ? \"\" : ` (imported by ${toPosix(relative(cwd, importer))})`\n warnings.push({\n code: \"UNDECLARED_DEPENDENCY\",\n message: `\"${pkg}\" is not in package.json dependencies${from}. It stays external and must be installed where .mext/ runs`,\n })\n }\n\n const emitted = new Set(output.map((o) => o.fileName))\n for (const name of Object.keys(input)) {\n if (!emitted.has(`${name}.js`)) throw new Error(`mext build: rolldown did not emit ${name}.js`)\n }\n\n const base = buildManifest(registry)\n const hash = manifestHash(base.commands, {\n resources: resourceList.map((r) => r.uri),\n prompts: promptList.map((p) => ({ name: p.name, argsSchema: p.argsSchema })),\n })\n const version = mextVersion()\n const manifest: BuildManifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n mextVersion: version,\n buildId: buildIdOf(version, hash, output),\n manifestHash: hash,\n tools: config.tools ?? \"execute\",\n ...(hasConfig ? { config: \"config.js\" } : {}),\n ...(hasInstrumentation ? { instrumentation: \"instrumentation.js\" } : {}),\n ...(base.description !== undefined ? { description: base.description } : {}),\n namespaces: base.namespaces,\n commands: base.commands.map((c) => ({ ...c, module: moduleOf.get(c.id)! })),\n ...(resourceList.length > 0\n ? { resources: resourceList.map((r) => ({ ...describeResource(r), module: resourceModuleOf.get(r.uri)! })) }\n : {}),\n ...(promptList.length > 0\n ? { prompts: promptList.map((p) => ({ ...describePrompt(p), module: promptModuleOf.get(p.name)! })) }\n : {}),\n ...(routes.routes.length > 0\n ? {\n routes: routes.routes\n .map((r) => ({ path: r.path, file: r.file, methods: r.methods, module: `${routeModuleName(r.file)}.js` }))\n .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),\n }\n : {}),\n }\n\n const generated: Record<string, string> = {\n \"package.json\": `${JSON.stringify({ type: \"module\" }, null, 2)}\\n`,\n \"server.js\": SERVER_JS,\n \"handler.js\": HANDLER_JS,\n }\n const localBin = local ? { bin: local.bin, version: local.version ?? projectVersion(cwd) ?? \"0.0.0\" } : undefined\n if (localBin) {\n generated[LOCAL_BIN_FILE] = localBinJs({ ...localBin, ...(local?.errors !== undefined ? { errors: `${LOCAL_BIN_ERRORS}.js` } : {}) })\n const declaredBin = packageBin(cwd, localBin.bin)\n const expected = `${toPosix(relative(cwd, outDir))}/${LOCAL_BIN_FILE}`\n if (declaredBin === undefined || declaredBin.replace(/^\\.\\//, \"\") !== expected) {\n warnings.push({\n code: \"LOCAL_BIN_UNDECLARED\",\n message: `cli.local: add \"bin\": { \"${localBin.bin}\": \"${expected}\" } to package.json (and include ${toPosix(relative(cwd, outDir))} in \"files\")`,\n })\n }\n }\n for (const [file, content] of Object.entries(generated)) writeFileSync(join(outDir, file), content)\n if (localBin) chmodSync(join(outDir, LOCAL_BIN_FILE), 0o755)\n\n // 고객 CLI (.mext/cli/, §5): manifest · buildId 확정 후, manifest.json 쓰기 전. 로컬 bin 이면 만들지 않는다\n const cli = config.cli && !local ? await buildCustomerCli({ rolldown, cwd, outDir, cli: config.cli, manifest }) : undefined\n\n // manifest.json 은 마지막: 중간 실패한 빌드는 manifest 가 없어 mext start 가 \"mext build 먼저\" 로 거부\n writeFileSync(join(outDir, BUILD_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\\n`)\n\n const files = [\n ...emitted,\n ...Object.keys(generated),\n BUILD_MANIFEST_FILE,\n ...(cli?.files.map((f) => `${CLI_DIR}/${f}`) ?? []),\n ].sort()\n return { outDir, manifest, files, warnings, ...(cli ? { cli } : {}), ...(localBin ? { localBin } : {}) }\n}\n\n/**\n * .mext/bin.js (로컬 bin, cli.local). 계약: mainLocalBin(.mext 폴더 URL, { bin, version, errors? }).\n * 도입 프로젝트 package.json bin 이 이 파일을 가리킨다 (npm 이 symlink 해도 import.meta.url = 실제 경로)\n */\nexport function localBinJs(options: { bin: string; version: string; errors?: string }): string {\n return `#!/usr/bin/env node\n// Generated by mext build. Do not edit.\n// Local bin (cli.local): ${options.bin} help · ${options.bin} <namespace> <command> · ${options.bin} mcp serve\nimport { mainLocalBin } from \"${START_ENTRY}\"\n\nawait mainLocalBin(new URL(\".\", import.meta.url), ${JSON.stringify(options)})\n`\n}\n\n/** package.json bin[name] (문자열 bin = 패키지 이름이 name 일 때) */\nfunction packageBin(cwd: string, name: string): string | undefined {\n try {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as { name?: unknown; bin?: unknown }\n if (typeof pkg.bin === \"string\") return pkg.name === name ? pkg.bin : undefined\n if (typeof pkg.bin === \"object\" && pkg.bin !== null) {\n const v = (pkg.bin as Record<string, unknown>)[name]\n return typeof v === \"string\" ? v : undefined\n }\n } catch {\n // package.json 없음 · 형식 오류 = 미선언\n }\n return undefined\n}\n\n/**\n * .mext/server.js. 계약: startFromBuild(.mext 폴더 URL, { argv, env }) → exit code.\n * argv = server.js 뒤 인자 (--stdio), env = PORT · HOST\n */\nexport const SERVER_JS = `// Generated by mext build. Do not edit.\n// node .mext/server.js [--stdio] (= mext start). Environment: PORT · HOST\nimport { startFromBuild } from \"${START_ENTRY}\"\n\nprocess.exitCode = await startFromBuild(new URL(\".\", import.meta.url), { argv: process.argv.slice(2), env: process.env })\n`\n\n/** .mext/handler.js. 계약: createFetchHandler(.mext 폴더 URL) → { fetch(request: Request): Promise<Response> } (동기 반환) */\nexport const HANDLER_JS = `// Generated by mext build. Do not edit.\n// Web fetch handler (Request → Response) for other runtimes and platforms\nimport { createFetchHandler } from \"${START_ENTRY}\"\n\nexport default createFetchHandler(new URL(\".\", import.meta.url))\n`\n\nasync function importRolldown(): Promise<RolldownModule> {\n // 문자열 변수: 타입 검사 · 번들러가 선택 peer 를 정적 의존으로 취급하지 않게\n const specifier = \"rolldown\"\n return (await import(specifier)) as RolldownModule\n}\n\nfunction isModuleNotFound(error: unknown, pkg: string): boolean {\n const e = error as { code?: unknown; message?: unknown } | null\n if (typeof e !== \"object\" || e === null) return false\n if (e.code !== \"ERR_MODULE_NOT_FOUND\" && e.code !== \"MODULE_NOT_FOUND\") return false\n return typeof e.message !== \"string\" || e.message.includes(`'${pkg}'`) || e.message.includes(`\"${pkg}\"`)\n}\n\n/** 도입 프로젝트의 lock 파일로 패키지 관리자 추정 */\nfunction installCommand(cwd: string): string {\n for (let dir = cwd; ; dir = resolve(dir, \"..\")) {\n if (existsSync(join(dir, \"pnpm-lock.yaml\"))) return \"pnpm add -D rolldown\"\n if (existsSync(join(dir, \"yarn.lock\"))) return \"yarn add -D rolldown\"\n if (existsSync(join(dir, \"bun.lock\")) || existsSync(join(dir, \"bun.lockb\"))) return \"bun add -d rolldown\"\n if (existsSync(join(dir, \"package-lock.json\")) || resolve(dir, \"..\") === dir) return \"npm install --save-dev rolldown\"\n }\n}\n\nfunction cleanOutDir(outDir: string): void {\n mkdirSync(outDir, { recursive: true })\n for (const name of readdirSync(outDir)) {\n if (!PRESERVED_ENTRIES.has(name)) rmSync(join(outDir, name), { recursive: true, force: true })\n }\n}\n\n/**\n * route 엔트리 이름 = routes/ 아래 소스 경로, [name] → _name_ (rolldown 이 [ ] 를 바꾸므로 직접 정한다).\n * `_` 접두 파일 · 폴더는 route 가 아니라 충돌 없음. routes/items/[id].ts → routes/items/_id_\n */\nfunction routeModuleName(file: string): string {\n return `routes/${file.replace(/\\.ts$/, \"\").replace(/\\[([^\\]/]+)\\]/g, \"_$1_\")}`\n}\n\n/** \"@scope/pkg/sub\" → \"@scope/pkg\" · \"pkg/sub\" → \"pkg\" */\nfunction packageName(specifier: string): string {\n const parts = specifier.split(\"/\")\n return specifier.startsWith(\"@\") ? parts.slice(0, 2).join(\"/\") : parts[0]!\n}\n\nfunction declaredDependencies(cwd: string): Set<string> {\n let pkg: Record<string, unknown>\n try {\n pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as Record<string, unknown>\n } catch {\n return new Set()\n }\n const names = new Set<string>()\n if (typeof pkg.name === \"string\") names.add(pkg.name)\n for (const field of [\"dependencies\", \"peerDependencies\", \"optionalDependencies\"]) {\n const deps = pkg[field]\n if (typeof deps === \"object\" && deps !== null) for (const name of Object.keys(deps)) names.add(name)\n }\n return names\n}\n\n/** D3: mextVersion · manifestHash · 번들 chunk (파일 이름 · 코드) 의 sha256 앞 16자. 같은 입력 = 같은 buildId */\nfunction buildIdOf(version: string, hash: string, output: readonly RolldownOutputItem[]): string {\n const h = createHash(\"sha256\").update(`${version}\\n${hash}\\n`)\n for (const item of [...output].sort((a, b) => (a.fileName < b.fileName ? -1 : 1))) {\n if (item.type !== \"chunk\") continue\n h.update(`${item.fileName}\\0${item.code ?? \"\"}\\0`)\n }\n return h.digest(\"hex\").slice(0, 16)\n}\n\nfunction toPosix(path: string): string {\n return path.split(sep).join(\"/\")\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CliIo, LineReader } from "./io.ts";
|
|
2
|
+
/**
|
|
3
|
+
* ctx.ask kind url 의 CLI 처리 (spec §12.4). 로컬 실행 · 원격 (서버의 elicitation/create mode url) 공용.
|
|
4
|
+
* TTY = message · 전체 URL (stderr) → [Y/n] → 브라우저 열기 (login 과 같은 판정) → Enter 대기 → true. n = false.
|
|
5
|
+
* TTY 없음 · --json = INPUT_UNAVAILABLE (details.url). --yes 는 적용하지 않는다.
|
|
6
|
+
* 고객 CLI 번들에 들어간다 (Zod · 서버 코드 import 금지).
|
|
7
|
+
*/
|
|
8
|
+
export interface UrlAsk {
|
|
9
|
+
command: string;
|
|
10
|
+
message: string;
|
|
11
|
+
url: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function askUrl(io: CliIo, lines: LineReader, request: UrlAsk, options: {
|
|
14
|
+
json: boolean;
|
|
15
|
+
signal: AbortSignal;
|
|
16
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MextError } from "../errors.js";
|
|
2
|
+
import { browserDecision, systemBrowserOpener } from "../remote/browser.js";
|
|
3
|
+
import { CliInterrupted } from "./output.js";
|
|
4
|
+
export async function askUrl(io, lines, request, options) {
|
|
5
|
+
const { command, message, url } = request;
|
|
6
|
+
if (!io.isTTY || options.json) {
|
|
7
|
+
const reason = options.json ? "--json output cannot prompt" : "stdin is not a terminal";
|
|
8
|
+
throw new MextError("INPUT_UNAVAILABLE", `${command} asked "${message}" at ${url}, but ${reason}. Open the URL, then run the command again.`, { command, url });
|
|
9
|
+
}
|
|
10
|
+
const question = async (prompt) => {
|
|
11
|
+
const answer = await lines.question(prompt, options.signal);
|
|
12
|
+
if (options.signal.aborted)
|
|
13
|
+
throw new CliInterrupted();
|
|
14
|
+
return (answer ?? "").trim();
|
|
15
|
+
};
|
|
16
|
+
io.stderr.write(`${message}\n ${url}\n`);
|
|
17
|
+
if (/^n(o)?$/i.test(await question("Open this URL? [Y/n] ")))
|
|
18
|
+
return false;
|
|
19
|
+
const decision = browserDecision(io.env);
|
|
20
|
+
if (decision.open)
|
|
21
|
+
systemBrowserOpener(io.env)(url);
|
|
22
|
+
else
|
|
23
|
+
io.stderr.write("Open the URL above in a browser.\n");
|
|
24
|
+
await question("Press Enter when done. ");
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=ask-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-url.js","sourceRoot":"","sources":["../../src/cli/ask-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAc5C,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,EAAS,EACT,KAAiB,EACjB,OAAe,EACf,OAA+C;IAE/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;IACzC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,yBAAyB,CAAA;QACvF,MAAM,IAAI,SAAS,CACjB,mBAAmB,EACnB,GAAG,OAAO,WAAW,OAAO,QAAQ,GAAG,SAAS,MAAM,6CAA6C,EACnG,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAmB,EAAE;QACzD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QAC3D,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,cAAc,EAAE,CAAA;QACtD,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9B,CAAC,CAAA;IACD,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,OAAO,GAAG,IAAI,CAAC,CAAA;IACzC,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,uBAAuB,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1E,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,QAAQ,CAAC,IAAI;QAAE,mBAAmB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;;QAC9C,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;IAC1D,MAAM,QAAQ,CAAC,yBAAyB,CAAC,CAAA;IACzC,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { MextError } from \"../errors.ts\"\nimport { browserDecision, systemBrowserOpener } from \"../remote/browser.ts\"\nimport type { CliIo, LineReader } from \"./io.ts\"\nimport { CliInterrupted } from \"./output.ts\"\n\n/**\n * ctx.ask kind url 의 CLI 처리 (spec §12.4). 로컬 실행 · 원격 (서버의 elicitation/create mode url) 공용.\n * TTY = message · 전체 URL (stderr) → [Y/n] → 브라우저 열기 (login 과 같은 판정) → Enter 대기 → true. n = false.\n * TTY 없음 · --json = INPUT_UNAVAILABLE (details.url). --yes 는 적용하지 않는다.\n * 고객 CLI 번들에 들어간다 (Zod · 서버 코드 import 금지).\n */\nexport interface UrlAsk {\n command: string\n message: string\n url: string\n}\n\nexport async function askUrl(\n io: CliIo,\n lines: LineReader,\n request: UrlAsk,\n options: { json: boolean; signal: AbortSignal },\n): Promise<boolean> {\n const { command, message, url } = request\n if (!io.isTTY || options.json) {\n const reason = options.json ? \"--json output cannot prompt\" : \"stdin is not a terminal\"\n throw new MextError(\n \"INPUT_UNAVAILABLE\",\n `${command} asked \"${message}\" at ${url}, but ${reason}. Open the URL, then run the command again.`,\n { command, url },\n )\n }\n const question = async (prompt: string): Promise<string> => {\n const answer = await lines.question(prompt, options.signal)\n if (options.signal.aborted) throw new CliInterrupted()\n return (answer ?? \"\").trim()\n }\n io.stderr.write(`${message}\\n ${url}\\n`)\n if (/^n(o)?$/i.test(await question(\"Open this URL? [Y/n] \"))) return false\n const decision = browserDecision(io.env)\n if (decision.open) systemBrowserOpener(io.env)(url)\n else io.stderr.write(\"Open the URL above in a browser.\\n\")\n await question(\"Press Enter when done. \")\n return true\n}\n"]}
|
package/dist/cli/build.js
CHANGED
|
@@ -42,6 +42,9 @@ export function formatBuildSummary(result, cwd) {
|
|
|
42
42
|
...manifest.commands.map((c) => [c.id, safetyOf(c), c.scopes.join(", ") || "-"]),
|
|
43
43
|
]).map((l) => ` ${l}`),
|
|
44
44
|
"",
|
|
45
|
+
...(manifest.routes?.length
|
|
46
|
+
? [...table([["Route", "Methods"], ...manifest.routes.map((r) => [r.path, r.methods.join(" · ")])]).map((l) => ` ${l}`), ""]
|
|
47
|
+
: []),
|
|
45
48
|
`Start: node ${dir}/server.js [--stdio]`,
|
|
46
49
|
];
|
|
47
50
|
const cli = result.cli;
|
|
@@ -72,12 +75,15 @@ export function buildHelp() {
|
|
|
72
75
|
"",
|
|
73
76
|
"Output (.mext/):",
|
|
74
77
|
...table([
|
|
75
|
-
["manifest.json", "schemaVersion · mextVersion · buildId · manifestHash · namespaces · commands (+ module)"],
|
|
78
|
+
["manifest.json", "schemaVersion · mextVersion · buildId · manifestHash · namespaces · commands · resources · prompts · routes (+ module)"],
|
|
76
79
|
["server.js", "node .mext/server.js [--stdio]. PORT · HOST environment variables"],
|
|
77
80
|
["handler.js", "export default { fetch(request) } (Web Request → Response)"],
|
|
78
81
|
["config.js", "mext.config.ts bundle (when present)"],
|
|
79
82
|
["instrumentation.js", "instrumentation.ts bundle (when present)"],
|
|
80
83
|
["commands/**/*.js", "one module per command"],
|
|
84
|
+
["resources/**/*.js", "one module per MCP resource (resources/, when present)"],
|
|
85
|
+
["prompts/**/*.js", "one module per MCP prompt (prompts/, when present)"],
|
|
86
|
+
["routes/**/*.js", "one module per HTTP route (routes/, when present)"],
|
|
81
87
|
["chunks/", "shared code"],
|
|
82
88
|
["cli/", "customer CLI npm package (when mext.config.ts has cli): package.json · bin.js · README.md"],
|
|
83
89
|
["bin.js", "local bin (cli.local: true, instead of cli/). package.json bin points here"],
|
package/dist/cli/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { relative } from \"node:path\"\nimport { buildProject, type BuildOptions, type BuildResult } from \"../build.ts\"\nimport type { BuildManifestCommand } from \"../manifest.ts\"\nimport { table } from \"./help.ts\"\nimport type { CliIo } from \"./io.ts\"\nimport { EXIT, exitCodeOf, formatError } from \"./output.ts\"\n\nexport const BUILD_PROG = \"mext build\"\n\n/**\n * mext build: commands/ → .mext/. 경고 · 오류 = stderr, 성공 요약 · 명령어 표 = stdout.\n * 검증 오류는 MextBuildError 하나에 모아 한 번에 출력, exit 1\n */\nexport async function runBuild(argv: readonly string[], io: CliIo, options: Omit<BuildOptions, \"cwd\"> = {}): Promise<number> {\n for (const tok of argv) {\n if (tok === \"--help\" || tok === \"-h\") {\n io.stdout.write(buildHelp())\n return EXIT.ok\n }\n io.stderr.write(`error: unexpected argument \"${tok}\"\\nRun \"${BUILD_PROG} --help\" for usage.\\n`)\n return EXIT.usage\n }\n let result: BuildResult\n try {\n result = await buildProject({ ...options, cwd: io.cwd })\n } catch (error) {\n io.stderr.write(formatError(error, BUILD_PROG))\n return exitCodeOf(error)\n }\n for (const w of result.warnings) io.stderr.write(`warning: ${w.message}\\n`)\n io.stdout.write(formatBuildSummary(result, io.cwd))\n return EXIT.ok\n}\n\n/** 성공 요약 + 명령어 표 (ID · 안전성 · scopes), next build 의 route 표와 같은 역할 */\nexport function formatBuildSummary(result: BuildResult, cwd: string): string {\n const { manifest } = result\n const dir = relative(cwd, result.outDir) || \".\"\n const n = manifest.commands.length\n const lines = [\n `Built ${dir}/ (${n} command${n === 1 ? \"\" : \"s\"}, buildId ${manifest.buildId})`,\n \"\",\n ...table([\n [\"Command\", \"Safety\", \"Scopes\"],\n ...manifest.commands.map((c) => [c.id, safetyOf(c), c.scopes.join(\", \") || \"-\"]),\n ]).map((l) => ` ${l}`),\n \"\",\n ...(manifest.routes?.length\n ? [...table([[\"Route\", \"Methods\"], ...manifest.routes.map((r) => [r.path, r.methods.join(\" · \")])]).map((l) => ` ${l}`), \"\"]\n : []),\n `Start: node ${dir}/server.js [--stdio]`,\n ]\n const cli = result.cli\n if (cli) {\n const kb = (cli.size / 1024).toFixed(1)\n lines.push(\n `Customer CLI: ${dir}/cli/ (${cli.packageName}@${cli.version}, bin ${cli.bin}, ${cli.form}, ${kb} KB). Publish: npm publish ${dir}/cli`,\n )\n }\n const local = result.localBin\n if (local) lines.push(`Local bin: ${dir}/bin.js (bin ${local.bin}@${local.version}). Run: ${local.bin} help (after npm link · npm install -g)`)\n return `${lines.join(\"\\n\")}\\n`\n}\n\n/** readOnly · destructive · confirm. 아무것도 없으면 write */\nfunction safetyOf(c: BuildManifestCommand): string {\n const flags = [\n ...(c.readOnly ? [\"readOnly\"] : []),\n ...(c.destructive ? [\"destructive\"] : []),\n ...(c.requiresConfirmation ? [\"confirm\"] : []),\n ]\n return flags.length === 0 ? \"write\" : flags.join(\" · \")\n}\n\nexport function buildHelp(): string {\n const lines = [\n \"Build commands/ into .mext/ for production (mext start · node .mext/server.js).\",\n \"\",\n \"Usage:\",\n ` ${BUILD_PROG}`,\n \"\",\n \"Output (.mext/):\",\n ...table([\n [\"manifest.json\", \"schemaVersion · mextVersion · buildId · manifestHash · namespaces · commands · resources · prompts · routes (+ module)\"],\n [\"server.js\", \"node .mext/server.js [--stdio]. PORT · HOST environment variables\"],\n [\"handler.js\", \"export default { fetch(request) } (Web Request → Response)\"],\n [\"config.js\", \"mext.config.ts bundle (when present)\"],\n [\"instrumentation.js\", \"instrumentation.ts bundle (when present)\"],\n [\"commands/**/*.js\", \"one module per command\"],\n [\"resources/**/*.js\", \"one module per MCP resource (resources/, when present)\"],\n [\"prompts/**/*.js\", \"one module per MCP prompt (prompts/, when present)\"],\n [\"routes/**/*.js\", \"one module per HTTP route (routes/, when present)\"],\n [\"chunks/\", \"shared code\"],\n [\"cli/\", \"customer CLI npm package (when mext.config.ts has cli): package.json · bin.js · README.md\"],\n [\"bin.js\", \"local bin (cli.local: true, instead of cli/). package.json bin points here\"],\n [\"cli-errors.js\", \"cli.errors bundle for the local bin\"],\n ]).map((l) => ` ${l}`),\n \"\",\n \"Requires rolldown (npm install --save-dev rolldown). Package imports stay external.\",\n \"All validation errors are reported at once (exit 1).\",\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n"]}
|
package/dist/cli/dev-server.d.ts
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
export type DevChildMessage = {
|
|
3
3
|
type: "config";
|
|
4
4
|
commandsDir: string;
|
|
5
|
+
routesDir: string;
|
|
6
|
+
/** 감시 대상 (§10). resources/ · prompts/ */
|
|
7
|
+
resourcesDir: string;
|
|
8
|
+
promptsDir: string;
|
|
5
9
|
server: {
|
|
6
10
|
host?: string;
|
|
7
11
|
port?: number;
|
|
@@ -14,7 +18,9 @@ export type DevChildMessage = {
|
|
|
14
18
|
type: "error";
|
|
15
19
|
message: string;
|
|
16
20
|
};
|
|
17
|
-
/** 부모 →
|
|
21
|
+
/** 부모 → 자식. retire = 새 자식으로 교체됨 (listen 스트림을 닫고 진행 중 요청은 끝까지), shutdown = 종료 */
|
|
18
22
|
export type DevParentMessage = {
|
|
19
23
|
type: "shutdown";
|
|
24
|
+
} | {
|
|
25
|
+
type: "retire";
|
|
20
26
|
};
|
package/dist/cli/dev-server.js
CHANGED
|
@@ -4,9 +4,12 @@
|
|
|
4
4
|
* 요청은 감독 프로세스 (부모) 가 받아 이 포트로 중계한다. 부모 IPC 가 끊기면 종료.
|
|
5
5
|
*/
|
|
6
6
|
import { createServer } from "node:http";
|
|
7
|
-
import { loadConfig, mcpDeclarations, resolveCommandsDir } from "../config.js";
|
|
7
|
+
import { loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from "../config.js";
|
|
8
8
|
import { loadProjectInstrumentation } from "../instrumentation.js";
|
|
9
9
|
import { createMcpHttpHandler } from "../mcp/http.js";
|
|
10
|
+
import { loadPromptSet, withPrompts } from "../prompt.js";
|
|
11
|
+
import { loadResourceSet, withResources } from "../resource.js";
|
|
12
|
+
import { loadRoutes } from "../route.js";
|
|
10
13
|
import { loadRegistry } from "../scan.js";
|
|
11
14
|
const send = (message) => new Promise((resolve) => {
|
|
12
15
|
if (!process.connected)
|
|
@@ -22,15 +25,22 @@ async function main() {
|
|
|
22
25
|
const instrumentation = await loadProjectInstrumentation(cwd);
|
|
23
26
|
const config = await loadConfig(cwd);
|
|
24
27
|
const commandsDir = resolveCommandsDir(cwd, config);
|
|
28
|
+
const routesDir = resolveRoutesDir(cwd, config);
|
|
29
|
+
const resourcesDir = resolveResourcesDir(cwd, config);
|
|
30
|
+
const promptsDir = resolvePromptsDir(cwd, config);
|
|
25
31
|
await send({
|
|
26
32
|
type: "config",
|
|
27
33
|
commandsDir,
|
|
34
|
+
routesDir,
|
|
35
|
+
resourcesDir,
|
|
36
|
+
promptsDir,
|
|
28
37
|
server: {
|
|
29
38
|
...(config.server?.host !== undefined ? { host: config.server.host } : {}),
|
|
30
39
|
...(config.server?.port !== undefined ? { port: config.server.port } : {}),
|
|
31
40
|
},
|
|
32
41
|
});
|
|
33
|
-
const registry = await loadRegistry(commandsDir);
|
|
42
|
+
const registry = withPrompts(withResources(await loadRegistry(commandsDir), await loadResourceSet(resourcesDir)), await loadPromptSet(promptsDir));
|
|
43
|
+
const routes = await loadRoutes(routesDir);
|
|
34
44
|
const listener = createMcpHttpHandler({
|
|
35
45
|
registry,
|
|
36
46
|
instrumentation,
|
|
@@ -38,6 +48,7 @@ async function main() {
|
|
|
38
48
|
...(config.auth ? { auth: config.auth } : {}),
|
|
39
49
|
...(config.tools ? { tools: config.tools } : {}),
|
|
40
50
|
...(config.oauth ? { oauth: config.oauth } : {}),
|
|
51
|
+
...(routes.length > 0 ? { routes } : {}),
|
|
41
52
|
...mcpDeclarations(config),
|
|
42
53
|
server: config.server?.allowedOrigins ? { allowedOrigins: config.server.allowedOrigins } : {},
|
|
43
54
|
onerror: (error) => process.stderr.write(`mcp: ${error.message}\n`),
|
|
@@ -51,6 +62,8 @@ async function main() {
|
|
|
51
62
|
});
|
|
52
63
|
});
|
|
53
64
|
process.on("message", (message) => {
|
|
65
|
+
if (message?.type === "retire")
|
|
66
|
+
void listener.closeSubscriptions();
|
|
54
67
|
if (message?.type !== "shutdown")
|
|
55
68
|
return;
|
|
56
69
|
void listener.close().finally(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../src/cli/dev-server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../src/cli/dev-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mext dev 의 서버 자식 프로세스 엔트리 (cli/dev.ts 가 fork). 직접 실행하지 않는다.\n * cwd 의 mext.config.ts · commands/ 를 로드해 127.0.0.1 임의 포트에서 MCP HTTP 처리기를 띄우고 IPC 로 보고한다.\n * 요청은 감독 프로세스 (부모) 가 받아 이 포트로 중계한다. 부모 IPC 가 끊기면 종료.\n */\nimport { createServer } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from \"../config.ts\"\nimport { loadProjectInstrumentation } from \"../instrumentation.ts\"\nimport { createMcpHttpHandler } from \"../mcp/http.ts\"\nimport { loadPromptSet, withPrompts } from \"../prompt.ts\"\nimport { loadResourceSet, withResources } from \"../resource.ts\"\nimport { loadRoutes } from \"../route.ts\"\nimport { loadRegistry } from \"../scan.ts\"\n\n/** 자식 → 부모 */\nexport type DevChildMessage =\n | {\n type: \"config\"\n commandsDir: string\n routesDir: string\n /** 감시 대상 (§10). resources/ · prompts/ */\n resourcesDir: string\n promptsDir: string\n server: { host?: string; port?: number }\n }\n | { type: \"ready\"; port: number; commands: number }\n | { type: \"error\"; message: string }\n\n/** 부모 → 자식. retire = 새 자식으로 교체됨 (listen 스트림을 닫고 진행 중 요청은 끝까지), shutdown = 종료 */\nexport type DevParentMessage = { type: \"shutdown\" } | { type: \"retire\" }\n\nconst send = (message: DevChildMessage): Promise<void> =>\n new Promise((resolve) => {\n if (!process.connected) return resolve()\n process.send!(message, undefined, {}, () => resolve())\n })\n\n// 터미널 Ctrl-C 는 프로세스 그룹 전체에 간다. 종료는 부모가 정한다 (shutdown · IPC 끊김)\nprocess.on(\"SIGINT\", () => {})\nprocess.on(\"disconnect\", () => process.exit(0))\n\nasync function main(): Promise<void> {\n const cwd = process.cwd()\n // register() = 명령어 · config import 전\n const instrumentation = await loadProjectInstrumentation(cwd)\n const config = await loadConfig(cwd)\n const commandsDir = resolveCommandsDir(cwd, config)\n const routesDir = resolveRoutesDir(cwd, config)\n const resourcesDir = resolveResourcesDir(cwd, config)\n const promptsDir = resolvePromptsDir(cwd, config)\n await send({\n type: \"config\",\n commandsDir,\n routesDir,\n resourcesDir,\n promptsDir,\n server: {\n ...(config.server?.host !== undefined ? { host: config.server.host } : {}),\n ...(config.server?.port !== undefined ? { port: config.server.port } : {}),\n },\n })\n const registry = withPrompts(\n withResources(await loadRegistry(commandsDir), await loadResourceSet(resourcesDir)),\n await loadPromptSet(promptsDir),\n )\n const routes = await loadRoutes(routesDir)\n const listener = createMcpHttpHandler({\n registry,\n instrumentation,\n ...(config.app ? { app: config.app } : {}),\n ...(config.auth ? { auth: config.auth } : {}),\n ...(config.tools ? { tools: config.tools } : {}),\n ...(config.oauth ? { oauth: config.oauth } : {}),\n ...(routes.length > 0 ? { routes } : {}),\n ...mcpDeclarations(config),\n server: config.server?.allowedOrigins ? { allowedOrigins: config.server.allowedOrigins } : {},\n onerror: (error) => process.stderr.write(`mcp: ${error.message}\\n`),\n })\n const server = createServer(listener)\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(0, \"127.0.0.1\", () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n process.on(\"message\", (message: DevParentMessage) => {\n if (message?.type === \"retire\") void listener.closeSubscriptions()\n if (message?.type !== \"shutdown\") return\n void listener.close().finally(() => {\n server.closeAllConnections()\n server.close(() => process.exit(0))\n })\n })\n await send({ type: \"ready\", port: (server.address() as AddressInfo).port, commands: registry.commands.size })\n}\n\nmain().catch(async (error: unknown) => {\n await send({ type: \"error\", message: describeLoadError(error) })\n process.exit(1)\n})\n\n/** SyntaxError 는 stack 첫 줄들에 파일 위치가 있다 (ESM 파싱 오류). 그 외는 message (MextBuildError = issue 목록) */\nfunction describeLoadError(error: unknown): string {\n if (error instanceof SyntaxError && error.stack) {\n const at = error.stack.indexOf(\"\\n at \")\n return (at < 0 ? error.stack : error.stack.slice(0, at)).trim()\n }\n return error instanceof Error ? error.message : String(error)\n}\n"]}
|