@obov/mext 0.3.0 → 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.
Files changed (115) hide show
  1. package/dist/build.js +67 -4
  2. package/dist/build.js.map +1 -1
  3. package/dist/cli/ask-url.d.ts +16 -0
  4. package/dist/cli/ask-url.js +27 -0
  5. package/dist/cli/ask-url.js.map +1 -0
  6. package/dist/cli/build.js +7 -1
  7. package/dist/cli/build.js.map +1 -1
  8. package/dist/cli/dev-server.d.ts +7 -1
  9. package/dist/cli/dev-server.js +15 -2
  10. package/dist/cli/dev-server.js.map +1 -1
  11. package/dist/cli/dev.js +27 -7
  12. package/dist/cli/dev.js.map +1 -1
  13. package/dist/cli/login.d.ts +5 -0
  14. package/dist/cli/login.js +11 -7
  15. package/dist/cli/login.js.map +1 -1
  16. package/dist/cli/logout.js +4 -6
  17. package/dist/cli/logout.js.map +1 -1
  18. package/dist/cli/output.d.ts +1 -1
  19. package/dist/cli/output.js +1 -2
  20. package/dist/cli/output.js.map +1 -1
  21. package/dist/cli/run.js +21 -5
  22. package/dist/cli/run.js.map +1 -1
  23. package/dist/client/cache.d.ts +14 -4
  24. package/dist/client/cache.js +10 -3
  25. package/dist/client/cache.js.map +1 -1
  26. package/dist/client/main.js +11 -10
  27. package/dist/client/main.js.map +1 -1
  28. package/dist/client/manifest.d.ts +13 -1
  29. package/dist/client/manifest.js +43 -0
  30. package/dist/client/manifest.js.map +1 -1
  31. package/dist/client/runner.d.ts +3 -1
  32. package/dist/client/runner.js +80 -19
  33. package/dist/client/runner.js.map +1 -1
  34. package/dist/client/task.d.ts +47 -0
  35. package/dist/client/task.js +126 -0
  36. package/dist/client/task.js.map +1 -0
  37. package/dist/command.d.ts +30 -3
  38. package/dist/command.js +16 -0
  39. package/dist/command.js.map +1 -1
  40. package/dist/config.d.ts +40 -6
  41. package/dist/config.js +57 -8
  42. package/dist/config.js.map +1 -1
  43. package/dist/errors.d.ts +3 -1
  44. package/dist/errors.js.map +1 -1
  45. package/dist/index.d.ts +17 -5
  46. package/dist/index.js +9 -2
  47. package/dist/index.js.map +1 -1
  48. package/dist/instrumentation.d.ts +14 -2
  49. package/dist/instrumentation.js +12 -4
  50. package/dist/instrumentation.js.map +1 -1
  51. package/dist/invoke.d.ts +38 -0
  52. package/dist/invoke.js +72 -3
  53. package/dist/invoke.js.map +1 -1
  54. package/dist/local-bin.js +17 -9
  55. package/dist/local-bin.js.map +1 -1
  56. package/dist/manifest.d.ts +48 -3
  57. package/dist/manifest.js +14 -3
  58. package/dist/manifest.js.map +1 -1
  59. package/dist/mcp/constants.d.ts +4 -0
  60. package/dist/mcp/constants.js +4 -0
  61. package/dist/mcp/constants.js.map +1 -1
  62. package/dist/mcp/dispatch.d.ts +21 -7
  63. package/dist/mcp/dispatch.js +42 -7
  64. package/dist/mcp/dispatch.js.map +1 -1
  65. package/dist/mcp/http.d.ts +23 -5
  66. package/dist/mcp/http.js +64 -9
  67. package/dist/mcp/http.js.map +1 -1
  68. package/dist/mcp/index.d.ts +14 -6
  69. package/dist/mcp/index.js +7 -3
  70. package/dist/mcp/index.js.map +1 -1
  71. package/dist/mcp/mrtr.d.ts +40 -8
  72. package/dist/mcp/mrtr.js +32 -11
  73. package/dist/mcp/mrtr.js.map +1 -1
  74. package/dist/mcp/prompts.d.ts +25 -0
  75. package/dist/mcp/prompts.js +164 -0
  76. package/dist/mcp/prompts.js.map +1 -0
  77. package/dist/mcp/resources.d.ts +48 -0
  78. package/dist/mcp/resources.js +142 -0
  79. package/dist/mcp/resources.js.map +1 -0
  80. package/dist/mcp/server.d.ts +30 -5
  81. package/dist/mcp/server.js +143 -16
  82. package/dist/mcp/server.js.map +1 -1
  83. package/dist/mcp/stdio.d.ts +5 -0
  84. package/dist/mcp/stdio.js +16 -3
  85. package/dist/mcp/stdio.js.map +1 -1
  86. package/dist/mcp/subscriptions.d.ts +61 -0
  87. package/dist/mcp/subscriptions.js +188 -0
  88. package/dist/mcp/subscriptions.js.map +1 -0
  89. package/dist/mcp/tasks.d.ts +127 -0
  90. package/dist/mcp/tasks.js +448 -0
  91. package/dist/mcp/tasks.js.map +1 -0
  92. package/dist/module-files.d.ts +24 -0
  93. package/dist/module-files.js +97 -0
  94. package/dist/module-files.js.map +1 -0
  95. package/dist/prompt.d.ts +133 -0
  96. package/dist/prompt.js +222 -0
  97. package/dist/prompt.js.map +1 -0
  98. package/dist/registry.d.ts +6 -0
  99. package/dist/registry.js.map +1 -1
  100. package/dist/remote/client.d.ts +17 -1
  101. package/dist/remote/client.js +18 -2
  102. package/dist/remote/client.js.map +1 -1
  103. package/dist/resource.d.ts +169 -0
  104. package/dist/resource.js +301 -0
  105. package/dist/resource.js.map +1 -0
  106. package/dist/route.d.ts +71 -0
  107. package/dist/route.js +280 -0
  108. package/dist/route.js.map +1 -0
  109. package/dist/start.d.ts +14 -3
  110. package/dist/start.js +76 -11
  111. package/dist/start.js.map +1 -1
  112. package/dist/state.d.ts +38 -0
  113. package/dist/state.js +98 -0
  114. package/dist/state.js.map +1 -0
  115. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename } from \"node:path\"\nimport type { MextApp } from \"./command.ts\"\nimport { MextBuildError, type BuildIssue } from \"./errors.ts\"\nimport { importModuleDefaults, walkModuleFiles } from \"./module-files.ts\"\nimport type { Principal } from \"./principal.ts\"\n\n/**\n * MCP 자원 (§12.3). resources/**\\/*.ts 파일 하나 = defineResource 하나. 식별자 = uri (고정 URI 또는 RFC 6570 level 1 템플릿).\n * MCP 전용 (CLI 노출 없음). 실행 어댑터 = mcp/resources.ts\n */\n\n/** read · list 의 ctx. ask · progress 없음 */\nexport interface ResourceContext {\n principal: Principal\n signal: AbortSignal\n app: MextApp\n}\n\n/** complete 의 ctx. arguments = 이미 정한 다른 템플릿 변수 */\nexport interface ResourceCompleteContext extends ResourceContext {\n arguments: Record<string, string>\n}\n\n/** completion/complete 후보 (§12.3 completion) */\nexport type ResourceCompleter = (value: string, ctx: ResourceCompleteContext) => readonly string[] | Promise<readonly string[]>\n\n/** list 결과 항목 (resources/list 의 Resource). title · description · mimeType 생략 = 자원 정의의 값 */\nexport interface ResourceListItem {\n uri: string\n name: string\n title?: string\n description?: string\n mimeType?: string\n size?: number\n}\n\ntype TemplateVariable<S extends string> = S extends `${string}{${infer V}}${infer Rest}` ? V | TemplateVariable<Rest> : never\n\n/** 템플릿 변수 → 값 (고정 URI = {}) */\nexport type ResourceVariables<U extends string> = string extends U ? Record<string, string> : { [K in TemplateVariable<U>]: string }\n\nexport interface ResourceDefinition<U extends string> {\n /** 고정 URI 또는 RFC 6570 level 1 템플릿 ({var}) */\n uri: U\n title?: string\n /** 필수. resources/list · templates/list 설명 */\n description: string\n /** read 반환이 string · Uint8Array 일 때의 mimeType. 그 외 (JSON) 기본 application/json */\n mimeType?: string\n /** 읽기에 필요한 scopes. 전부 보유해야 목록 · 읽기 */\n scopes?: readonly string[]\n /** resourceSubscriptions 대상 (§12.5) */\n subscribe?: boolean\n /** 템플릿 전용. 구체 URI 목록 → resources/list */\n list?: (ctx: ResourceContext) => readonly ResourceListItem[] | Promise<readonly ResourceListItem[]>\n /** 템플릿 전용. 변수별 completion/complete */\n complete?: { [K in TemplateVariable<U>]?: ResourceCompleter }\n /** string = text · Uint8Array = blob · 그 외 = JSON text */\n read(variables: ResourceVariables<U>, ctx: ResourceContext): unknown\n}\n\nexport const RESOURCE: unique symbol = Symbol.for(\"@obov/mext/resource\") as never\n\nexport interface Resource<U extends string = string> {\n readonly [RESOURCE]: true\n readonly uri: U\n readonly title: string | undefined\n readonly description: string\n readonly mimeType: string | undefined\n readonly scopes: readonly string[]\n readonly subscribe: boolean\n readonly list: ((ctx: ResourceContext) => readonly ResourceListItem[] | Promise<readonly ResourceListItem[]>) | undefined\n readonly complete: Readonly<Record<string, ResourceCompleter>>\n read(variables: ResourceVariables<U>, ctx: ResourceContext): unknown\n}\n\nexport function defineResource<const U extends string>(definition: ResourceDefinition<U>): Resource<U> {\n const d = definition as Partial<ResourceDefinition<U>>\n const fail = (message: string): never => {\n throw new TypeError(`defineResource: ${message}`)\n }\n if (typeof d.uri !== \"string\") fail(\"uri must be a string\")\n let template: UriTemplatePattern | undefined\n try {\n template = parseUriTemplate(d.uri!)\n } catch (error) {\n fail((error as Error).message)\n }\n if (typeof d.description !== \"string\" || d.description.trim() === \"\") fail(\"description must be a non-empty string\")\n if (typeof d.read !== \"function\") fail(\"read must be a function\")\n if (d.title !== undefined && typeof d.title !== \"string\") fail(\"title must be a string\")\n if (d.mimeType !== undefined && (typeof d.mimeType !== \"string\" || d.mimeType === \"\")) fail(\"mimeType must be a non-empty string\")\n if (d.scopes !== undefined && (!Array.isArray(d.scopes) || d.scopes.some((s) => typeof s !== \"string\"))) {\n fail(\"scopes must be an array of strings\")\n }\n if (d.subscribe !== undefined && typeof d.subscribe !== \"boolean\") fail(\"subscribe must be a boolean\")\n if (d.list !== undefined) {\n if (typeof d.list !== \"function\") fail(\"list must be a function\")\n if (!template) fail(`list applies to URI templates only (${d.uri} has no {variable})`)\n }\n const complete: Record<string, ResourceCompleter> = {}\n if (d.complete !== undefined) {\n if (typeof d.complete !== \"object\" || d.complete === null || Array.isArray(d.complete)) fail(\"complete must be an object\")\n for (const [key, fn] of Object.entries(d.complete as Record<string, unknown>)) {\n if (!template?.variables.includes(key)) fail(`complete.${key}: ${d.uri} has no {${key}} variable`)\n if (typeof fn !== \"function\") fail(`complete.${key} must be a function`)\n complete[key] = fn as ResourceCompleter\n }\n }\n const read = d.read!\n const list = d.list\n return Object.freeze({\n [RESOURCE]: true as const,\n uri: d.uri!,\n title: d.title,\n description: d.description!,\n mimeType: d.mimeType,\n scopes: Object.freeze([...(d.scopes ?? [])]),\n subscribe: d.subscribe === true,\n list: list ? (ctx: ResourceContext) => list.call(definition, ctx) : undefined,\n complete: Object.freeze(complete),\n read(variables: ResourceVariables<U>, ctx: ResourceContext) {\n return read.call(definition, variables, ctx)\n },\n })\n}\n\nexport function isResource(value: unknown): value is Resource {\n return typeof value === \"object\" && value !== null && (value as Record<symbol, unknown>)[RESOURCE] === true\n}\n\n/* ---------------------------------------------------------------- URI 템플릿 (RFC 6570 level 1) */\n\nexport interface UriTemplatePattern {\n /** 등장 순 */\n readonly variables: readonly string[]\n /** 변수 밖 문자 수 (매칭 우선순위) */\n readonly literalLength: number\n /** 변수 이름을 지운 형태 (\"users://{}/profile\"). 같으면 같은 템플릿 (중복) */\n readonly key: string\n /** 매칭 = 변수 값 (percent-decode), 아니면 undefined. 변수 = 비어 있지 않은 \"/\" 없는 문자열 */\n match(uri: string): Record<string, string> | undefined\n}\n\nconst SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:/\nconst VARNAME = /^[A-Za-z0-9_]+(?:\\.[A-Za-z0-9_]+)*$/\n\n/**\n * uri 해석. 변수 없음 = undefined (고정 URI). 형식 오류 = TypeError\n * (scheme 없음 · 공백 · 짝 없는 중괄호 · level 2+ 연산자 · 잘못된 변수 이름 · 같은 변수 반복 · 변수 연속)\n */\nexport function parseUriTemplate(uri: string): UriTemplatePattern | undefined {\n if (!SCHEME.test(uri)) throw new TypeError(`uri must be an absolute URI with a scheme (got ${JSON.stringify(uri)})`)\n if (/\\s/.test(uri)) throw new TypeError(`uri must not contain whitespace (got ${JSON.stringify(uri)})`)\n const literals: string[] = []\n const variables: string[] = []\n let rest = uri\n for (;;) {\n const open = rest.indexOf(\"{\")\n const close = rest.indexOf(\"}\")\n if (open < 0) {\n if (close >= 0) throw new TypeError(`unmatched \"}\" in ${uri}`)\n literals.push(rest)\n break\n }\n if (close >= 0 && close < open) throw new TypeError(`unmatched \"}\" in ${uri}`)\n const end = rest.indexOf(\"}\", open)\n if (end < 0) throw new TypeError(`unmatched \"{\" in ${uri}`)\n const name = rest.slice(open + 1, end)\n if (name !== \"\" && \"+#./;?&=,!@|\".includes(name[0]!)) {\n throw new TypeError(`${uri}: only RFC 6570 level 1 templates ({var}) are supported (got {${name}})`)\n }\n if (!VARNAME.test(name)) throw new TypeError(`${uri}: invalid variable name {${name}}`)\n if (variables.includes(name)) throw new TypeError(`${uri}: variable {${name}} appears more than once`)\n const literal = rest.slice(0, open)\n if (variables.length > 0 && literal === \"\") throw new TypeError(`${uri}: adjacent variables need a literal between them`)\n literals.push(literal)\n variables.push(name)\n rest = rest.slice(end + 1)\n }\n if (variables.length === 0) return undefined\n const pattern = new RegExp(`^${literals.map(escapeRegExp).join(\"([^/]+)\")}$`)\n return Object.freeze({\n variables: Object.freeze(variables),\n literalLength: literals.reduce((n, l) => n + l.length, 0),\n key: literals.join(\"{}\"),\n match(candidate: string) {\n const m = pattern.exec(candidate)\n if (!m) return undefined\n const values: Record<string, string> = {}\n for (let i = 0; i < variables.length; i++) {\n try {\n values[variables[i]!] = decodeURIComponent(m[i + 1]!)\n } catch {\n return undefined\n }\n }\n return values\n },\n })\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[\\\\^$.*+?()[\\]{}|]/g, \"\\\\$&\")\n}\n\n/* ---------------------------------------------------------------- 자원 집합 (Registry.resources) */\n\n/**\n * 등록된 자원의 메타데이터 + 모듈 로더. eager (스캔) = load 가 정의 그대로, lazy (mext start) = 모듈 import (1회 캐시)\n */\nexport interface RegisteredResource {\n /** 고정 URI 또는 템플릿 원문 */\n uri: string\n /** 템플릿이면 해석 결과 */\n template: UriTemplatePattern | undefined\n title: string | undefined\n description: string\n mimeType: string | undefined\n scopes: readonly string[]\n subscribe: boolean\n /** list 정의 여부 */\n list: boolean\n /** complete 를 정의한 변수 (정렬) */\n complete: readonly string[]\n /** resourcesDir 기준 상대 경로 (posix) */\n file: string | undefined\n load(): Promise<Resource>\n}\n\nexport interface ResourceSet {\n /** 고정 URI → 자원. uri 순 */\n readonly fixed: ReadonlyMap<string, RegisteredResource>\n /** 템플릿 자원. 매칭 순 (리터럴 문자 수 많은 순, 같으면 파일 경로 순) */\n readonly templates: readonly RegisteredResource[]\n}\n\n/** manifest 의 자원 (mext build). module 은 BuildManifestResource */\nexport interface ManifestResource {\n uri: string\n title?: string\n description: string\n mimeType?: string\n scopes: string[]\n subscribe: boolean\n list: boolean\n complete: string[]\n /** resourcesDir 기준 상대 경로 (posix) */\n file?: string\n}\n\nexport interface ResourceInput {\n resource: Resource\n /** resourcesDir 기준 상대 경로 (posix). 스캔 결과에만 있음 */\n file?: string\n}\n\nexport interface LazyResourceInput extends ManifestResource {\n /** 읽을 때 1회 호출 (결과 캐시, 실패는 다음 호출에서 재시도) */\n load: () => Promise<Resource>\n}\n\n/** 자원 목록 → ResourceSet. 중복 uri · 템플릿 = MextBuildError */\nexport function createResourceSet(inputs: readonly ResourceInput[]): ResourceSet {\n const { resources, issues } = collectResourceSet(inputs)\n if (issues.length > 0) throw new MextBuildError(issues)\n return resources\n}\n\n/**\n * createResourceSet 의 수집형 (mext build). 던지지 않는다. resources = 규칙을 통과한 자원만.\n * label = issue 의 file 접두 (resourcesDir 이름, \"resources/users/profile.ts\")\n */\nexport function collectResourceSet(\n inputs: readonly ResourceInput[],\n label?: string,\n): { resources: ResourceSet; issues: BuildIssue[] } {\n const entries: RegisteredResource[] = []\n const issues: BuildIssue[] = []\n for (const { resource, file } of inputs) {\n if (!isResource(resource)) {\n issues.push({ code: \"INVALID_RESOURCE\", message: \"not a defineResource result\", ...issueFile(file, label) })\n continue\n }\n entries.push({\n ...metadata(describe(resource, file)),\n load: () => Promise.resolve(resource),\n })\n }\n return assemble(entries, issues, label)\n}\n\n/** manifest (mext build 산출) → ResourceSet. 모듈은 읽을 때 import */\nexport function createLazyResourceSet(inputs: readonly LazyResourceInput[]): ResourceSet {\n const entries = inputs.map((input): RegisteredResource => {\n const load = input.load\n let pending: Promise<Resource> | undefined\n return {\n ...metadata(input),\n load: () =>\n (pending ??= load().catch((error: unknown) => {\n pending = undefined\n throw error\n })),\n }\n })\n const { resources, issues } = assemble(entries, [])\n if (issues.length > 0) throw new MextBuildError(issues)\n return resources\n}\n\n/** 자원 메타데이터 (manifest) */\nexport function describeResource(entry: RegisteredResource): ManifestResource {\n const out: ManifestResource = {\n uri: entry.uri,\n description: entry.description,\n scopes: [...entry.scopes],\n subscribe: entry.subscribe,\n list: entry.list,\n complete: [...entry.complete],\n }\n if (entry.title !== undefined) out.title = entry.title\n if (entry.mimeType !== undefined) out.mimeType = entry.mimeType\n if (entry.file !== undefined) out.file = entry.file\n return out\n}\n\n/** 모든 자원 (고정 → 템플릿 매칭 순) */\nexport function resourceEntries(set: ResourceSet): RegisteredResource[] {\n return [...set.fixed.values(), ...set.templates]\n}\n\n/** read 매칭: 고정 URI 우선, 다음 템플릿 (매칭 순). 없으면 undefined */\nexport function matchResource(\n set: ResourceSet,\n uri: string,\n): { entry: RegisteredResource; variables: Record<string, string> } | undefined {\n const fixed = set.fixed.get(uri)\n if (fixed) return { entry: fixed, variables: {} }\n for (const entry of set.templates) {\n const variables = entry.template!.match(uri)\n if (variables) return { entry, variables }\n }\n return undefined\n}\n\nfunction describe(resource: Resource, file: string | undefined): ManifestResource {\n return {\n uri: resource.uri,\n ...(resource.title !== undefined ? { title: resource.title } : {}),\n description: resource.description,\n ...(resource.mimeType !== undefined ? { mimeType: resource.mimeType } : {}),\n scopes: [...resource.scopes],\n subscribe: resource.subscribe,\n list: resource.list !== undefined,\n complete: Object.keys(resource.complete).sort(),\n ...(file !== undefined ? { file } : {}),\n }\n}\n\nfunction metadata(m: ManifestResource): Omit<RegisteredResource, \"load\"> {\n return {\n uri: m.uri,\n template: parseUriTemplate(m.uri),\n title: m.title,\n description: m.description,\n mimeType: m.mimeType,\n scopes: Object.freeze([...m.scopes]),\n subscribe: m.subscribe,\n list: m.list,\n complete: Object.freeze([...m.complete]),\n file: m.file,\n }\n}\n\nfunction assemble(\n entries: readonly RegisteredResource[],\n issues: BuildIssue[],\n label?: string,\n): { resources: ResourceSet; issues: BuildIssue[] } {\n const fixed = new Map<string, RegisteredResource>()\n const byKey = new Map<string, RegisteredResource>()\n const templates: RegisteredResource[] = []\n for (const entry of entries) {\n const where = { id: entry.uri, ...issueFile(entry.file, label) }\n const prev = entry.template ? byKey.get(entry.template.key) : fixed.get(entry.uri)\n if (prev) {\n const what = entry.template ? `URI template (same as ${prev.uri})` : \"URI\"\n const other = prev.file === undefined ? prev.uri : (issueFile(prev.file, label).file ?? prev.file)\n issues.push({ code: \"DUPLICATE_ID\", message: `duplicate resource ${what}, also ${other}`, ...where })\n continue\n }\n if (entry.template) {\n byKey.set(entry.template.key, entry)\n templates.push(entry)\n } else fixed.set(entry.uri, entry)\n }\n templates.sort(\n (a, b) => b.template!.literalLength - a.template!.literalLength || compare(a.file ?? a.uri, b.file ?? b.uri),\n )\n const sortedFixed = new Map([...fixed].sort(([a], [b]) => compare(a, b)))\n return { resources: { fixed: sortedFixed, templates }, issues }\n}\n\nfunction issueFile(file: string | undefined, label: string | undefined): { file?: string } {\n if (file === undefined) return {}\n return { file: label === undefined ? file : `${label}/${file}` }\n}\n\nfunction compare(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0\n}\n\n/* ---------------------------------------------------------------- 스캔 (resources/) */\n\n/**\n * resources/ 스캔 (수집형, mext build). 폴더 없음 = 자원 없음 (issue 아님).\n * 파일 규칙 = §3 의 private · 제외 · kebab-case. 각 파일의 default export = defineResource\n */\nexport async function collectResources(dir: string): Promise<{ inputs: ResourceInput[]; issues: BuildIssue[] }> {\n const label = basename(dir)\n const walked = walkModuleFiles(dir, label)\n const { modules, issues } = await importModuleDefaults(dir, walked.files, label, isResource, \"INVALID_RESOURCE\", \"defineResource\")\n return { inputs: modules.map(({ file, value }) => ({ resource: value, file })), issues: [...walked.issues, ...issues] }\n}\n\n/** Registry 에 자원 집합 연결 (없으면 그대로) */\nexport function withResources<R extends object>(registry: R, resources: ResourceSet | undefined): R & { resources?: ResourceSet } {\n return resources ? { ...registry, resources } : registry\n}\n\n/** 개발 모드 런타임 스캔: resources/ → ResourceSet. 폴더 없음 · 자원 없음 = undefined (기능 없음). 규칙 위반 = MextBuildError */\nexport async function loadResourceSet(dir: string): Promise<ResourceSet | undefined> {\n const scanned = await collectResources(dir)\n const { resources, issues } = collectResourceSet(scanned.inputs, basename(dir))\n const all = [...scanned.issues, ...issues]\n if (all.length > 0) throw new MextBuildError(all)\n return resources.fixed.size + resources.templates.length > 0 ? resources : undefined\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import type { MextApp } from "./command.ts";
2
+ import { type BuildIssue } from "./errors.ts";
3
+ /**
4
+ * Routes (§12.4): MCP 엔드포인트 밖 HTTP 경로. routes/**\/*.ts 파일 경로 = URL 경로.
5
+ * HTTP (dev · start · server.js · handler.js) 전용. stdio · CLI 없음. Origin 검사 · auth 대상 아님.
6
+ * Registry 와 별개 집합 (D1): 명령어 계약 (help · tools · manifestHash) 과 공유하는 것이 없다
7
+ */
8
+ export declare const ROUTE_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
9
+ export type RouteMethod = (typeof ROUTE_METHODS)[number];
10
+ export interface RouteContext {
11
+ /** [name] 세그먼트 값 (디코딩) */
12
+ params: Readonly<Record<string, string>>;
13
+ app: MextApp;
14
+ /** 요청 취소 (클라이언트 연결 종료) */
15
+ signal: AbortSignal;
16
+ /** 자원 갱신 알림 (§12.5). 명령어 ctx.resourceUpdated 와 같음 (state 없음 = no-op) */
17
+ resourceUpdated(uri: string): Promise<void>;
18
+ }
19
+ /** routes/ 모듈의 GET · POST · PUT · PATCH · DELETE export */
20
+ export type RouteHandler = (request: Request, ctx: RouteContext) => Response | Promise<Response>;
21
+ export type RouteModule = Partial<Record<RouteMethod, RouteHandler>>;
22
+ export interface ScannedRoute {
23
+ /** URL 경로 패턴. routes/items/[id].ts → "/items/[id]", routes/index.ts → "/" */
24
+ path: string;
25
+ /** routes/ 기준 상대 경로 (posix) */
26
+ file: string;
27
+ }
28
+ /** 실행 가능한 route. eager (loadRoutes) = 모듈 그대로, lazy (manifest) = 처음 요청에서 import */
29
+ export interface RouteEntry {
30
+ path: string;
31
+ file?: string;
32
+ /** export 한 메서드 (ROUTE_METHODS 순) */
33
+ methods: readonly RouteMethod[];
34
+ load: () => Promise<RouteModule>;
35
+ }
36
+ /**
37
+ * routes/ 파일 트리 해석 (import 없음). 폴더 없음 = route 없음.
38
+ * index.ts = 폴더 경로 · [name] = 동적 · `_` `.` 접두 = private · *.test.ts *.spec.ts *.d.ts 제외 · 그 외 kebab-case.
39
+ * 충돌 (MCP 엔드포인트 · /.well-known/oauth-protected-resource* · 같은 경로) = issue
40
+ */
41
+ export declare function walkRoutes(dir: string): {
42
+ routes: ScannedRoute[];
43
+ issues: BuildIssue[];
44
+ };
45
+ /** walkRoutes + 모듈 import · export 검사의 수집형 (mext build 일괄 검증용). 던지지 않는다 */
46
+ export declare function collectRoutes(dir: string): Promise<{
47
+ dir: string;
48
+ routes: (ScannedRoute & {
49
+ methods: RouteMethod[];
50
+ module: RouteModule;
51
+ })[];
52
+ issues: BuildIssue[];
53
+ }>;
54
+ /** 개발 모드 런타임 스캔: routes/ → RouteEntry[] (eager). 규칙 위반 = MextBuildError */
55
+ export declare function loadRoutes(dir: string): Promise<RouteEntry[]>;
56
+ /** 처음 호출에서 1회 (실패는 다음 호출에서 재시도) */
57
+ export declare function onceApp(factory: (() => MextApp | Promise<MextApp>) | undefined): () => Promise<MextApp>;
58
+ export interface RouteDispatchOptions {
59
+ routes: readonly RouteEntry[];
60
+ app: () => Promise<MextApp>;
61
+ /** 예외 보고. 기본 console.error (stderr) */
62
+ log?: (line: string) => void;
63
+ /** ctx.resourceUpdated. 기본 = no-op (uri 형식만 검사) */
64
+ resourceUpdated?: (uri: string) => Promise<void>;
65
+ }
66
+ /**
67
+ * route 처리기. 맞는 route 없음 = undefined (호출자가 404).
68
+ * 매칭 = 세그먼트 수가 같고 앞 세그먼트부터 고정이 동적보다 우선. 끝 "/" 1개 무시. MCP 엔드포인트 · well-known 은 대상 아님.
69
+ * export 없는 메서드 = 405 (Allow). HEAD = GET 의 본문 제거. 예외 · Response 아닌 반환 = 500 + log (onCommandError 미보고)
70
+ */
71
+ export declare function createRouteDispatcher(options: RouteDispatchOptions): (request: Request, url: URL) => Promise<Response | undefined>;
package/dist/route.js ADDED
@@ -0,0 +1,280 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { readdirSync, statSync } from "node:fs";
10
+ import { join, resolve } from "node:path";
11
+ import { pathToFileURL } from "node:url";
12
+ import { MextBuildError } from "./errors.js";
13
+ import { isSegment } from "./ids.js";
14
+ import { assertResourceUri } from "./invoke.js";
15
+ import { MCP_PATH } from "./mcp/constants.js";
16
+ /**
17
+ * Routes (§12.4): MCP 엔드포인트 밖 HTTP 경로. routes/**\/*.ts 파일 경로 = URL 경로.
18
+ * HTTP (dev · start · server.js · handler.js) 전용. stdio · CLI 없음. Origin 검사 · auth 대상 아님.
19
+ * Registry 와 별개 집합 (D1): 명령어 계약 (help · tools · manifestHash) 과 공유하는 것이 없다
20
+ */
21
+ export const ROUTE_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
22
+ /** RFC 9728 well-known 경로 (mcp/http.ts PROTECTED_RESOURCE_METADATA_PATH 와 같음) */
23
+ const PROTECTED_RESOURCE_PREFIX = "/.well-known/oauth-protected-resource";
24
+ const EXCLUDED_SUFFIXES = [".test.ts", ".spec.ts", ".d.ts"];
25
+ /** [name]: ctx.params 의 키 = JS 식별자 */
26
+ const DYNAMIC_SEGMENT = /^\[([A-Za-z_][A-Za-z0-9_]*)\]$/;
27
+ /**
28
+ * routes/ 파일 트리 해석 (import 없음). 폴더 없음 = route 없음.
29
+ * index.ts = 폴더 경로 · [name] = 동적 · `_` `.` 접두 = private · *.test.ts *.spec.ts *.d.ts 제외 · 그 외 kebab-case.
30
+ * 충돌 (MCP 엔드포인트 · /.well-known/oauth-protected-resource* · 같은 경로) = issue
31
+ */
32
+ export function walkRoutes(dir) {
33
+ const root = resolve(dir);
34
+ const routes = [];
35
+ const issues = [];
36
+ if (!isDirectory(root))
37
+ return { routes, issues };
38
+ const visit = (abs, segments) => {
39
+ const entries = readdirSync(abs, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : 1));
40
+ for (const entry of entries) {
41
+ const name = entry.name;
42
+ if (name.startsWith("_") || name.startsWith("."))
43
+ continue;
44
+ const rel = [...segments, name].join("/");
45
+ if (isDirEntry(abs, entry)) {
46
+ if (!isRouteSegment(name)) {
47
+ issues.push({ code: "INVALID_SEGMENT", message: `directory "${name}" is not kebab-case or [name]`, file: rel });
48
+ continue;
49
+ }
50
+ visit(join(abs, name), [...segments, name]);
51
+ continue;
52
+ }
53
+ if (!name.endsWith(".ts") || EXCLUDED_SUFFIXES.some((s) => name.endsWith(s)))
54
+ continue;
55
+ if (!isFileEntry(abs, entry))
56
+ continue;
57
+ const base = name.slice(0, -".ts".length);
58
+ if (base !== "index" && !isRouteSegment(base)) {
59
+ issues.push({ code: "INVALID_SEGMENT", message: `file "${name}" is not kebab-case or [name]`, file: rel });
60
+ continue;
61
+ }
62
+ const pathSegments = base === "index" ? segments : [...segments, base];
63
+ const path = `/${pathSegments.join("/")}`;
64
+ const params = pathSegments.map((s) => DYNAMIC_SEGMENT.exec(s)?.[1]).filter((p) => p !== undefined);
65
+ const repeated = params.find((p, i) => params.indexOf(p) !== i);
66
+ if (repeated !== undefined) {
67
+ issues.push({ code: "INVALID_SEGMENT", message: `route ${path}: parameter [${repeated}] appears twice`, file: rel, id: path });
68
+ continue;
69
+ }
70
+ routes.push({ path, file: rel });
71
+ }
72
+ };
73
+ visit(root, []);
74
+ const accepted = [];
75
+ const seen = new Map();
76
+ for (const route of routes) {
77
+ const where = { file: route.file, id: route.path };
78
+ if (route.path === MCP_PATH) {
79
+ issues.push({ code: "ROUTE_CONFLICT", message: `route ${route.path} conflicts with the MCP endpoint`, ...where });
80
+ continue;
81
+ }
82
+ if (route.path.startsWith(PROTECTED_RESOURCE_PREFIX)) {
83
+ issues.push({ code: "ROUTE_CONFLICT", message: `route ${route.path} conflicts with ${PROTECTED_RESOURCE_PREFIX}*`, ...where });
84
+ continue;
85
+ }
86
+ // 동적 세그먼트 이름만 다른 경로 (/items/[id] · /items/[slug]) = 같은 경로
87
+ const shape = route.path.replace(/\[[^\]/]*\]/g, "[]");
88
+ const prev = seen.get(shape);
89
+ if (prev) {
90
+ issues.push({ code: "DUPLICATE_ROUTE", message: `route ${route.path} duplicates ${prev.path} (${prev.file})`, ...where });
91
+ continue;
92
+ }
93
+ seen.set(shape, route);
94
+ accepted.push(route);
95
+ }
96
+ return { routes: accepted, issues };
97
+ }
98
+ /** walkRoutes + 모듈 import · export 검사의 수집형 (mext build 일괄 검증용). 던지지 않는다 */
99
+ export async function collectRoutes(dir) {
100
+ const root = resolve(dir);
101
+ const walked = walkRoutes(root);
102
+ const issues = [...walked.issues];
103
+ const routes = [];
104
+ for (const route of walked.routes) {
105
+ const where = { file: route.file, id: route.path };
106
+ let mod;
107
+ try {
108
+ mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(join(root, route.file)).href)));
109
+ }
110
+ catch (error) {
111
+ issues.push({ code: "LOAD_FAILED", message: error instanceof Error ? error.message : String(error), ...where });
112
+ continue;
113
+ }
114
+ const bad = ROUTE_METHODS.filter((m) => mod[m] !== undefined && typeof mod[m] !== "function");
115
+ if (bad.length > 0) {
116
+ issues.push({ code: "INVALID_ROUTE", message: `export ${bad.join(", ")} must be a function (request, ctx) => Response`, ...where });
117
+ continue;
118
+ }
119
+ const methods = ROUTE_METHODS.filter((m) => typeof mod[m] === "function");
120
+ if (methods.length === 0) {
121
+ issues.push({ code: "INVALID_ROUTE", message: `no handler export (${ROUTE_METHODS.join(" · ")})`, ...where });
122
+ continue;
123
+ }
124
+ routes.push({ ...route, methods, module: mod });
125
+ }
126
+ return { dir: root, routes, issues };
127
+ }
128
+ /** 개발 모드 런타임 스캔: routes/ → RouteEntry[] (eager). 규칙 위반 = MextBuildError */
129
+ export async function loadRoutes(dir) {
130
+ const { routes, issues } = await collectRoutes(dir);
131
+ if (issues.length > 0)
132
+ throw new MextBuildError(issues);
133
+ return routes.map((r) => ({ path: r.path, file: r.file, methods: r.methods, load: () => Promise.resolve(r.module) }));
134
+ }
135
+ /** 처음 호출에서 1회 (실패는 다음 호출에서 재시도) */
136
+ export function onceApp(factory) {
137
+ if (!factory)
138
+ return async () => ({});
139
+ let pending;
140
+ return () => (pending ??= Promise.resolve()
141
+ .then(factory)
142
+ .catch((error) => {
143
+ pending = undefined;
144
+ throw error;
145
+ }));
146
+ }
147
+ /**
148
+ * route 처리기. 맞는 route 없음 = undefined (호출자가 404).
149
+ * 매칭 = 세그먼트 수가 같고 앞 세그먼트부터 고정이 동적보다 우선. 끝 "/" 1개 무시. MCP 엔드포인트 · well-known 은 대상 아님.
150
+ * export 없는 메서드 = 405 (Allow). HEAD = GET 의 본문 제거. 예외 · Response 아닌 반환 = 500 + log (onCommandError 미보고)
151
+ */
152
+ export function createRouteDispatcher(options) {
153
+ const log = options.log ?? ((line) => console.error(line));
154
+ const resourceUpdated = options.resourceUpdated ?? (async (uri) => assertResourceUri(uri));
155
+ const compiled = options.routes
156
+ .map((route) => ({ route, segments: route.path === "/" ? [] : route.path.slice(1).split("/") }))
157
+ .map(({ route, segments }) => ({
158
+ route,
159
+ segments: segments.map((s) => ({ literal: DYNAMIC_SEGMENT.exec(s) ? undefined : s, param: DYNAMIC_SEGMENT.exec(s)?.[1] })),
160
+ }))
161
+ .sort((a, b) => compareSpecificity(a.segments, b.segments) || (a.route.path < b.route.path ? -1 : 1));
162
+ // 모듈 로드 1회 캐시 (lazy 실패는 다음 요청에서 재시도)
163
+ const modules = new Map();
164
+ const loadModule = (route) => {
165
+ let pending = modules.get(route);
166
+ if (!pending) {
167
+ pending = route.load().catch((error) => {
168
+ modules.delete(route);
169
+ throw error;
170
+ });
171
+ modules.set(route, pending);
172
+ }
173
+ return pending;
174
+ };
175
+ const match = (pathname) => {
176
+ if (pathname === MCP_PATH || pathname.startsWith(PROTECTED_RESOURCE_PREFIX))
177
+ return undefined;
178
+ const trimmed = pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
179
+ const parts = trimmed === "/" ? [] : trimmed.slice(1).split("/");
180
+ candidates: for (const { route, segments } of compiled) {
181
+ if (segments.length !== parts.length)
182
+ continue;
183
+ const params = {};
184
+ for (let i = 0; i < parts.length; i++) {
185
+ const part = parts[i];
186
+ const seg = segments[i];
187
+ if (seg.literal !== undefined) {
188
+ if (part !== seg.literal)
189
+ continue candidates;
190
+ continue;
191
+ }
192
+ if (part === "")
193
+ continue candidates;
194
+ try {
195
+ params[seg.param] = decodeURIComponent(part);
196
+ }
197
+ catch {
198
+ continue candidates;
199
+ }
200
+ }
201
+ return { route, params };
202
+ }
203
+ return undefined;
204
+ };
205
+ return async (request, url) => {
206
+ const found = match(url.pathname);
207
+ if (!found)
208
+ return undefined;
209
+ const { route, params } = found;
210
+ const head = request.method === "HEAD";
211
+ const method = (head ? "GET" : request.method);
212
+ if (!route.methods.includes(method)) {
213
+ const allow = route.methods.includes("GET") ? [...route.methods, "HEAD"] : [...route.methods];
214
+ return new Response("Method Not Allowed\n", {
215
+ status: 405,
216
+ headers: { Allow: allow.join(", "), "Content-Type": "text/plain; charset=utf-8" },
217
+ });
218
+ }
219
+ try {
220
+ const mod = await loadModule(route);
221
+ const handler = mod[method];
222
+ if (typeof handler !== "function")
223
+ throw new TypeError(`${route.file ?? route.path}: export ${method} is not a function`);
224
+ const ctx = { params: Object.freeze(params), app: await options.app(), signal: request.signal, resourceUpdated };
225
+ const response = await handler(request, ctx);
226
+ if (!(response instanceof Response))
227
+ throw new TypeError(`route ${method} ${route.path} did not return a Response`);
228
+ if (!head)
229
+ return response;
230
+ await response.body?.cancel().catch(() => { });
231
+ return new Response(null, { status: response.status, statusText: response.statusText, headers: response.headers });
232
+ }
233
+ catch (error) {
234
+ try {
235
+ log(`route ${request.method} ${route.path}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);
236
+ }
237
+ catch {
238
+ // 보고는 응답을 바꾸지 않는다
239
+ }
240
+ return new Response("Internal Server Error\n", { status: 500, headers: { "Content-Type": "text/plain; charset=utf-8" } });
241
+ }
242
+ };
243
+ }
244
+ /** 앞 세그먼트부터 고정 < 동적 */
245
+ function compareSpecificity(a, b) {
246
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
247
+ const x = a[i].literal === undefined ? 1 : 0;
248
+ const y = b[i].literal === undefined ? 1 : 0;
249
+ if (x !== y)
250
+ return x - y;
251
+ }
252
+ return a.length - b.length;
253
+ }
254
+ function isRouteSegment(name) {
255
+ return isSegment(name) || DYNAMIC_SEGMENT.test(name);
256
+ }
257
+ function isDirectory(path) {
258
+ try {
259
+ return statSync(path).isDirectory();
260
+ }
261
+ catch {
262
+ return false;
263
+ }
264
+ }
265
+ function isDirEntry(parent, entry) {
266
+ return entry.isDirectory() || (entry.isSymbolicLink() && isDirectory(join(parent, entry.name)));
267
+ }
268
+ function isFileEntry(parent, entry) {
269
+ if (entry.isFile())
270
+ return true;
271
+ if (!entry.isSymbolicLink())
272
+ return false;
273
+ try {
274
+ return statSync(join(parent, entry.name)).isFile();
275
+ }
276
+ catch {
277
+ return false;
278
+ }
279
+ }
280
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdirSync, statSync, type Dirent } from \"node:fs\"\nimport { join, resolve } from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\nimport type { MextApp } from \"./command.ts\"\nimport { MextBuildError, type BuildIssue } from \"./errors.ts\"\nimport { isSegment } from \"./ids.ts\"\nimport { assertResourceUri } from \"./invoke.ts\"\nimport { MCP_PATH } from \"./mcp/constants.ts\"\n\n/**\n * Routes (§12.4): MCP 엔드포인트 밖 HTTP 경로. routes/**\\/*.ts 파일 경로 = URL 경로.\n * HTTP (dev · start · server.js · handler.js) 전용. stdio · CLI 없음. Origin 검사 · auth 대상 아님.\n * Registry 와 별개 집합 (D1): 명령어 계약 (help · tools · manifestHash) 과 공유하는 것이 없다\n */\n\nexport const ROUTE_METHODS = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"] as const\nexport type RouteMethod = (typeof ROUTE_METHODS)[number]\n\nexport interface RouteContext {\n /** [name] 세그먼트 값 (디코딩) */\n params: Readonly<Record<string, string>>\n app: MextApp\n /** 요청 취소 (클라이언트 연결 종료) */\n signal: AbortSignal\n /** 자원 갱신 알림 (§12.5). 명령어 ctx.resourceUpdated 와 같음 (state 없음 = no-op) */\n resourceUpdated(uri: string): Promise<void>\n}\n\n/** routes/ 모듈의 GET · POST · PUT · PATCH · DELETE export */\nexport type RouteHandler = (request: Request, ctx: RouteContext) => Response | Promise<Response>\n\nexport type RouteModule = Partial<Record<RouteMethod, RouteHandler>>\n\nexport interface ScannedRoute {\n /** URL 경로 패턴. routes/items/[id].ts → \"/items/[id]\", routes/index.ts → \"/\" */\n path: string\n /** routes/ 기준 상대 경로 (posix) */\n file: string\n}\n\n/** 실행 가능한 route. eager (loadRoutes) = 모듈 그대로, lazy (manifest) = 처음 요청에서 import */\nexport interface RouteEntry {\n path: string\n file?: string\n /** export 한 메서드 (ROUTE_METHODS 순) */\n methods: readonly RouteMethod[]\n load: () => Promise<RouteModule>\n}\n\n/** RFC 9728 well-known 경로 (mcp/http.ts PROTECTED_RESOURCE_METADATA_PATH 와 같음) */\nconst PROTECTED_RESOURCE_PREFIX = \"/.well-known/oauth-protected-resource\"\nconst EXCLUDED_SUFFIXES = [\".test.ts\", \".spec.ts\", \".d.ts\"]\n/** [name]: ctx.params 의 키 = JS 식별자 */\nconst DYNAMIC_SEGMENT = /^\\[([A-Za-z_][A-Za-z0-9_]*)\\]$/\n\n/**\n * routes/ 파일 트리 해석 (import 없음). 폴더 없음 = route 없음.\n * index.ts = 폴더 경로 · [name] = 동적 · `_` `.` 접두 = private · *.test.ts *.spec.ts *.d.ts 제외 · 그 외 kebab-case.\n * 충돌 (MCP 엔드포인트 · /.well-known/oauth-protected-resource* · 같은 경로) = issue\n */\nexport function walkRoutes(dir: string): { routes: ScannedRoute[]; issues: BuildIssue[] } {\n const root = resolve(dir)\n const routes: ScannedRoute[] = []\n const issues: BuildIssue[] = []\n if (!isDirectory(root)) return { routes, issues }\n\n const visit = (abs: string, segments: string[]): void => {\n const entries = readdirSync(abs, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : 1))\n for (const entry of entries) {\n const name = entry.name\n if (name.startsWith(\"_\") || name.startsWith(\".\")) continue\n const rel = [...segments, name].join(\"/\")\n if (isDirEntry(abs, entry)) {\n if (!isRouteSegment(name)) {\n issues.push({ code: \"INVALID_SEGMENT\", message: `directory \"${name}\" is not kebab-case or [name]`, file: rel })\n continue\n }\n visit(join(abs, name), [...segments, name])\n continue\n }\n if (!name.endsWith(\".ts\") || EXCLUDED_SUFFIXES.some((s) => name.endsWith(s))) continue\n if (!isFileEntry(abs, entry)) continue\n const base = name.slice(0, -\".ts\".length)\n if (base !== \"index\" && !isRouteSegment(base)) {\n issues.push({ code: \"INVALID_SEGMENT\", message: `file \"${name}\" is not kebab-case or [name]`, file: rel })\n continue\n }\n const pathSegments = base === \"index\" ? segments : [...segments, base]\n const path = `/${pathSegments.join(\"/\")}`\n const params = pathSegments.map((s) => DYNAMIC_SEGMENT.exec(s)?.[1]).filter((p): p is string => p !== undefined)\n const repeated = params.find((p, i) => params.indexOf(p) !== i)\n if (repeated !== undefined) {\n issues.push({ code: \"INVALID_SEGMENT\", message: `route ${path}: parameter [${repeated}] appears twice`, file: rel, id: path })\n continue\n }\n routes.push({ path, file: rel })\n }\n }\n visit(root, [])\n\n const accepted: ScannedRoute[] = []\n const seen = new Map<string, ScannedRoute>()\n for (const route of routes) {\n const where = { file: route.file, id: route.path }\n if (route.path === MCP_PATH) {\n issues.push({ code: \"ROUTE_CONFLICT\", message: `route ${route.path} conflicts with the MCP endpoint`, ...where })\n continue\n }\n if (route.path.startsWith(PROTECTED_RESOURCE_PREFIX)) {\n issues.push({ code: \"ROUTE_CONFLICT\", message: `route ${route.path} conflicts with ${PROTECTED_RESOURCE_PREFIX}*`, ...where })\n continue\n }\n // 동적 세그먼트 이름만 다른 경로 (/items/[id] · /items/[slug]) = 같은 경로\n const shape = route.path.replace(/\\[[^\\]/]*\\]/g, \"[]\")\n const prev = seen.get(shape)\n if (prev) {\n issues.push({ code: \"DUPLICATE_ROUTE\", message: `route ${route.path} duplicates ${prev.path} (${prev.file})`, ...where })\n continue\n }\n seen.set(shape, route)\n accepted.push(route)\n }\n return { routes: accepted, issues }\n}\n\n/** walkRoutes + 모듈 import · export 검사의 수집형 (mext build 일괄 검증용). 던지지 않는다 */\nexport async function collectRoutes(\n dir: string,\n): Promise<{ dir: string; routes: (ScannedRoute & { methods: RouteMethod[]; module: RouteModule })[]; issues: BuildIssue[] }> {\n const root = resolve(dir)\n const walked = walkRoutes(root)\n const issues = [...walked.issues]\n const routes: (ScannedRoute & { methods: RouteMethod[]; module: RouteModule })[] = []\n for (const route of walked.routes) {\n const where = { file: route.file, id: route.path }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(join(root, route.file)).href)) as Record<string, unknown>\n } catch (error) {\n issues.push({ code: \"LOAD_FAILED\", message: error instanceof Error ? error.message : String(error), ...where })\n continue\n }\n const bad = ROUTE_METHODS.filter((m) => mod[m] !== undefined && typeof mod[m] !== \"function\")\n if (bad.length > 0) {\n issues.push({ code: \"INVALID_ROUTE\", message: `export ${bad.join(\", \")} must be a function (request, ctx) => Response`, ...where })\n continue\n }\n const methods = ROUTE_METHODS.filter((m) => typeof mod[m] === \"function\")\n if (methods.length === 0) {\n issues.push({ code: \"INVALID_ROUTE\", message: `no handler export (${ROUTE_METHODS.join(\" · \")})`, ...where })\n continue\n }\n routes.push({ ...route, methods, module: mod as RouteModule })\n }\n return { dir: root, routes, issues }\n}\n\n/** 개발 모드 런타임 스캔: routes/ → RouteEntry[] (eager). 규칙 위반 = MextBuildError */\nexport async function loadRoutes(dir: string): Promise<RouteEntry[]> {\n const { routes, issues } = await collectRoutes(dir)\n if (issues.length > 0) throw new MextBuildError(issues)\n return routes.map((r) => ({ path: r.path, file: r.file, methods: r.methods, load: () => Promise.resolve(r.module) }))\n}\n\n/** 처음 호출에서 1회 (실패는 다음 호출에서 재시도) */\nexport function onceApp(factory: (() => MextApp | Promise<MextApp>) | undefined): () => Promise<MextApp> {\n if (!factory) return async () => ({}) as MextApp\n let pending: Promise<MextApp> | undefined\n return () =>\n (pending ??= Promise.resolve()\n .then(factory)\n .catch((error: unknown) => {\n pending = undefined\n throw error\n }))\n}\n\nexport interface RouteDispatchOptions {\n routes: readonly RouteEntry[]\n app: () => Promise<MextApp>\n /** 예외 보고. 기본 console.error (stderr) */\n log?: (line: string) => void\n /** ctx.resourceUpdated. 기본 = no-op (uri 형식만 검사) */\n resourceUpdated?: (uri: string) => Promise<void>\n}\n\n/**\n * route 처리기. 맞는 route 없음 = undefined (호출자가 404).\n * 매칭 = 세그먼트 수가 같고 앞 세그먼트부터 고정이 동적보다 우선. 끝 \"/\" 1개 무시. MCP 엔드포인트 · well-known 은 대상 아님.\n * export 없는 메서드 = 405 (Allow). HEAD = GET 의 본문 제거. 예외 · Response 아닌 반환 = 500 + log (onCommandError 미보고)\n */\nexport function createRouteDispatcher(options: RouteDispatchOptions): (request: Request, url: URL) => Promise<Response | undefined> {\n const log = options.log ?? ((line: string) => console.error(line))\n const resourceUpdated = options.resourceUpdated ?? (async (uri: string) => assertResourceUri(uri))\n const compiled = options.routes\n .map((route) => ({ route, segments: route.path === \"/\" ? [] : route.path.slice(1).split(\"/\") }))\n .map(({ route, segments }) => ({\n route,\n segments: segments.map((s) => ({ literal: DYNAMIC_SEGMENT.exec(s) ? undefined : s, param: DYNAMIC_SEGMENT.exec(s)?.[1] })),\n }))\n .sort((a, b) => compareSpecificity(a.segments, b.segments) || (a.route.path < b.route.path ? -1 : 1))\n // 모듈 로드 1회 캐시 (lazy 실패는 다음 요청에서 재시도)\n const modules = new Map<RouteEntry, Promise<RouteModule>>()\n const loadModule = (route: RouteEntry): Promise<RouteModule> => {\n let pending = modules.get(route)\n if (!pending) {\n pending = route.load().catch((error: unknown) => {\n modules.delete(route)\n throw error\n })\n modules.set(route, pending)\n }\n return pending\n }\n\n const match = (pathname: string): { route: RouteEntry; params: Record<string, string> } | undefined => {\n if (pathname === MCP_PATH || pathname.startsWith(PROTECTED_RESOURCE_PREFIX)) return undefined\n const trimmed = pathname.length > 1 && pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname\n const parts = trimmed === \"/\" ? [] : trimmed.slice(1).split(\"/\")\n candidates: for (const { route, segments } of compiled) {\n if (segments.length !== parts.length) continue\n const params: Record<string, string> = {}\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]!\n const seg = segments[i]!\n if (seg.literal !== undefined) {\n if (part !== seg.literal) continue candidates\n continue\n }\n if (part === \"\") continue candidates\n try {\n params[seg.param!] = decodeURIComponent(part)\n } catch {\n continue candidates\n }\n }\n return { route, params }\n }\n return undefined\n }\n\n return async (request, url) => {\n const found = match(url.pathname)\n if (!found) return undefined\n const { route, params } = found\n const head = request.method === \"HEAD\"\n const method = (head ? \"GET\" : request.method) as RouteMethod\n if (!route.methods.includes(method)) {\n const allow = route.methods.includes(\"GET\") ? [...route.methods, \"HEAD\"] : [...route.methods]\n return new Response(\"Method Not Allowed\\n\", {\n status: 405,\n headers: { Allow: allow.join(\", \"), \"Content-Type\": \"text/plain; charset=utf-8\" },\n })\n }\n try {\n const mod = await loadModule(route)\n const handler = mod[method]\n if (typeof handler !== \"function\") throw new TypeError(`${route.file ?? route.path}: export ${method} is not a function`)\n const ctx: RouteContext = { params: Object.freeze(params), app: await options.app(), signal: request.signal, resourceUpdated }\n const response: unknown = await handler(request, ctx)\n if (!(response instanceof Response)) throw new TypeError(`route ${method} ${route.path} did not return a Response`)\n if (!head) return response\n await response.body?.cancel().catch(() => {})\n return new Response(null, { status: response.status, statusText: response.statusText, headers: response.headers })\n } catch (error) {\n try {\n log(`route ${request.method} ${route.path}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`)\n } catch {\n // 보고는 응답을 바꾸지 않는다\n }\n return new Response(\"Internal Server Error\\n\", { status: 500, headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } })\n }\n }\n}\n\n/** 앞 세그먼트부터 고정 < 동적 */\nfunction compareSpecificity(a: readonly { literal?: string }[], b: readonly { literal?: string }[]): number {\n for (let i = 0; i < Math.min(a.length, b.length); i++) {\n const x = a[i]!.literal === undefined ? 1 : 0\n const y = b[i]!.literal === undefined ? 1 : 0\n if (x !== y) return x - y\n }\n return a.length - b.length\n}\n\nfunction isRouteSegment(name: string): boolean {\n return isSegment(name) || DYNAMIC_SEGMENT.test(name)\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n\nfunction isDirEntry(parent: string, entry: Dirent): boolean {\n return entry.isDirectory() || (entry.isSymbolicLink() && isDirectory(join(parent, entry.name)))\n}\n\nfunction isFileEntry(parent: string, entry: Dirent): boolean {\n if (entry.isFile()) return true\n if (!entry.isSymbolicLink()) return false\n try {\n return statSync(join(parent, entry.name)).isFile()\n } catch {\n return false\n }\n}\n"]}
package/dist/start.d.ts CHANGED
@@ -2,6 +2,7 @@ import { type MextConfig } from "./config.ts";
2
2
  import { type Instrumentation } from "./instrumentation.ts";
3
3
  import { type BuildManifest } from "./manifest.ts";
4
4
  import { type Registry } from "./registry.ts";
5
+ import type { RouteEntry } from "./route.ts";
5
6
  /**
6
7
  * @obov/mext/start: .mext/ (mext build 산출) 실행 런타임. 소스 스캔 · TypeScript 없음.
7
8
  * 생성 파일 계약 (mext build 가 쓰는 server.js · handler.js, 바꾸면 기존 빌드가 깨진다):
@@ -26,8 +27,11 @@ export interface StartOptions {
26
27
  };
27
28
  }
28
29
  export interface FetchHandler {
29
- /** 거부하지 않는다. 초기화 실패 · 내부 오류 = 500 JSON-RPC 오류 */
30
- fetch(request: Request): Promise<Response>;
30
+ /**
31
+ * 거부하지 않는다. 초기화 실패 · 내부 오류 = 500 JSON-RPC 오류.
32
+ * rest 중 waitUntil 함수를 가진 객체 (Cloudflare ctx · Vercel 등) = 응답 후 task 실행 유지. 없으면 tasks 확장 미선언 (§10 · §12.6)
33
+ */
34
+ fetch(request: Request, ...rest: unknown[]): Promise<Response>;
31
35
  }
32
36
  /** .mext/ 로드 결과 */
33
37
  export interface LoadedBuild {
@@ -35,6 +39,8 @@ export interface LoadedBuild {
35
39
  config: MextConfig;
36
40
  registry: Registry;
37
41
  instrumentation: Instrumentation;
42
+ /** manifest.routes → lazy RouteEntry (모듈은 처음 요청에서 import) */
43
+ routes: RouteEntry[];
38
44
  }
39
45
  export interface LoadBuildOptions {
40
46
  /** 명령어 모듈 import (테스트 계측). 기본 = 동적 import */
@@ -53,7 +59,12 @@ export declare function createFetchHandler(dir: string | URL, options?: LoadBuil
53
59
  export declare function readBuildManifest(dir: string | URL): BuildManifest;
54
60
  /** manifest 검증 → instrumentation.js (register, 사용자 코드보다 먼저) → config.js → lazy Registry */
55
61
  export declare function loadBuild(dir: string | URL, options?: LoadBuildOptions): Promise<LoadedBuild>;
56
- /** manifest → lazy Registry. 명령어 모듈 (manifest.commands[].module) 은 load() 에서 import */
62
+ /** manifest.routes → RouteEntry. 405 = manifest 의 methods 만, 모듈 (routes[].module) 은 load() 에서 import */
63
+ export declare function routesFromManifest(manifest: BuildManifest, dir: string | URL, options?: LoadBuildOptions): RouteEntry[];
64
+ /**
65
+ * manifest → lazy Registry. 명령어 모듈 (manifest.commands[].module) · 자원 모듈 (resources[].module) ·
66
+ * 프롬프트 모듈 (prompts[].module) 은 load() 에서 import
67
+ */
57
68
  export declare function registryFromManifest(manifest: BuildManifest, dir: string | URL, options?: LoadBuildOptions): Registry;
58
69
  interface StartArgs {
59
70
  stdio: boolean;