@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.
- 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 +27 -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 +1 -2
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/run.js +21 -5
- 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 +17 -9
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/remote/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../version.ts\"\n\n/**\n * 원격 실행용 최소 MCP 클라이언트 (Streamable HTTP, 프로토콜 2026-07-28, stateless).\n * 요청마다 POST 1회: _meta envelope (버전 · clientInfo · clientCapabilities) + MCP-Protocol-Version · Mcp-Method ·\n * Mcp-Name · Mcp-Param-* 헤더. 응답 = application/json 또는 text/event-stream (progress 알림 → onNotification).\n * MRTR (InputRequiredResult) 재시도 루프는 callTool 의 onInputRequired 가 담당.\n */\n\nexport const PROTOCOL_VERSION = \"2026-07-28\"\n\nexport const META_KEYS = {\n protocolVersion: \"io.modelcontextprotocol/protocolVersion\",\n clientInfo: \"io.modelcontextprotocol/clientInfo\",\n clientCapabilities: \"io.modelcontextprotocol/clientCapabilities\",\n} as const\n\n/** 클라이언트가 처리하는 입력 요청 = elicitation form 만 (sampling · roots 없음) */\nexport const CLIENT_CAPABILITIES = { elicitation: { form: {} } } as const\n\n/** MRTR 재시도 상한 (같은 요청의 input_required 연속 횟수) */\nexport const MAX_INPUT_ROUNDS = 8\n\nexport interface RemoteTool {\n name: string\n description?: string\n inputSchema?: Record<string, unknown>\n annotations?: Record<string, unknown>\n}\n\nexport interface CallToolResult {\n content?: unknown[]\n structuredContent?: unknown\n isError?: boolean\n [key: string]: unknown\n}\n\n/** InputRequiredResult (resultType: input_required) */\nexport interface InputRequired {\n inputRequests?: Record<string, InputRequestObject>\n requestState?: string\n}\n\nexport interface InputRequestObject {\n method: string\n params?: Record<string, unknown>\n}\n\n/** 입력 요청 key → 응답 (ElicitResult 등). 이번 라운드 요청에 대한 것만 */\nexport type InputResponses = Record<string, unknown>\n\nexport interface RequestOptions {\n signal?: AbortSignal\n /** 서버 → 클라이언트 알림 (notifications/progress 등) */\n onNotification?: (method: string, params: Record<string, unknown>) => void\n /** _meta.progressToken. 있으면 서버가 SSE 로 응답 */\n progressToken?: string | number\n}\n\nexport interface CallToolOptions extends RequestOptions {\n /** input_required 응답 처리 → 이번 라운드의 inputResponses. 없으면 RemoteInputRequiredError */\n onInputRequired?: (request: InputRequired, round: number) => Promise<InputResponses>\n}\n\n/** HTTP 401. challenge = WWW-Authenticate 파싱 결과, data = JSON-RPC error.data (mext 는 UNAUTHENTICATED toJSON) */\nexport class RemoteUnauthorizedError extends Error {\n readonly challenge: BearerChallenge\n readonly data: unknown\n constructor(message: string, challenge: BearerChallenge, data: unknown) {\n super(message)\n this.name = \"RemoteUnauthorizedError\"\n this.challenge = challenge\n this.data = data\n }\n}\n\n/** JSON-RPC 오류 응답 (HTTP 400 · 403 · 500 포함) */\nexport class RemoteRpcError extends Error {\n readonly code: number\n readonly data: unknown\n readonly status: number\n constructor(message: string, code: number, data: unknown, status: number) {\n super(message)\n this.name = \"RemoteRpcError\"\n this.code = code\n this.data = data\n this.status = status\n }\n}\n\n/** 연결 실패 · JSON-RPC 가 아닌 응답 */\nexport class RemoteTransportError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = \"RemoteTransportError\"\n }\n}\n\n/** onInputRequired 없이 input_required 를 받음 · 라운드 상한 초과 */\nexport class RemoteInputRequiredError extends Error {\n readonly request: InputRequired\n constructor(message: string, request: InputRequired) {\n super(message)\n this.name = \"RemoteInputRequiredError\"\n this.request = request\n }\n}\n\nexport interface RemoteClientOptions {\n /** MCP 엔드포인트 (http(s)://host/mcp) */\n url: string\n /** 요청마다 호출. 없으면 Authorization 헤더 없음 */\n token?: () => string | undefined | Promise<string | undefined>\n fetch?: typeof fetch\n clientInfo?: { name: string; version: string }\n}\n\n/** tools/list 전체 페이지 + 첫 페이지의 캐시 힌트 (2026-07-28 ttlMs · cacheScope) */\nexport interface ToolsListResult {\n tools: RemoteTool[]\n ttlMs?: number\n cacheScope?: string\n}\n\nexport interface RemoteClient {\n readonly url: string\n request(method: string, params?: Record<string, unknown>, options?: RequestOptions): Promise<Record<string, unknown>>\n listTools(options?: RequestOptions): Promise<RemoteTool[]>\n listToolsResult(options?: RequestOptions): Promise<ToolsListResult>\n callTool(tool: RemoteTool, args: Record<string, unknown>, options?: CallToolOptions): Promise<CallToolResult>\n}\n\nexport function createRemoteClient(options: RemoteClientOptions): RemoteClient {\n const doFetch = options.fetch ?? fetch\n const clientInfo = options.clientInfo ?? { name: \"mext\", version: VERSION }\n let nextId = 1\n\n const request = async (\n method: string,\n params: Record<string, unknown> = {},\n opts: RequestOptions = {},\n extraHeaders: Record<string, string> = {},\n ): Promise<Record<string, unknown>> => {\n const id = nextId++\n const meta: Record<string, unknown> = {\n ...(isRecord(params._meta) ? params._meta : {}),\n [META_KEYS.protocolVersion]: PROTOCOL_VERSION,\n [META_KEYS.clientInfo]: clientInfo,\n [META_KEYS.clientCapabilities]: CLIENT_CAPABILITIES,\n }\n if (opts.progressToken !== undefined) meta.progressToken = opts.progressToken\n const body = { jsonrpc: \"2.0\", id, method, params: { ...params, _meta: meta } }\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"MCP-Protocol-Version\": PROTOCOL_VERSION,\n \"Mcp-Method\": method,\n ...extraHeaders,\n }\n const token = await options.token?.()\n if (token) headers.Authorization = `Bearer ${token}`\n\n let res: Response\n try {\n res = await doFetch(options.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(opts.signal ? { signal: opts.signal } : {}),\n })\n } catch (error) {\n if (opts.signal?.aborted) throw error\n throw new RemoteTransportError(`Cannot reach ${options.url}: ${errorMessage(error)}`, { cause: error })\n }\n\n const type = res.headers.get(\"content-type\") ?? \"\"\n if (res.status === 401) {\n const payload = await readJson(res)\n const err = isRecord(payload) && isRecord(payload.error) ? payload.error : {}\n throw new RemoteUnauthorizedError(\n typeof err.message === \"string\" ? err.message : \"Authentication required.\",\n parseBearerChallenge(res.headers.get(\"www-authenticate\")),\n err.data,\n )\n }\n if (type.includes(\"text/event-stream\")) {\n return handleMessage(await readSse(res, id, opts), id, res.status)\n }\n const payload = await readJson(res)\n if (payload === undefined) {\n throw new RemoteTransportError(`${options.url} returned HTTP ${res.status} without a JSON-RPC response.`)\n }\n return handleMessage(payload, id, res.status)\n }\n\n const handleMessage = (message: unknown, id: number, status: number): Record<string, unknown> => {\n if (!isRecord(message)) throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n if (isRecord(message.error)) {\n const e = message.error\n throw new RemoteRpcError(\n typeof e.message === \"string\" ? e.message : \"JSON-RPC error\",\n typeof e.code === \"number\" ? e.code : -32_603,\n e.data,\n status,\n )\n }\n if (message.id !== id || !isRecord(message.result)) {\n throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n }\n return message.result\n }\n\n const listToolsResult = async (opts: RequestOptions = {}): Promise<ToolsListResult> => {\n const tools: RemoteTool[] = []\n const out: ToolsListResult = { tools }\n let cursor: string | undefined\n for (let page = 0; page < 100; page++) {\n const result = await request(\"tools/list\", cursor === undefined ? {} : { cursor }, opts)\n if (page === 0) {\n if (typeof result.ttlMs === \"number\" && Number.isFinite(result.ttlMs) && result.ttlMs >= 0) out.ttlMs = result.ttlMs\n if (typeof result.cacheScope === \"string\") out.cacheScope = result.cacheScope\n }\n if (Array.isArray(result.tools)) {\n for (const t of result.tools) if (isRecord(t) && typeof t.name === \"string\") tools.push(t as unknown as RemoteTool)\n }\n if (typeof result.nextCursor !== \"string\" || result.nextCursor === \"\") break\n cursor = result.nextCursor\n }\n return out\n }\n\n const callTool = async (\n tool: RemoteTool,\n args: Record<string, unknown>,\n opts: CallToolOptions = {},\n ): Promise<CallToolResult> => {\n const headers: Record<string, string> = { \"Mcp-Name\": tool.name, ...paramHeaders(tool, args) }\n let retry: { inputResponses?: InputResponses; requestState?: string } = {}\n for (let round = 0; ; round++) {\n const result = await request(\"tools/call\", { name: tool.name, arguments: args, ...retry }, opts, headers)\n if (result.resultType !== \"input_required\") return result as CallToolResult\n const required: InputRequired = {}\n if (isRecord(result.inputRequests)) required.inputRequests = result.inputRequests as InputRequired[\"inputRequests\"]\n if (typeof result.requestState === \"string\") required.requestState = result.requestState\n if (!opts.onInputRequired) throw new RemoteInputRequiredError(`${tool.name} requires input.`, required)\n if (round >= MAX_INPUT_ROUNDS) {\n throw new RemoteInputRequiredError(`${tool.name} still required input after ${MAX_INPUT_ROUNDS} rounds.`, required)\n }\n // 요청이 있으면 응답을 만든 뒤 재시도. requestState 는 그대로 되돌려 보내고, 없으면 보내지 않는다\n const responses = required.inputRequests ? await opts.onInputRequired(required, round) : undefined\n retry = {}\n if (responses !== undefined) retry.inputResponses = responses\n if (required.requestState !== undefined) retry.requestState = required.requestState\n }\n }\n\n return {\n url: options.url,\n request: (method, params, opts) => request(method, params, opts),\n listTools: async (opts) => (await listToolsResult(opts)).tools,\n listToolsResult,\n callTool,\n }\n}\n\n/** inputSchema 의 x-mcp-header 속성 → Mcp-Param-<Name> 헤더 (SEP-2243). 문자열 · 숫자 · boolean 값만 */\nfunction paramHeaders(tool: RemoteTool, args: Record<string, unknown>): Record<string, string> {\n const props = tool.inputSchema?.properties\n if (!isRecord(props)) return {}\n const out: Record<string, string> = {}\n for (const [key, schema] of Object.entries(props)) {\n if (!isRecord(schema) || typeof schema[\"x-mcp-header\"] !== \"string\") continue\n const value = args[key]\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n out[`Mcp-Param-${schema[\"x-mcp-header\"]}`] = String(value)\n }\n }\n return out\n}\n\n/* SSE */\n\n/** 응답 스트림에서 id 의 응답 메시지가 올 때까지 읽는다. 알림은 콜백, 응답 후 스트림을 닫는다 */\nasync function readSse(res: Response, id: number, opts: RequestOptions): Promise<unknown> {\n if (!res.body) throw new RemoteTransportError(\"Empty event stream.\")\n const reader = res.body.pipeThrough(new TextDecoderStream()).getReader()\n let buffer = \"\"\n let data: string[] = []\n const dispatch = (): unknown => {\n if (data.length === 0) return undefined\n const text = data.join(\"\\n\")\n data = []\n let message: unknown\n try {\n message = JSON.parse(text)\n } catch {\n return undefined\n }\n if (!isRecord(message)) return undefined\n if (typeof message.method === \"string\" && message.id === undefined) {\n try {\n opts.onNotification?.(message.method, isRecord(message.params) ? message.params : {})\n } catch {\n // 표시 오류는 응답에 영향 없음\n }\n return undefined\n }\n if (message.id === id && (\"result\" in message || \"error\" in message)) return message\n return undefined\n }\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += value\n let nl: number\n while ((nl = buffer.search(/\\r\\n|\\r|\\n/)) >= 0) {\n const line = buffer.slice(0, nl)\n buffer = buffer.slice(nl + (buffer.startsWith(\"\\r\\n\", nl) ? 2 : 1))\n if (line === \"\") {\n const found = dispatch()\n if (found !== undefined) return found\n continue\n }\n if (line.startsWith(\":\")) continue\n const colon = line.indexOf(\":\")\n const field = colon < 0 ? line : line.slice(0, colon)\n let value = colon < 0 ? \"\" : line.slice(colon + 1)\n if (value.startsWith(\" \")) value = value.slice(1)\n if (field === \"data\") data.push(value)\n }\n }\n const found = dispatch()\n if (found !== undefined) return found\n } finally {\n await reader.cancel().catch(() => {})\n }\n if (opts.signal?.aborted) throw opts.signal.reason\n throw new RemoteTransportError(\"Event stream ended without a response.\")\n}\n\nasync function readJson(res: Response): Promise<unknown> {\n const text = await res.text().catch(() => \"\")\n if (text === \"\") return undefined\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\n/* WWW-Authenticate */\n\nexport interface BearerChallenge {\n /** Bearer challenge 가 있었는지 */\n bearer: boolean\n error?: string\n scope?: string\n resourceMetadata?: string\n}\n\n/** WWW-Authenticate 의 Bearer challenge 파라미터 (RFC 6750 · RFC 9728 resource_metadata) */\nexport function parseBearerChallenge(header: string | null): BearerChallenge {\n if (!header) return { bearer: false }\n const m = /(?:^|,\\s*)Bearer\\b(.*)$/i.exec(header)\n if (!m) return { bearer: false }\n const params: Record<string, string> = {}\n const re = /([A-Za-z_][\\w-]*)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g\n for (let p = re.exec(m[1]!); p !== null; p = re.exec(m[1]!)) {\n params[p[1]!.toLowerCase()] = p[2] !== undefined ? p[2].replace(/\\\\(.)/g, \"$1\") : p[3]!\n }\n const out: BearerChallenge = { bearer: true }\n if (params.error !== undefined) out.error = params.error\n if (params.scope !== undefined) out.scope = params.scope\n if (params.resource_metadata !== undefined) out.resourceMetadata = params.resource_metadata\n return out\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n const cause = (error as { cause?: unknown }).cause\n return cause instanceof Error && cause.message ? cause.message : error.message\n }\n return String(error)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/remote/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../version.ts\"\n\n/**\n * 원격 실행용 최소 MCP 클라이언트 (Streamable HTTP, 프로토콜 2026-07-28, stateless).\n * 요청마다 POST 1회: _meta envelope (버전 · clientInfo · clientCapabilities) + MCP-Protocol-Version · Mcp-Method ·\n * Mcp-Name · Mcp-Param-* 헤더. 응답 = application/json 또는 text/event-stream (progress 알림 → onNotification).\n * MRTR (InputRequiredResult) 재시도 루프는 callTool 의 onInputRequired 가 담당.\n * tasks 확장 (§12.6) 선언: tools/call 이 CreateTaskResult (resultType \"task\") 를 그대로 돌려주고, 폴링 · 답 · 취소 =\n * getTask · updateTask · cancelTask (Mcp-Name = taskId). 폴링 루프는 client/task.ts\n */\n\nexport const PROTOCOL_VERSION = \"2026-07-28\"\n\nexport const META_KEYS = {\n protocolVersion: \"io.modelcontextprotocol/protocolVersion\",\n clientInfo: \"io.modelcontextprotocol/clientInfo\",\n clientCapabilities: \"io.modelcontextprotocol/clientCapabilities\",\n} as const\n\n/** tasks 확장 ID (mcp/tasks.ts TASKS_EXTENSION 과 같은 값. 이 모듈은 서버 SDK 를 import 하지 않는다) */\nexport const TASKS_EXTENSION_ID = \"io.modelcontextprotocol/tasks\"\n\n/** 클라이언트가 처리하는 입력 요청 = elicitation form · url (sampling · roots 없음) + tasks 확장 (폴링 · 답 · 취소) */\nexport const CLIENT_CAPABILITIES = {\n elicitation: { form: {}, url: {} },\n extensions: { [TASKS_EXTENSION_ID]: {} },\n} as const\n\n/** MRTR 재시도 상한 (같은 요청의 input_required 연속 횟수) */\nexport const MAX_INPUT_ROUNDS = 8\n\nexport interface RemoteTool {\n name: string\n description?: string\n inputSchema?: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n annotations?: Record<string, unknown>\n _meta?: Record<string, unknown>\n}\n\nexport interface CallToolResult {\n content?: unknown[]\n structuredContent?: unknown\n isError?: boolean\n [key: string]: unknown\n}\n\n/** InputRequiredResult (resultType: input_required) */\nexport interface InputRequired {\n inputRequests?: Record<string, InputRequestObject>\n requestState?: string\n}\n\nexport interface InputRequestObject {\n method: string\n params?: Record<string, unknown>\n}\n\n/** 입력 요청 key → 응답 (ElicitResult 등). 이번 라운드 요청에 대한 것만 */\nexport type InputResponses = Record<string, unknown>\n\nexport interface RequestOptions {\n signal?: AbortSignal\n /** 서버 → 클라이언트 알림 (notifications/progress 등) */\n onNotification?: (method: string, params: Record<string, unknown>) => void\n /** _meta.progressToken. 있으면 서버가 SSE 로 응답 */\n progressToken?: string | number\n}\n\nexport interface CallToolOptions extends RequestOptions {\n /** input_required 응답 처리 → 이번 라운드의 inputResponses. 없으면 RemoteInputRequiredError */\n onInputRequired?: (request: InputRequired, round: number) => Promise<InputResponses>\n}\n\n/** HTTP 401. challenge = WWW-Authenticate 파싱 결과, data = JSON-RPC error.data (mext 는 UNAUTHENTICATED toJSON) */\nexport class RemoteUnauthorizedError extends Error {\n readonly challenge: BearerChallenge\n readonly data: unknown\n constructor(message: string, challenge: BearerChallenge, data: unknown) {\n super(message)\n this.name = \"RemoteUnauthorizedError\"\n this.challenge = challenge\n this.data = data\n }\n}\n\n/** JSON-RPC 오류 응답 (HTTP 400 · 403 · 500 포함) */\nexport class RemoteRpcError extends Error {\n readonly code: number\n readonly data: unknown\n readonly status: number\n constructor(message: string, code: number, data: unknown, status: number) {\n super(message)\n this.name = \"RemoteRpcError\"\n this.code = code\n this.data = data\n this.status = status\n }\n}\n\n/** 연결 실패 · JSON-RPC 가 아닌 응답 */\nexport class RemoteTransportError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = \"RemoteTransportError\"\n }\n}\n\n/** onInputRequired 없이 input_required 를 받음 · 라운드 상한 초과 */\nexport class RemoteInputRequiredError extends Error {\n readonly request: InputRequired\n constructor(message: string, request: InputRequired) {\n super(message)\n this.name = \"RemoteInputRequiredError\"\n this.request = request\n }\n}\n\nexport interface RemoteClientOptions {\n /** MCP 엔드포인트 (http(s)://host/mcp) */\n url: string\n /** 요청마다 호출. 없으면 Authorization 헤더 없음 */\n token?: () => string | undefined | Promise<string | undefined>\n fetch?: typeof fetch\n clientInfo?: { name: string; version: string }\n}\n\n/** tools/list 전체 페이지 + 첫 페이지의 캐시 힌트 (2026-07-28 ttlMs · cacheScope) */\nexport interface ToolsListResult {\n tools: RemoteTool[]\n ttlMs?: number\n cacheScope?: string\n}\n\nexport interface RemoteClient {\n readonly url: string\n request(method: string, params?: Record<string, unknown>, options?: RequestOptions): Promise<Record<string, unknown>>\n listTools(options?: RequestOptions): Promise<RemoteTool[]>\n listToolsResult(options?: RequestOptions): Promise<ToolsListResult>\n callTool(tool: RemoteTool, args: Record<string, unknown>, options?: CallToolOptions): Promise<CallToolResult>\n /** tasks/get (Mcp-Name = taskId) */\n getTask(taskId: string, options?: RequestOptions): Promise<Record<string, unknown>>\n /** tasks/update { taskId, inputResponses } */\n updateTask(taskId: string, inputResponses: InputResponses, options?: RequestOptions): Promise<void>\n /** tasks/cancel { taskId } */\n cancelTask(taskId: string, options?: RequestOptions): Promise<void>\n}\n\nexport function createRemoteClient(options: RemoteClientOptions): RemoteClient {\n const doFetch = options.fetch ?? fetch\n const clientInfo = options.clientInfo ?? { name: \"mext\", version: VERSION }\n let nextId = 1\n\n const request = async (\n method: string,\n params: Record<string, unknown> = {},\n opts: RequestOptions = {},\n extraHeaders: Record<string, string> = {},\n ): Promise<Record<string, unknown>> => {\n const id = nextId++\n const meta: Record<string, unknown> = {\n ...(isRecord(params._meta) ? params._meta : {}),\n [META_KEYS.protocolVersion]: PROTOCOL_VERSION,\n [META_KEYS.clientInfo]: clientInfo,\n [META_KEYS.clientCapabilities]: CLIENT_CAPABILITIES,\n }\n if (opts.progressToken !== undefined) meta.progressToken = opts.progressToken\n const body = { jsonrpc: \"2.0\", id, method, params: { ...params, _meta: meta } }\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"MCP-Protocol-Version\": PROTOCOL_VERSION,\n \"Mcp-Method\": method,\n ...extraHeaders,\n }\n const token = await options.token?.()\n if (token) headers.Authorization = `Bearer ${token}`\n\n let res: Response\n try {\n res = await doFetch(options.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(opts.signal ? { signal: opts.signal } : {}),\n })\n } catch (error) {\n if (opts.signal?.aborted) throw error\n throw new RemoteTransportError(`Cannot reach ${options.url}: ${errorMessage(error)}`, { cause: error })\n }\n\n const type = res.headers.get(\"content-type\") ?? \"\"\n if (res.status === 401) {\n const payload = await readJson(res)\n const err = isRecord(payload) && isRecord(payload.error) ? payload.error : {}\n throw new RemoteUnauthorizedError(\n typeof err.message === \"string\" ? err.message : \"Authentication required.\",\n parseBearerChallenge(res.headers.get(\"www-authenticate\")),\n err.data,\n )\n }\n if (type.includes(\"text/event-stream\")) {\n return handleMessage(await readSse(res, id, opts), id, res.status)\n }\n const payload = await readJson(res)\n if (payload === undefined) {\n throw new RemoteTransportError(`${options.url} returned HTTP ${res.status} without a JSON-RPC response.`)\n }\n return handleMessage(payload, id, res.status)\n }\n\n const handleMessage = (message: unknown, id: number, status: number): Record<string, unknown> => {\n if (!isRecord(message)) throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n if (isRecord(message.error)) {\n const e = message.error\n throw new RemoteRpcError(\n typeof e.message === \"string\" ? e.message : \"JSON-RPC error\",\n typeof e.code === \"number\" ? e.code : -32_603,\n e.data,\n status,\n )\n }\n if (message.id !== id || !isRecord(message.result)) {\n throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n }\n return message.result\n }\n\n const listToolsResult = async (opts: RequestOptions = {}): Promise<ToolsListResult> => {\n const tools: RemoteTool[] = []\n const out: ToolsListResult = { tools }\n let cursor: string | undefined\n for (let page = 0; page < 100; page++) {\n const result = await request(\"tools/list\", cursor === undefined ? {} : { cursor }, opts)\n if (page === 0) {\n if (typeof result.ttlMs === \"number\" && Number.isFinite(result.ttlMs) && result.ttlMs >= 0) out.ttlMs = result.ttlMs\n if (typeof result.cacheScope === \"string\") out.cacheScope = result.cacheScope\n }\n if (Array.isArray(result.tools)) {\n for (const t of result.tools) if (isRecord(t) && typeof t.name === \"string\") tools.push(t as unknown as RemoteTool)\n }\n if (typeof result.nextCursor !== \"string\" || result.nextCursor === \"\") break\n cursor = result.nextCursor\n }\n return out\n }\n\n const callTool = async (\n tool: RemoteTool,\n args: Record<string, unknown>,\n opts: CallToolOptions = {},\n ): Promise<CallToolResult> => {\n const headers: Record<string, string> = { \"Mcp-Name\": tool.name, ...paramHeaders(tool, args) }\n let retry: { inputResponses?: InputResponses; requestState?: string } = {}\n for (let round = 0; ; round++) {\n const result = await request(\"tools/call\", { name: tool.name, arguments: args, ...retry }, opts, headers)\n if (result.resultType !== \"input_required\") return result as CallToolResult\n const required: InputRequired = {}\n if (isRecord(result.inputRequests)) required.inputRequests = result.inputRequests as InputRequired[\"inputRequests\"]\n if (typeof result.requestState === \"string\") required.requestState = result.requestState\n if (!opts.onInputRequired) throw new RemoteInputRequiredError(`${tool.name} requires input.`, required)\n if (round >= MAX_INPUT_ROUNDS) {\n throw new RemoteInputRequiredError(`${tool.name} still required input after ${MAX_INPUT_ROUNDS} rounds.`, required)\n }\n // 요청이 있으면 응답을 만든 뒤 재시도. requestState 는 그대로 되돌려 보내고, 없으면 보내지 않는다\n const responses = required.inputRequests ? await opts.onInputRequired(required, round) : undefined\n retry = {}\n if (responses !== undefined) retry.inputResponses = responses\n if (required.requestState !== undefined) retry.requestState = required.requestState\n }\n }\n\n /** tasks/* = Mcp-Name 헤더 = taskId (SDK 검증, 없으면 400) */\n const taskRequest = (method: string, taskId: string, params: Record<string, unknown>, opts: RequestOptions = {}) =>\n request(method, { taskId, ...params }, opts, { \"Mcp-Name\": taskId })\n\n return {\n url: options.url,\n request: (method, params, opts) => request(method, params, opts),\n listTools: async (opts) => (await listToolsResult(opts)).tools,\n listToolsResult,\n callTool,\n getTask: (taskId, opts) => taskRequest(\"tasks/get\", taskId, {}, opts),\n updateTask: async (taskId, inputResponses, opts) => {\n await taskRequest(\"tasks/update\", taskId, { inputResponses }, opts)\n },\n cancelTask: async (taskId, opts) => {\n await taskRequest(\"tasks/cancel\", taskId, {}, opts)\n },\n }\n}\n\n/** inputSchema 의 x-mcp-header 속성 → Mcp-Param-<Name> 헤더 (SEP-2243). 문자열 · 숫자 · boolean 값만 */\nfunction paramHeaders(tool: RemoteTool, args: Record<string, unknown>): Record<string, string> {\n const props = tool.inputSchema?.properties\n if (!isRecord(props)) return {}\n const out: Record<string, string> = {}\n for (const [key, schema] of Object.entries(props)) {\n if (!isRecord(schema) || typeof schema[\"x-mcp-header\"] !== \"string\") continue\n const value = args[key]\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n out[`Mcp-Param-${schema[\"x-mcp-header\"]}`] = String(value)\n }\n }\n return out\n}\n\n/* SSE */\n\n/** 응답 스트림에서 id 의 응답 메시지가 올 때까지 읽는다. 알림은 콜백, 응답 후 스트림을 닫는다 */\nasync function readSse(res: Response, id: number, opts: RequestOptions): Promise<unknown> {\n if (!res.body) throw new RemoteTransportError(\"Empty event stream.\")\n const reader = res.body.pipeThrough(new TextDecoderStream()).getReader()\n let buffer = \"\"\n let data: string[] = []\n const dispatch = (): unknown => {\n if (data.length === 0) return undefined\n const text = data.join(\"\\n\")\n data = []\n let message: unknown\n try {\n message = JSON.parse(text)\n } catch {\n return undefined\n }\n if (!isRecord(message)) return undefined\n if (typeof message.method === \"string\" && message.id === undefined) {\n try {\n opts.onNotification?.(message.method, isRecord(message.params) ? message.params : {})\n } catch {\n // 표시 오류는 응답에 영향 없음\n }\n return undefined\n }\n if (message.id === id && (\"result\" in message || \"error\" in message)) return message\n return undefined\n }\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += value\n let nl: number\n while ((nl = buffer.search(/\\r\\n|\\r|\\n/)) >= 0) {\n const line = buffer.slice(0, nl)\n buffer = buffer.slice(nl + (buffer.startsWith(\"\\r\\n\", nl) ? 2 : 1))\n if (line === \"\") {\n const found = dispatch()\n if (found !== undefined) return found\n continue\n }\n if (line.startsWith(\":\")) continue\n const colon = line.indexOf(\":\")\n const field = colon < 0 ? line : line.slice(0, colon)\n let value = colon < 0 ? \"\" : line.slice(colon + 1)\n if (value.startsWith(\" \")) value = value.slice(1)\n if (field === \"data\") data.push(value)\n }\n }\n const found = dispatch()\n if (found !== undefined) return found\n } finally {\n await reader.cancel().catch(() => {})\n }\n if (opts.signal?.aborted) throw opts.signal.reason\n throw new RemoteTransportError(\"Event stream ended without a response.\")\n}\n\nasync function readJson(res: Response): Promise<unknown> {\n const text = await res.text().catch(() => \"\")\n if (text === \"\") return undefined\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\n/* WWW-Authenticate */\n\nexport interface BearerChallenge {\n /** Bearer challenge 가 있었는지 */\n bearer: boolean\n error?: string\n scope?: string\n resourceMetadata?: string\n}\n\n/** WWW-Authenticate 의 Bearer challenge 파라미터 (RFC 6750 · RFC 9728 resource_metadata) */\nexport function parseBearerChallenge(header: string | null): BearerChallenge {\n if (!header) return { bearer: false }\n const m = /(?:^|,\\s*)Bearer\\b(.*)$/i.exec(header)\n if (!m) return { bearer: false }\n const params: Record<string, string> = {}\n const re = /([A-Za-z_][\\w-]*)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g\n for (let p = re.exec(m[1]!); p !== null; p = re.exec(m[1]!)) {\n params[p[1]!.toLowerCase()] = p[2] !== undefined ? p[2].replace(/\\\\(.)/g, \"$1\") : p[3]!\n }\n const out: BearerChallenge = { bearer: true }\n if (params.error !== undefined) out.error = params.error\n if (params.scope !== undefined) out.scope = params.scope\n if (params.resource_metadata !== undefined) out.resourceMetadata = params.resource_metadata\n return out\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n const cause = (error as { cause?: unknown }).cause\n return cause instanceof Error && cause.message ? cause.message : error.message\n }\n return String(error)\n}\n"]}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { MextApp } from "./command.ts";
|
|
2
|
+
import { type BuildIssue } from "./errors.ts";
|
|
3
|
+
import type { Principal } from "./principal.ts";
|
|
4
|
+
/**
|
|
5
|
+
* MCP 자원 (§12.3). resources/**\/*.ts 파일 하나 = defineResource 하나. 식별자 = uri (고정 URI 또는 RFC 6570 level 1 템플릿).
|
|
6
|
+
* MCP 전용 (CLI 노출 없음). 실행 어댑터 = mcp/resources.ts
|
|
7
|
+
*/
|
|
8
|
+
/** read · list 의 ctx. ask · progress 없음 */
|
|
9
|
+
export interface ResourceContext {
|
|
10
|
+
principal: Principal;
|
|
11
|
+
signal: AbortSignal;
|
|
12
|
+
app: MextApp;
|
|
13
|
+
}
|
|
14
|
+
/** complete 의 ctx. arguments = 이미 정한 다른 템플릿 변수 */
|
|
15
|
+
export interface ResourceCompleteContext extends ResourceContext {
|
|
16
|
+
arguments: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
/** completion/complete 후보 (§12.3 completion) */
|
|
19
|
+
export type ResourceCompleter = (value: string, ctx: ResourceCompleteContext) => readonly string[] | Promise<readonly string[]>;
|
|
20
|
+
/** list 결과 항목 (resources/list 의 Resource). title · description · mimeType 생략 = 자원 정의의 값 */
|
|
21
|
+
export interface ResourceListItem {
|
|
22
|
+
uri: string;
|
|
23
|
+
name: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
mimeType?: string;
|
|
27
|
+
size?: number;
|
|
28
|
+
}
|
|
29
|
+
type TemplateVariable<S extends string> = S extends `${string}{${infer V}}${infer Rest}` ? V | TemplateVariable<Rest> : never;
|
|
30
|
+
/** 템플릿 변수 → 값 (고정 URI = {}) */
|
|
31
|
+
export type ResourceVariables<U extends string> = string extends U ? Record<string, string> : {
|
|
32
|
+
[K in TemplateVariable<U>]: string;
|
|
33
|
+
};
|
|
34
|
+
export interface ResourceDefinition<U extends string> {
|
|
35
|
+
/** 고정 URI 또는 RFC 6570 level 1 템플릿 ({var}) */
|
|
36
|
+
uri: U;
|
|
37
|
+
title?: string;
|
|
38
|
+
/** 필수. resources/list · templates/list 설명 */
|
|
39
|
+
description: string;
|
|
40
|
+
/** read 반환이 string · Uint8Array 일 때의 mimeType. 그 외 (JSON) 기본 application/json */
|
|
41
|
+
mimeType?: string;
|
|
42
|
+
/** 읽기에 필요한 scopes. 전부 보유해야 목록 · 읽기 */
|
|
43
|
+
scopes?: readonly string[];
|
|
44
|
+
/** resourceSubscriptions 대상 (§12.5) */
|
|
45
|
+
subscribe?: boolean;
|
|
46
|
+
/** 템플릿 전용. 구체 URI 목록 → resources/list */
|
|
47
|
+
list?: (ctx: ResourceContext) => readonly ResourceListItem[] | Promise<readonly ResourceListItem[]>;
|
|
48
|
+
/** 템플릿 전용. 변수별 completion/complete */
|
|
49
|
+
complete?: {
|
|
50
|
+
[K in TemplateVariable<U>]?: ResourceCompleter;
|
|
51
|
+
};
|
|
52
|
+
/** string = text · Uint8Array = blob · 그 외 = JSON text */
|
|
53
|
+
read(variables: ResourceVariables<U>, ctx: ResourceContext): unknown;
|
|
54
|
+
}
|
|
55
|
+
export declare const RESOURCE: unique symbol;
|
|
56
|
+
export interface Resource<U extends string = string> {
|
|
57
|
+
readonly [RESOURCE]: true;
|
|
58
|
+
readonly uri: U;
|
|
59
|
+
readonly title: string | undefined;
|
|
60
|
+
readonly description: string;
|
|
61
|
+
readonly mimeType: string | undefined;
|
|
62
|
+
readonly scopes: readonly string[];
|
|
63
|
+
readonly subscribe: boolean;
|
|
64
|
+
readonly list: ((ctx: ResourceContext) => readonly ResourceListItem[] | Promise<readonly ResourceListItem[]>) | undefined;
|
|
65
|
+
readonly complete: Readonly<Record<string, ResourceCompleter>>;
|
|
66
|
+
read(variables: ResourceVariables<U>, ctx: ResourceContext): unknown;
|
|
67
|
+
}
|
|
68
|
+
export declare function defineResource<const U extends string>(definition: ResourceDefinition<U>): Resource<U>;
|
|
69
|
+
export declare function isResource(value: unknown): value is Resource;
|
|
70
|
+
export interface UriTemplatePattern {
|
|
71
|
+
/** 등장 순 */
|
|
72
|
+
readonly variables: readonly string[];
|
|
73
|
+
/** 변수 밖 문자 수 (매칭 우선순위) */
|
|
74
|
+
readonly literalLength: number;
|
|
75
|
+
/** 변수 이름을 지운 형태 ("users://{}/profile"). 같으면 같은 템플릿 (중복) */
|
|
76
|
+
readonly key: string;
|
|
77
|
+
/** 매칭 = 변수 값 (percent-decode), 아니면 undefined. 변수 = 비어 있지 않은 "/" 없는 문자열 */
|
|
78
|
+
match(uri: string): Record<string, string> | undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* uri 해석. 변수 없음 = undefined (고정 URI). 형식 오류 = TypeError
|
|
82
|
+
* (scheme 없음 · 공백 · 짝 없는 중괄호 · level 2+ 연산자 · 잘못된 변수 이름 · 같은 변수 반복 · 변수 연속)
|
|
83
|
+
*/
|
|
84
|
+
export declare function parseUriTemplate(uri: string): UriTemplatePattern | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* 등록된 자원의 메타데이터 + 모듈 로더. eager (스캔) = load 가 정의 그대로, lazy (mext start) = 모듈 import (1회 캐시)
|
|
87
|
+
*/
|
|
88
|
+
export interface RegisteredResource {
|
|
89
|
+
/** 고정 URI 또는 템플릿 원문 */
|
|
90
|
+
uri: string;
|
|
91
|
+
/** 템플릿이면 해석 결과 */
|
|
92
|
+
template: UriTemplatePattern | undefined;
|
|
93
|
+
title: string | undefined;
|
|
94
|
+
description: string;
|
|
95
|
+
mimeType: string | undefined;
|
|
96
|
+
scopes: readonly string[];
|
|
97
|
+
subscribe: boolean;
|
|
98
|
+
/** list 정의 여부 */
|
|
99
|
+
list: boolean;
|
|
100
|
+
/** complete 를 정의한 변수 (정렬) */
|
|
101
|
+
complete: readonly string[];
|
|
102
|
+
/** resourcesDir 기준 상대 경로 (posix) */
|
|
103
|
+
file: string | undefined;
|
|
104
|
+
load(): Promise<Resource>;
|
|
105
|
+
}
|
|
106
|
+
export interface ResourceSet {
|
|
107
|
+
/** 고정 URI → 자원. uri 순 */
|
|
108
|
+
readonly fixed: ReadonlyMap<string, RegisteredResource>;
|
|
109
|
+
/** 템플릿 자원. 매칭 순 (리터럴 문자 수 많은 순, 같으면 파일 경로 순) */
|
|
110
|
+
readonly templates: readonly RegisteredResource[];
|
|
111
|
+
}
|
|
112
|
+
/** manifest 의 자원 (mext build). module 은 BuildManifestResource */
|
|
113
|
+
export interface ManifestResource {
|
|
114
|
+
uri: string;
|
|
115
|
+
title?: string;
|
|
116
|
+
description: string;
|
|
117
|
+
mimeType?: string;
|
|
118
|
+
scopes: string[];
|
|
119
|
+
subscribe: boolean;
|
|
120
|
+
list: boolean;
|
|
121
|
+
complete: string[];
|
|
122
|
+
/** resourcesDir 기준 상대 경로 (posix) */
|
|
123
|
+
file?: string;
|
|
124
|
+
}
|
|
125
|
+
export interface ResourceInput {
|
|
126
|
+
resource: Resource;
|
|
127
|
+
/** resourcesDir 기준 상대 경로 (posix). 스캔 결과에만 있음 */
|
|
128
|
+
file?: string;
|
|
129
|
+
}
|
|
130
|
+
export interface LazyResourceInput extends ManifestResource {
|
|
131
|
+
/** 읽을 때 1회 호출 (결과 캐시, 실패는 다음 호출에서 재시도) */
|
|
132
|
+
load: () => Promise<Resource>;
|
|
133
|
+
}
|
|
134
|
+
/** 자원 목록 → ResourceSet. 중복 uri · 템플릿 = MextBuildError */
|
|
135
|
+
export declare function createResourceSet(inputs: readonly ResourceInput[]): ResourceSet;
|
|
136
|
+
/**
|
|
137
|
+
* createResourceSet 의 수집형 (mext build). 던지지 않는다. resources = 규칙을 통과한 자원만.
|
|
138
|
+
* label = issue 의 file 접두 (resourcesDir 이름, "resources/users/profile.ts")
|
|
139
|
+
*/
|
|
140
|
+
export declare function collectResourceSet(inputs: readonly ResourceInput[], label?: string): {
|
|
141
|
+
resources: ResourceSet;
|
|
142
|
+
issues: BuildIssue[];
|
|
143
|
+
};
|
|
144
|
+
/** manifest (mext build 산출) → ResourceSet. 모듈은 읽을 때 import */
|
|
145
|
+
export declare function createLazyResourceSet(inputs: readonly LazyResourceInput[]): ResourceSet;
|
|
146
|
+
/** 자원 메타데이터 (manifest) */
|
|
147
|
+
export declare function describeResource(entry: RegisteredResource): ManifestResource;
|
|
148
|
+
/** 모든 자원 (고정 → 템플릿 매칭 순) */
|
|
149
|
+
export declare function resourceEntries(set: ResourceSet): RegisteredResource[];
|
|
150
|
+
/** read 매칭: 고정 URI 우선, 다음 템플릿 (매칭 순). 없으면 undefined */
|
|
151
|
+
export declare function matchResource(set: ResourceSet, uri: string): {
|
|
152
|
+
entry: RegisteredResource;
|
|
153
|
+
variables: Record<string, string>;
|
|
154
|
+
} | undefined;
|
|
155
|
+
/**
|
|
156
|
+
* resources/ 스캔 (수집형, mext build). 폴더 없음 = 자원 없음 (issue 아님).
|
|
157
|
+
* 파일 규칙 = §3 의 private · 제외 · kebab-case. 각 파일의 default export = defineResource
|
|
158
|
+
*/
|
|
159
|
+
export declare function collectResources(dir: string): Promise<{
|
|
160
|
+
inputs: ResourceInput[];
|
|
161
|
+
issues: BuildIssue[];
|
|
162
|
+
}>;
|
|
163
|
+
/** Registry 에 자원 집합 연결 (없으면 그대로) */
|
|
164
|
+
export declare function withResources<R extends object>(registry: R, resources: ResourceSet | undefined): R & {
|
|
165
|
+
resources?: ResourceSet;
|
|
166
|
+
};
|
|
167
|
+
/** 개발 모드 런타임 스캔: resources/ → ResourceSet. 폴더 없음 · 자원 없음 = undefined (기능 없음). 규칙 위반 = MextBuildError */
|
|
168
|
+
export declare function loadResourceSet(dir: string): Promise<ResourceSet | undefined>;
|
|
169
|
+
export {};
|
package/dist/resource.js
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { MextBuildError } from "./errors.js";
|
|
3
|
+
import { importModuleDefaults, walkModuleFiles } from "./module-files.js";
|
|
4
|
+
export const RESOURCE = Symbol.for("@obov/mext/resource");
|
|
5
|
+
export function defineResource(definition) {
|
|
6
|
+
const d = definition;
|
|
7
|
+
const fail = (message) => {
|
|
8
|
+
throw new TypeError(`defineResource: ${message}`);
|
|
9
|
+
};
|
|
10
|
+
if (typeof d.uri !== "string")
|
|
11
|
+
fail("uri must be a string");
|
|
12
|
+
let template;
|
|
13
|
+
try {
|
|
14
|
+
template = parseUriTemplate(d.uri);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
fail(error.message);
|
|
18
|
+
}
|
|
19
|
+
if (typeof d.description !== "string" || d.description.trim() === "")
|
|
20
|
+
fail("description must be a non-empty string");
|
|
21
|
+
if (typeof d.read !== "function")
|
|
22
|
+
fail("read must be a function");
|
|
23
|
+
if (d.title !== undefined && typeof d.title !== "string")
|
|
24
|
+
fail("title must be a string");
|
|
25
|
+
if (d.mimeType !== undefined && (typeof d.mimeType !== "string" || d.mimeType === ""))
|
|
26
|
+
fail("mimeType must be a non-empty string");
|
|
27
|
+
if (d.scopes !== undefined && (!Array.isArray(d.scopes) || d.scopes.some((s) => typeof s !== "string"))) {
|
|
28
|
+
fail("scopes must be an array of strings");
|
|
29
|
+
}
|
|
30
|
+
if (d.subscribe !== undefined && typeof d.subscribe !== "boolean")
|
|
31
|
+
fail("subscribe must be a boolean");
|
|
32
|
+
if (d.list !== undefined) {
|
|
33
|
+
if (typeof d.list !== "function")
|
|
34
|
+
fail("list must be a function");
|
|
35
|
+
if (!template)
|
|
36
|
+
fail(`list applies to URI templates only (${d.uri} has no {variable})`);
|
|
37
|
+
}
|
|
38
|
+
const complete = {};
|
|
39
|
+
if (d.complete !== undefined) {
|
|
40
|
+
if (typeof d.complete !== "object" || d.complete === null || Array.isArray(d.complete))
|
|
41
|
+
fail("complete must be an object");
|
|
42
|
+
for (const [key, fn] of Object.entries(d.complete)) {
|
|
43
|
+
if (!template?.variables.includes(key))
|
|
44
|
+
fail(`complete.${key}: ${d.uri} has no {${key}} variable`);
|
|
45
|
+
if (typeof fn !== "function")
|
|
46
|
+
fail(`complete.${key} must be a function`);
|
|
47
|
+
complete[key] = fn;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const read = d.read;
|
|
51
|
+
const list = d.list;
|
|
52
|
+
return Object.freeze({
|
|
53
|
+
[RESOURCE]: true,
|
|
54
|
+
uri: d.uri,
|
|
55
|
+
title: d.title,
|
|
56
|
+
description: d.description,
|
|
57
|
+
mimeType: d.mimeType,
|
|
58
|
+
scopes: Object.freeze([...(d.scopes ?? [])]),
|
|
59
|
+
subscribe: d.subscribe === true,
|
|
60
|
+
list: list ? (ctx) => list.call(definition, ctx) : undefined,
|
|
61
|
+
complete: Object.freeze(complete),
|
|
62
|
+
read(variables, ctx) {
|
|
63
|
+
return read.call(definition, variables, ctx);
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export function isResource(value) {
|
|
68
|
+
return typeof value === "object" && value !== null && value[RESOURCE] === true;
|
|
69
|
+
}
|
|
70
|
+
const SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:/;
|
|
71
|
+
const VARNAME = /^[A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)*$/;
|
|
72
|
+
/**
|
|
73
|
+
* uri 해석. 변수 없음 = undefined (고정 URI). 형식 오류 = TypeError
|
|
74
|
+
* (scheme 없음 · 공백 · 짝 없는 중괄호 · level 2+ 연산자 · 잘못된 변수 이름 · 같은 변수 반복 · 변수 연속)
|
|
75
|
+
*/
|
|
76
|
+
export function parseUriTemplate(uri) {
|
|
77
|
+
if (!SCHEME.test(uri))
|
|
78
|
+
throw new TypeError(`uri must be an absolute URI with a scheme (got ${JSON.stringify(uri)})`);
|
|
79
|
+
if (/\s/.test(uri))
|
|
80
|
+
throw new TypeError(`uri must not contain whitespace (got ${JSON.stringify(uri)})`);
|
|
81
|
+
const literals = [];
|
|
82
|
+
const variables = [];
|
|
83
|
+
let rest = uri;
|
|
84
|
+
for (;;) {
|
|
85
|
+
const open = rest.indexOf("{");
|
|
86
|
+
const close = rest.indexOf("}");
|
|
87
|
+
if (open < 0) {
|
|
88
|
+
if (close >= 0)
|
|
89
|
+
throw new TypeError(`unmatched "}" in ${uri}`);
|
|
90
|
+
literals.push(rest);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
if (close >= 0 && close < open)
|
|
94
|
+
throw new TypeError(`unmatched "}" in ${uri}`);
|
|
95
|
+
const end = rest.indexOf("}", open);
|
|
96
|
+
if (end < 0)
|
|
97
|
+
throw new TypeError(`unmatched "{" in ${uri}`);
|
|
98
|
+
const name = rest.slice(open + 1, end);
|
|
99
|
+
if (name !== "" && "+#./;?&=,!@|".includes(name[0])) {
|
|
100
|
+
throw new TypeError(`${uri}: only RFC 6570 level 1 templates ({var}) are supported (got {${name}})`);
|
|
101
|
+
}
|
|
102
|
+
if (!VARNAME.test(name))
|
|
103
|
+
throw new TypeError(`${uri}: invalid variable name {${name}}`);
|
|
104
|
+
if (variables.includes(name))
|
|
105
|
+
throw new TypeError(`${uri}: variable {${name}} appears more than once`);
|
|
106
|
+
const literal = rest.slice(0, open);
|
|
107
|
+
if (variables.length > 0 && literal === "")
|
|
108
|
+
throw new TypeError(`${uri}: adjacent variables need a literal between them`);
|
|
109
|
+
literals.push(literal);
|
|
110
|
+
variables.push(name);
|
|
111
|
+
rest = rest.slice(end + 1);
|
|
112
|
+
}
|
|
113
|
+
if (variables.length === 0)
|
|
114
|
+
return undefined;
|
|
115
|
+
const pattern = new RegExp(`^${literals.map(escapeRegExp).join("([^/]+)")}$`);
|
|
116
|
+
return Object.freeze({
|
|
117
|
+
variables: Object.freeze(variables),
|
|
118
|
+
literalLength: literals.reduce((n, l) => n + l.length, 0),
|
|
119
|
+
key: literals.join("{}"),
|
|
120
|
+
match(candidate) {
|
|
121
|
+
const m = pattern.exec(candidate);
|
|
122
|
+
if (!m)
|
|
123
|
+
return undefined;
|
|
124
|
+
const values = {};
|
|
125
|
+
for (let i = 0; i < variables.length; i++) {
|
|
126
|
+
try {
|
|
127
|
+
values[variables[i]] = decodeURIComponent(m[i + 1]);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return values;
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function escapeRegExp(text) {
|
|
138
|
+
return text.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
|
|
139
|
+
}
|
|
140
|
+
/** 자원 목록 → ResourceSet. 중복 uri · 템플릿 = MextBuildError */
|
|
141
|
+
export function createResourceSet(inputs) {
|
|
142
|
+
const { resources, issues } = collectResourceSet(inputs);
|
|
143
|
+
if (issues.length > 0)
|
|
144
|
+
throw new MextBuildError(issues);
|
|
145
|
+
return resources;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* createResourceSet 의 수집형 (mext build). 던지지 않는다. resources = 규칙을 통과한 자원만.
|
|
149
|
+
* label = issue 의 file 접두 (resourcesDir 이름, "resources/users/profile.ts")
|
|
150
|
+
*/
|
|
151
|
+
export function collectResourceSet(inputs, label) {
|
|
152
|
+
const entries = [];
|
|
153
|
+
const issues = [];
|
|
154
|
+
for (const { resource, file } of inputs) {
|
|
155
|
+
if (!isResource(resource)) {
|
|
156
|
+
issues.push({ code: "INVALID_RESOURCE", message: "not a defineResource result", ...issueFile(file, label) });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
entries.push({
|
|
160
|
+
...metadata(describe(resource, file)),
|
|
161
|
+
load: () => Promise.resolve(resource),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return assemble(entries, issues, label);
|
|
165
|
+
}
|
|
166
|
+
/** manifest (mext build 산출) → ResourceSet. 모듈은 읽을 때 import */
|
|
167
|
+
export function createLazyResourceSet(inputs) {
|
|
168
|
+
const entries = inputs.map((input) => {
|
|
169
|
+
const load = input.load;
|
|
170
|
+
let pending;
|
|
171
|
+
return {
|
|
172
|
+
...metadata(input),
|
|
173
|
+
load: () => (pending ??= load().catch((error) => {
|
|
174
|
+
pending = undefined;
|
|
175
|
+
throw error;
|
|
176
|
+
})),
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
const { resources, issues } = assemble(entries, []);
|
|
180
|
+
if (issues.length > 0)
|
|
181
|
+
throw new MextBuildError(issues);
|
|
182
|
+
return resources;
|
|
183
|
+
}
|
|
184
|
+
/** 자원 메타데이터 (manifest) */
|
|
185
|
+
export function describeResource(entry) {
|
|
186
|
+
const out = {
|
|
187
|
+
uri: entry.uri,
|
|
188
|
+
description: entry.description,
|
|
189
|
+
scopes: [...entry.scopes],
|
|
190
|
+
subscribe: entry.subscribe,
|
|
191
|
+
list: entry.list,
|
|
192
|
+
complete: [...entry.complete],
|
|
193
|
+
};
|
|
194
|
+
if (entry.title !== undefined)
|
|
195
|
+
out.title = entry.title;
|
|
196
|
+
if (entry.mimeType !== undefined)
|
|
197
|
+
out.mimeType = entry.mimeType;
|
|
198
|
+
if (entry.file !== undefined)
|
|
199
|
+
out.file = entry.file;
|
|
200
|
+
return out;
|
|
201
|
+
}
|
|
202
|
+
/** 모든 자원 (고정 → 템플릿 매칭 순) */
|
|
203
|
+
export function resourceEntries(set) {
|
|
204
|
+
return [...set.fixed.values(), ...set.templates];
|
|
205
|
+
}
|
|
206
|
+
/** read 매칭: 고정 URI 우선, 다음 템플릿 (매칭 순). 없으면 undefined */
|
|
207
|
+
export function matchResource(set, uri) {
|
|
208
|
+
const fixed = set.fixed.get(uri);
|
|
209
|
+
if (fixed)
|
|
210
|
+
return { entry: fixed, variables: {} };
|
|
211
|
+
for (const entry of set.templates) {
|
|
212
|
+
const variables = entry.template.match(uri);
|
|
213
|
+
if (variables)
|
|
214
|
+
return { entry, variables };
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
function describe(resource, file) {
|
|
219
|
+
return {
|
|
220
|
+
uri: resource.uri,
|
|
221
|
+
...(resource.title !== undefined ? { title: resource.title } : {}),
|
|
222
|
+
description: resource.description,
|
|
223
|
+
...(resource.mimeType !== undefined ? { mimeType: resource.mimeType } : {}),
|
|
224
|
+
scopes: [...resource.scopes],
|
|
225
|
+
subscribe: resource.subscribe,
|
|
226
|
+
list: resource.list !== undefined,
|
|
227
|
+
complete: Object.keys(resource.complete).sort(),
|
|
228
|
+
...(file !== undefined ? { file } : {}),
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function metadata(m) {
|
|
232
|
+
return {
|
|
233
|
+
uri: m.uri,
|
|
234
|
+
template: parseUriTemplate(m.uri),
|
|
235
|
+
title: m.title,
|
|
236
|
+
description: m.description,
|
|
237
|
+
mimeType: m.mimeType,
|
|
238
|
+
scopes: Object.freeze([...m.scopes]),
|
|
239
|
+
subscribe: m.subscribe,
|
|
240
|
+
list: m.list,
|
|
241
|
+
complete: Object.freeze([...m.complete]),
|
|
242
|
+
file: m.file,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function assemble(entries, issues, label) {
|
|
246
|
+
const fixed = new Map();
|
|
247
|
+
const byKey = new Map();
|
|
248
|
+
const templates = [];
|
|
249
|
+
for (const entry of entries) {
|
|
250
|
+
const where = { id: entry.uri, ...issueFile(entry.file, label) };
|
|
251
|
+
const prev = entry.template ? byKey.get(entry.template.key) : fixed.get(entry.uri);
|
|
252
|
+
if (prev) {
|
|
253
|
+
const what = entry.template ? `URI template (same as ${prev.uri})` : "URI";
|
|
254
|
+
const other = prev.file === undefined ? prev.uri : (issueFile(prev.file, label).file ?? prev.file);
|
|
255
|
+
issues.push({ code: "DUPLICATE_ID", message: `duplicate resource ${what}, also ${other}`, ...where });
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (entry.template) {
|
|
259
|
+
byKey.set(entry.template.key, entry);
|
|
260
|
+
templates.push(entry);
|
|
261
|
+
}
|
|
262
|
+
else
|
|
263
|
+
fixed.set(entry.uri, entry);
|
|
264
|
+
}
|
|
265
|
+
templates.sort((a, b) => b.template.literalLength - a.template.literalLength || compare(a.file ?? a.uri, b.file ?? b.uri));
|
|
266
|
+
const sortedFixed = new Map([...fixed].sort(([a], [b]) => compare(a, b)));
|
|
267
|
+
return { resources: { fixed: sortedFixed, templates }, issues };
|
|
268
|
+
}
|
|
269
|
+
function issueFile(file, label) {
|
|
270
|
+
if (file === undefined)
|
|
271
|
+
return {};
|
|
272
|
+
return { file: label === undefined ? file : `${label}/${file}` };
|
|
273
|
+
}
|
|
274
|
+
function compare(a, b) {
|
|
275
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
276
|
+
}
|
|
277
|
+
/* ---------------------------------------------------------------- 스캔 (resources/) */
|
|
278
|
+
/**
|
|
279
|
+
* resources/ 스캔 (수집형, mext build). 폴더 없음 = 자원 없음 (issue 아님).
|
|
280
|
+
* 파일 규칙 = §3 의 private · 제외 · kebab-case. 각 파일의 default export = defineResource
|
|
281
|
+
*/
|
|
282
|
+
export async function collectResources(dir) {
|
|
283
|
+
const label = basename(dir);
|
|
284
|
+
const walked = walkModuleFiles(dir, label);
|
|
285
|
+
const { modules, issues } = await importModuleDefaults(dir, walked.files, label, isResource, "INVALID_RESOURCE", "defineResource");
|
|
286
|
+
return { inputs: modules.map(({ file, value }) => ({ resource: value, file })), issues: [...walked.issues, ...issues] };
|
|
287
|
+
}
|
|
288
|
+
/** Registry 에 자원 집합 연결 (없으면 그대로) */
|
|
289
|
+
export function withResources(registry, resources) {
|
|
290
|
+
return resources ? { ...registry, resources } : registry;
|
|
291
|
+
}
|
|
292
|
+
/** 개발 모드 런타임 스캔: resources/ → ResourceSet. 폴더 없음 · 자원 없음 = undefined (기능 없음). 규칙 위반 = MextBuildError */
|
|
293
|
+
export async function loadResourceSet(dir) {
|
|
294
|
+
const scanned = await collectResources(dir);
|
|
295
|
+
const { resources, issues } = collectResourceSet(scanned.inputs, basename(dir));
|
|
296
|
+
const all = [...scanned.issues, ...issues];
|
|
297
|
+
if (all.length > 0)
|
|
298
|
+
throw new MextBuildError(all);
|
|
299
|
+
return resources.fixed.size + resources.templates.length > 0 ? resources : undefined;
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=resource.js.map
|