@route-forge/core 0.1.1 → 0.3.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/index.cjs CHANGED
@@ -372,14 +372,12 @@ async function resolveAdapter(opts) {
372
372
  // src/forge.ts
373
373
  var DEFAULT_TIMEOUT = 3e4;
374
374
  var DEFAULT_CACHE_TTL = 3600;
375
- var DEFAULT_NAME_SEPARATOR = ".";
376
375
  function createRouteForge(options) {
377
376
  if (!options.endpoint) throw new TypeError("options.endpoint is required");
378
377
  const {
379
378
  adapter = "auto",
380
379
  timeout = DEFAULT_TIMEOUT,
381
380
  baseURL = "",
382
- nameSeparator = DEFAULT_NAME_SEPARATOR,
383
381
  auth,
384
382
  interceptors: declarativeInterceptors,
385
383
  cache: cacheOpts = {}
@@ -390,8 +388,8 @@ function createRouteForge(options) {
390
388
  const explicitEndpoint = options.endpoint;
391
389
  let effectiveLevels = explicitLevels ?? [];
392
390
  let effectiveEager = explicitEager ?? [];
393
- let effectiveStrict = explicitStrict;
394
391
  let effectiveEndpoint = explicitEndpoint;
392
+ let effectiveUrlPrefix = "";
395
393
  const summaryPromise = (async () => {
396
394
  try {
397
395
  const summaryUrl = explicitEndpoint;
@@ -423,11 +421,13 @@ function createRouteForge(options) {
423
421
  );
424
422
  effectiveEndpoint = summary.config.endpoint_prefix;
425
423
  }
424
+ if (summary.config.url_prefix) {
425
+ effectiveUrlPrefix = summary.config.url_prefix.endsWith("/") ? summary.config.url_prefix.slice(0, -1) : summary.config.url_prefix;
426
+ }
426
427
  if (summary.config.strict_mode && !explicitStrict) {
427
428
  console.warn(
428
429
  "[route-forge] backend strict_mode=true overrides frontend strict=false; forcing strict=true"
429
430
  );
430
- effectiveStrict = true;
431
431
  }
432
432
  const backendLevels = Object.keys(summary.levels);
433
433
  if (explicitLevels && explicitLevels.length > 0) {
@@ -547,63 +547,64 @@ function createRouteForge(options) {
547
547
  const list = Array.isArray(level) ? level : [level];
548
548
  await Promise.all(list.map(loadOne));
549
549
  }
550
- function route(name, params) {
551
- const meta = findRouteMeta(name);
550
+ function route(level, name, params) {
551
+ const meta = findRouteMeta(level, name);
552
552
  if (!meta) {
553
- if (effectiveStrict) throw new UnknownRouteError(name);
554
- return "";
553
+ throw new UnknownRouteError(name, level);
555
554
  }
556
555
  return buildRequestUrl(meta, params ?? {});
557
556
  }
558
557
  function buildRequestUrl(meta, params) {
559
558
  let uri = meta.uri;
559
+ const defaults = meta.parameter_defaults ?? {};
560
+ const missingRequired = [];
560
561
  for (const p of meta.parameters) {
561
- const v = params[p];
562
- if (v === void 0) {
563
- if (effectiveStrict) throw new MissingRouteParamError(meta.name, [p]);
564
- uri = uri.replace(`{${p}}`, "");
562
+ let v = params[p];
563
+ if ((v === void 0 || v === null) && p in defaults) {
564
+ v = defaults[p];
565
+ }
566
+ if (v === void 0 || v === null) {
567
+ if (uri.includes(`{${p}?}`)) {
568
+ uri = uri.replace(`{${p}?}`, "");
569
+ continue;
570
+ }
571
+ missingRequired.push(p);
565
572
  } else {
566
- uri = uri.replace(`{${p}}`, encodeURIComponent(String(v)));
573
+ uri = uri.replace(`{${p}?}`, encodeURIComponent(String(v))).replace(`{${p}}`, encodeURIComponent(String(v)));
567
574
  }
568
575
  }
576
+ if (missingRequired.length > 0) {
577
+ throw new MissingRouteParamError(meta.name, missingRequired);
578
+ }
579
+ uri = uri.replace(/\/+/g, "/").replace(/\/$/, "");
580
+ if (effectiveUrlPrefix.includes("://")) {
581
+ const prefix2 = effectiveUrlPrefix.endsWith("/") ? effectiveUrlPrefix.slice(0, -1) : effectiveUrlPrefix;
582
+ return uri.startsWith("/") ? `${prefix2}${uri}` : `${prefix2}/${uri}`;
583
+ }
569
584
  const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
570
- return uri.startsWith("/") ? `${base}${uri}` : `${base}/${uri}`;
571
- }
572
- function findRouteMeta(name) {
573
- for (const level of effectiveLevels) {
574
- const entry = cache.get(level);
575
- const meta = entry?.routes[name];
576
- if (meta) {
577
- return { ...meta, level };
578
- }
585
+ const prefix = effectiveUrlPrefix;
586
+ return uri.startsWith("/") ? `${base}${prefix}${uri}` : `${base}${prefix}/${uri}`;
587
+ }
588
+ function findRouteMeta(level, name) {
589
+ const entry = cache.get(level);
590
+ const meta = entry?.routes[name];
591
+ if (meta) {
592
+ return { ...meta, level };
579
593
  }
580
594
  return void 0;
581
595
  }
582
- async function api(name, params = {}) {
596
+ async function api(level, name, params = {}) {
583
597
  await autoDiscoveryPromise;
584
- const meta = findRouteMeta(name);
598
+ await load(level);
599
+ const meta = findRouteMeta(level, name);
585
600
  if (!meta) {
586
- const firstSeg = name.split(nameSeparator)[0];
587
- if (firstSeg && effectiveLevels.includes(firstSeg)) {
588
- await load(firstSeg);
589
- }
590
- const reMeta = findRouteMeta(name);
591
- if (!reMeta) {
592
- if (effectiveStrict) throw new UnknownRouteError(name);
593
- return void 0;
594
- }
595
- return doApiCall(reMeta, params);
601
+ throw new UnknownRouteError(name, level);
596
602
  }
597
603
  return doApiCall(meta, params);
598
604
  }
599
605
  async function doApiCall(meta, params) {
600
606
  assertAuth(meta.level ?? "");
601
- const { query, body, headers, ...pathParams } = params;
602
- for (const p of meta.parameters) {
603
- if (pathParams[p] === void 0) {
604
- if (effectiveStrict) throw new MissingRouteParamError(meta.name, [p]);
605
- }
606
- }
607
+ const { pathParams, query, body, headers } = resolveApiParams(params);
607
608
  const method = pickMethod(meta);
608
609
  const urlWithQuery = appendQuery(buildRequestUrl(meta, pathParams), query);
609
610
  const config = {
@@ -652,6 +653,36 @@ function createRouteForge(options) {
652
653
  if (level) cache.del(level);
653
654
  else cache.clear();
654
655
  }
656
+ function isLoaded(level) {
657
+ if (level) return cache.get(level) !== void 0;
658
+ return effectiveLevels.every((lvl) => cache.get(lvl) !== void 0);
659
+ }
660
+ function hasRoute(level, name) {
661
+ return findRouteMeta(level, name) !== void 0;
662
+ }
663
+ function getRoutes(level) {
664
+ if (level !== void 0) {
665
+ const entry = cache.get(level);
666
+ const routes = entry?.routes ?? {};
667
+ const result2 = {};
668
+ for (const [k, v] of Object.entries(routes)) {
669
+ result2[k] = { ...v };
670
+ }
671
+ return result2;
672
+ }
673
+ const result = {};
674
+ for (const lvl of effectiveLevels) {
675
+ const entry = cache.get(lvl);
676
+ if (entry) {
677
+ const levelRoutes = {};
678
+ for (const [k, v] of Object.entries(entry.routes)) {
679
+ levelRoutes[k] = { ...v };
680
+ }
681
+ result[lvl] = levelRoutes;
682
+ }
683
+ }
684
+ return result;
685
+ }
655
686
  void autoDiscoveryPromise.then(() => {
656
687
  if (effectiveEager.length > 0) {
657
688
  void Promise.all(effectiveEager.map((lvl) => load(lvl))).catch((e) => {
@@ -664,7 +695,11 @@ function createRouteForge(options) {
664
695
  api,
665
696
  load,
666
697
  route,
698
+ url: route,
667
699
  invalidate,
700
+ isLoaded,
701
+ hasRoute,
702
+ getRoutes,
668
703
  interceptors: {
669
704
  request: requestInterceptors,
670
705
  response: responseInterceptors
@@ -686,6 +721,46 @@ function appendQuery(url, query) {
686
721
  if (!qs) return url;
687
722
  return url.includes("?") ? `${url}&${qs}` : `${url}?${qs}`;
688
723
  }
724
+ function resolveApiParams(input) {
725
+ const {
726
+ params: explicitParams,
727
+ query: rawQuery,
728
+ body: rawBody,
729
+ headers: rawHeaders,
730
+ ...flatRest
731
+ } = input;
732
+ const pathParams = explicitParams ? { ...explicitParams } : {};
733
+ for (const [k, v] of Object.entries(flatRest)) {
734
+ if (!(k in pathParams)) {
735
+ pathParams[k] = v;
736
+ }
737
+ }
738
+ let query;
739
+ let body;
740
+ let headers;
741
+ if (rawQuery !== void 0) {
742
+ if (typeof rawQuery === "object" && rawQuery !== null) {
743
+ query = rawQuery;
744
+ } else if (!("query" in pathParams)) {
745
+ pathParams.query = rawQuery;
746
+ }
747
+ }
748
+ if (rawBody !== void 0) {
749
+ if (typeof rawBody !== "string" && typeof rawBody !== "number") {
750
+ body = rawBody;
751
+ } else if (!("body" in pathParams)) {
752
+ pathParams.body = rawBody;
753
+ }
754
+ }
755
+ if (rawHeaders !== void 0) {
756
+ if (typeof rawHeaders === "object" && rawHeaders !== null) {
757
+ headers = rawHeaders;
758
+ } else if (!("headers" in pathParams)) {
759
+ pathParams.headers = rawHeaders;
760
+ }
761
+ }
762
+ return { pathParams, query, body, headers };
763
+ }
689
764
 
690
765
  exports.AdapterNotFoundError = AdapterNotFoundError;
691
766
  exports.ForgeError = ForgeError;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cache.ts","../src/errors.ts","../src/interceptors.ts","../src/adapters/builtin-http.ts","../src/adapters/axios.ts","../src/adapters/index.ts","../src/forge.ts"],"names":["wrapped"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 按层级隔离的路由表缓存\n * @see .docs/SPEC.md §4.1.2\n *\n * 规则:\n * - 每层级独立条目,互不污染(cache key = `route-forge:${level}`)\n * - TTL 优先用后端响应里的 cache 字段,本地 cache.ttl 仅作兜底\n * - storage: 'memory' | 'sessionStorage' | 'localStorage'\n */\n\nimport type { CacheStorage, LevelRoutesResponse, RouteMeta } from './types.js';\n\ninterface CacheEntry {\n level: string;\n routes: Record<string, RouteMeta>;\n ttl: number | null;\n cachedAt: number;\n}\n\nconst KEY_PREFIX = 'route-forge:';\n\nfunction pickStorage(storage: CacheStorage): Storage | null {\n if (storage === 'memory') return null;\n if (typeof globalThis === 'undefined') return null;\n if (storage === 'sessionStorage') {\n return globalThis.sessionStorage ?? null;\n }\n if (storage === 'localStorage') {\n return globalThis.localStorage ?? null;\n }\n return null;\n}\n\nexport class RouteCache {\n private readonly storage: CacheStorage;\n private readonly fallbackTtl: number;\n private readonly backend: Storage | null;\n private readonly memory = new Map<string, CacheEntry>();\n\n constructor(opts: { storage: CacheStorage; ttl: number }) {\n this.storage = opts.storage;\n this.fallbackTtl = opts.ttl;\n this.backend = pickStorage(opts.storage);\n }\n\n private key(level: string): string {\n return `${KEY_PREFIX}${level}`;\n }\n\n get(level: string): CacheEntry | undefined {\n if (this.storage === 'memory' || !this.backend) {\n return this.getFromMemory(level);\n }\n const raw = this.backend.getItem(this.key(level));\n if (!raw) return undefined;\n try {\n const entry = JSON.parse(raw) as CacheEntry;\n if (this.isExpired(entry)) {\n this.del(level);\n return undefined;\n }\n return entry;\n } catch {\n return undefined;\n }\n }\n\n private getFromMemory(level: string): CacheEntry | undefined {\n const entry = this.memory.get(level);\n if (!entry) return undefined;\n if (this.isExpired(entry)) {\n this.memory.delete(level);\n return undefined;\n }\n return entry;\n }\n\n set(resp: LevelRoutesResponse): void {\n const ttl = resp.cache !== undefined && resp.cache !== null ? resp.cache : this.fallbackTtl;\n const entry: CacheEntry = {\n level: resp.level,\n routes: resp.routes,\n ttl,\n cachedAt: Date.now(),\n };\n if (this.storage === 'memory' || !this.backend) {\n this.memory.set(resp.level, entry);\n return;\n }\n try {\n this.backend.setItem(this.key(resp.level), JSON.stringify(entry));\n } catch {\n // 容量满或被禁用:回退内存\n this.memory.set(resp.level, entry);\n }\n }\n\n del(level: string): void {\n this.memory.delete(level);\n if (this.backend) {\n try {\n this.backend.removeItem(this.key(level));\n } catch {\n /* noop */\n }\n }\n }\n\n clear(): void {\n this.memory.clear();\n if (this.backend) {\n try {\n const toRemove: string[] = [];\n for (let i = 0; i < this.backend.length; i++) {\n const k = this.backend.key(i);\n if (k && k.startsWith(KEY_PREFIX)) toRemove.push(k);\n }\n for (const k of toRemove) this.backend.removeItem(k);\n } catch {\n /* noop */\n }\n }\n }\n\n private isExpired(entry: CacheEntry): boolean {\n if (entry.ttl === null) return false;\n if (entry.ttl === 0) return false; // 0 表示永久\n return Date.now() - entry.cachedAt > entry.ttl * 1000;\n }\n}\n","/**\n * Route Forge 错误基类与具体错误类\n * @see .docs/SPEC.md §6\n */\n\nexport interface ForgeErrorContext {\n [key: string]: unknown;\n}\n\nexport class ForgeError extends Error {\n readonly code: string;\n readonly route?: string;\n readonly level?: string;\n readonly context?: ForgeErrorContext;\n readonly cause?: unknown;\n\n constructor(\n message: string,\n opts: {\n code: string;\n route?: string;\n level?: string;\n context?: ForgeErrorContext;\n cause?: unknown;\n },\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = opts.code;\n if (opts.route !== undefined) this.route = opts.route;\n if (opts.level !== undefined) this.level = opts.level;\n if (opts.context !== undefined) this.context = opts.context;\n if (opts.cause !== undefined) this.cause = opts.cause;\n }\n}\n\n/** RF_FE_001:路由名不存在于已加载层级中 */\nexport class UnknownRouteError extends ForgeError {\n constructor(route: string, level?: string) {\n super(`Route \"${route}\" not found${level ? ` in level \"${level}\"` : ''}`, {\n code: 'RF_FE_001',\n route,\n level,\n });\n }\n}\n\n/** RF_FE_002:路由所在层级未在 levels 声明 */\nexport class UnknownLevelError extends ForgeError {\n constructor(level: string) {\n super(`Level \"${level}\" not declared in options.levels`, {\n code: 'RF_FE_002',\n level,\n });\n }\n}\n\n/** RF_FE_003:路径参数缺失(strict=true 时) */\nexport class MissingRouteParamError extends ForgeError {\n constructor(route: string, missingParams: string[]) {\n super(`Missing path parameter(s) ${missingParams.join(', ')} for route \"${route}\"`, {\n code: 'RF_FE_003',\n route,\n context: { missingParams },\n });\n }\n}\n\n/** RF_FE_004:未登录访问受保护层级 */\nexport class InsufficientAuthError extends ForgeError {\n constructor(level: string) {\n super(`Insufficient auth: level \"${level}\" requires login`, {\n code: 'RF_FE_004',\n level,\n });\n }\n}\n\n/** RF_FE_005:adapter: 'axios' 但未检测到 axios */\nexport class AdapterNotFoundError extends ForgeError {\n constructor(adapter: string) {\n super(`Adapter \"${adapter}\" not available; install axios or use 'builtin'`, {\n code: 'RF_FE_005',\n context: { adapter },\n });\n }\n}\n\n/** RF_FE_006:请求拦截器返回非 RequestConfig */\nexport class InvalidInterceptorReturnError extends ForgeError {\n constructor(route?: string) {\n super(`Request interceptor must return a RequestConfig object`, {\n code: 'RF_FE_006',\n route,\n });\n }\n}\n\n/** RF_FE_007:adapter 抛出的网络错误(DNS、连接超时等) */\nexport class NetworkError extends ForgeError {\n constructor(message: string, route?: string, level?: string, cause?: unknown) {\n super(message, { code: 'RF_FE_007', route, level, cause });\n }\n}\n\n/** RF_FE_008:HTTP 非 2xx 且未被 onRejected 拦截器恢复 */\nexport class HTTPError extends ForgeError {\n constructor(\n message: string,\n opts: { route?: string; level?: string; status?: number; url?: string; method?: string; cause?: unknown },\n ) {\n super(message, {\n code: 'RF_FE_008',\n route: opts.route,\n level: opts.level,\n context: { status: opts.status, url: opts.url, method: opts.method },\n cause: opts.cause,\n });\n }\n}\n","/**\n * 拦截器管理器实现\n * @see .docs/SPEC.md §4.1.3a, §4.1.1\n *\n * 执行顺序约定(对齐 axios):\n * - 请求拦截器:LIFO(后注册先执行),onRejected 与 onFulfilled 同序\n * - 响应拦截器:FIFO(先注册先执行),onRejected 与 onFulfilled 同序\n *\n * 实现策略:\n * - InterceptorManagerImpl.forEach 保持正序迭代(与 use/eject 语义一致)\n * - runRequestInterceptors 收集 handlers 后 reverse() 再串联 Promise 链,实现 LIFO\n * - runResponseInterceptors 直接正序串联,实现 FIFO\n *\n * 串联实现:采用标准 Promise 链语义\n * `Promise.resolve(initial).then(f0, r0).then(f1, r1).then(f2, r2)...`\n * - onFulfilled 抛错 → 下一组 onRejected 接住\n * - onRejected 返回值 → 后续 onFulfilled 继续执行(恢复为正常流程)\n * - onRejected 抛错 → 下一组 onRejected 接住 / 进入调用方 catch\n */\n\nimport type {\n InterceptorHandler,\n InterceptorManager,\n RequestConfig,\n ResponseData,\n} from './types.js';\nimport { InvalidInterceptorReturnError } from './errors.js';\n\nexport class InterceptorManagerImpl<TIn, TOut = TIn> implements InterceptorManager<TIn, TOut> {\n private handlers: InterceptorHandler<TIn, TOut>[] = [];\n private nextId = 0;\n\n use(\n onFulfilled?: (value: TIn) => TOut | Promise<TOut>,\n onRejected?: (error: unknown) => unknown | Promise<unknown>,\n ): number {\n const id = this.nextId++;\n this.handlers.push({ id, onFulfilled, onRejected });\n return id;\n }\n\n eject(id: number): void {\n const idx = this.handlers.findIndex((h) => h.id === id);\n if (idx >= 0) this.handlers.splice(idx, 1);\n }\n\n clear(): void {\n this.handlers = [];\n }\n\n forEach(fn: (handler: InterceptorHandler<TIn, TOut>) => void): void {\n for (const h of this.handlers) fn(h);\n }\n\n /** 测试用:当前注册数量 */\n get size(): number {\n return this.handlers.length;\n }\n}\n\n/**\n * 串联请求拦截器(LIFO,对齐 axios)。\n *\n * - onFulfilled 必须返回对象(RequestConfig);非对象抛 InvalidInterceptorReturnError\n * - onFulfilled 抛错 → 同管理器的 onRejected 链;某段 onRejected 返回值则恢复正序流程\n * - 仍未消化则向上抛,不发请求\n */\nexport async function runRequestInterceptors(\n manager: InterceptorManager<RequestConfig, RequestConfig>,\n initial: RequestConfig,\n): Promise<RequestConfig> {\n const handlers: InterceptorHandler<RequestConfig, RequestConfig>[] = [];\n manager.forEach((h) => handlers.push(h));\n // 请求拦截器 LIFO(对齐 axios):后注册先执行\n handlers.reverse();\n\n let p: Promise<unknown> = Promise.resolve(initial);\n for (const h of handlers) {\n const onF = h.onFulfilled;\n const onR = h.onRejected;\n p = p.then(\n async (v) => {\n if (!onF) return v;\n const result = await onF(v as RequestConfig);\n if (result === null || typeof result !== 'object') {\n throw new InvalidInterceptorReturnError();\n }\n return result;\n },\n (e) => (onR ? onR(e) : Promise.reject(e)),\n );\n }\n return p as Promise<RequestConfig>;\n}\n\n/**\n * 串联响应拦截器(FIFO,对齐 axios)。\n *\n * - HTTP 非 2xx 或任一 onFulfilled 抛错 → onRejected 链;onRejected 返回值则恢复正序流程\n * - 首段 onFulfilled 接收 ResponseData;后续段接收上一段返回值(类型由用户约束)\n * - 末段返回值即 forge.api() 的 resolve 值\n *\n * @param source 已包含 HTTP 错误转换逻辑的 ResponseData Promise\n * (HTTP 非 2xx 时 reject 为 HTTPError;网络层错误 reject 为 NetworkError)\n */\nexport async function runResponseInterceptors(\n manager: InterceptorManager<ResponseData, unknown>,\n source: Promise<ResponseData>,\n): Promise<unknown> {\n const handlers: InterceptorHandler<ResponseData, unknown>[] = [];\n manager.forEach((h) => handlers.push(h));\n\n let p: Promise<unknown> = source;\n for (const h of handlers) {\n const onF = h.onFulfilled;\n const onR = h.onRejected;\n p = p.then(\n (v) => (onF ? onF(v as ResponseData) : v),\n (e) => (onR ? onR(e) : Promise.reject(e)),\n );\n }\n return p;\n}\n\n/**\n * 工厂函数:供自定义 Fetcher 复用同一套拦截器实现\n * @see .docs/SPEC.md §4.3.3\n */\nexport function createInterceptorManager<TIn, TOut = TIn>(): InterceptorManager<TIn, TOut> {\n return new InterceptorManagerImpl<TIn, TOut>();\n}\n","/**\n * 内置类 axios 精简实现(builtin adapter)\n * @see .docs/SPEC.md §4.3.1\n *\n * 设计目标:\n * - API 兼容 axios(use/eject/clear、request/get/post/...)便于业务代码零成本切换\n * - 拦截器执行顺序对齐 axios(请求 LIFO、响应 FIFO),与 SPEC §4.1.3a 一致\n * - 仅实现 Route Forge 调用链需要的能力:拦截器、JSON、超时、取消\n * - 零依赖,仅基于宿主原生 fetch(Node 18+ / 现代浏览器原生支持)\n * - 体积目标:min+gzip < 3KB,仅作为兜底,不追求覆盖 axios 全部 API\n */\n\nimport type { RequestConfig, ResponseData, InterceptorManager } from '../types.js';\nimport {\n createInterceptorManager,\n runRequestInterceptors,\n runResponseInterceptors,\n} from '../interceptors.js';\n\nexport function createBuiltinHttp(forgeInterceptors?: {\n request: InterceptorManager<RequestConfig, RequestConfig>;\n response: InterceptorManager<ResponseData, unknown>;\n}) {\n const requestMgr = forgeInterceptors?.request ?? createInterceptorManager<RequestConfig>();\n const responseMgr = forgeInterceptors?.response ?? createInterceptorManager<ResponseData>();\n\n async function request(config: RequestConfig): Promise<ResponseData> {\n // 1. 执行请求拦截器(LIFO,对齐 axios)\n const finalConfig = await runRequestInterceptors(requestMgr, config);\n\n // 2. 超时控制:timeout > 0 时用 AbortSignal.timeout\n const signal: AbortSignal | undefined =\n finalConfig.timeout && finalConfig.timeout > 0\n ? AbortSignal.timeout(finalConfig.timeout)\n : undefined;\n\n // 3. paramsSerializer:自定义 query 序列化\n let url = finalConfig.url;\n if (finalConfig.paramsSerializer && finalConfig.params) {\n const qs = finalConfig.paramsSerializer(finalConfig.params);\n if (qs) {\n url = url.includes('?') ? `${url}&${qs}` : `${url}?${qs}`;\n }\n }\n\n // 4. 构建 fetchInit\n const fetchInit: RequestInit = {\n method: finalConfig.method,\n headers: new Headers(finalConfig.headers),\n };\n if (signal) fetchInit.signal = signal;\n if (\n finalConfig.body !== undefined &&\n !['GET', 'HEAD'].includes(finalConfig.method.toUpperCase())\n ) {\n fetchInit.body =\n typeof finalConfig.body === 'string'\n ? finalConfig.body\n : JSON.stringify(finalConfig.body);\n }\n\n // 5. 调用 fetch\n const res = await fetch(url, fetchInit);\n const text = await res.text();\n let data: unknown = text;\n const contentType = res.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n try {\n data = JSON.parse(text);\n } catch {\n /* 保留原始文本 */\n }\n }\n\n // 6. 构建 ResponseData\n const responseData: ResponseData = {\n route: finalConfig.route,\n level: finalConfig.level,\n method: finalConfig.method,\n url,\n status: res.status,\n headers: res.headers,\n data,\n config: finalConfig,\n };\n\n // 7. 执行响应拦截器(FIFO,对齐 axios);末段返回值即 request() 的 resolve 值\n return runResponseInterceptors(\n responseMgr,\n Promise.resolve(responseData),\n ) as Promise<ResponseData>;\n }\n\n // 便捷方法\n const get = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'GET' } as RequestConfig);\n const post = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'POST' } as RequestConfig);\n const put = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'PUT' } as RequestConfig);\n const patch = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'PATCH' } as RequestConfig);\n const del = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'DELETE' } as RequestConfig);\n\n return {\n request,\n interceptors: {\n request: requestMgr,\n response: responseMgr,\n },\n runsInterceptors: true,\n get,\n post,\n put,\n patch,\n delete: del,\n };\n}\n","/**\n * 把宿主项目的 axios 实例包装为 Fetcher adapter\n * @see .docs/SPEC.md §4.3.2, §4.3.4\n *\n * 设计约定:\n * - 不接管或修改宿主 axios 已有拦截器/defaults 配置,仅调用其 request 入口\n * - 宿主 axios 的 defaults.baseURL/defaults.headers 自动生效\n * - 宿主已注册的拦截器会先执行;Route Forge 自身拦截器在宿主拦截器之后执行\n * (由 forge.interceptors 注入到宿主 axios 时序)后续阶段填充\n * - 未检测到 axios 时返回 null(让 'auto' 自动降级到 builtin)\n */\n\nimport type { RequestConfig, ResponseData } from '../types.js';\nimport type { ResolvedAdapter } from './index.js';\n\nexport async function wrapAxiosAdapter(): Promise<ResolvedAdapter | null> {\n // ESM 友好的动态探测:尝试 import('axios'),失败则查全局 window.axios\n let axios: any;\n try {\n const mod = await import(/* @vite-ignore */ 'axios');\n axios = mod.default ?? mod;\n } catch {\n if (typeof globalThis !== 'undefined' && (globalThis as any).axios) {\n axios = (globalThis as any).axios;\n }\n }\n if (!axios || typeof axios.request !== 'function') return null;\n\n async function request(config: RequestConfig): Promise<ResponseData> {\n const headers: Record<string, string> = { ...config.headers };\n const res = await axios.request({\n url: config.url,\n method: config.method,\n headers,\n data: config.body,\n // axios 会处理 baseURL/transformRequest 等 defaults\n });\n\n return {\n route: config.route,\n level: config.level,\n method: config.method,\n url: config.url,\n status: res.status,\n headers: new Headers(res.headers ?? {}),\n data: res.data,\n config,\n };\n }\n\n // 不暴露宿主 axios 的 interceptors manager(避免覆盖 Route Forge 的统一时序);\n // Route Forge 调用链由 forge.interceptors 控制,宿主拦截器先执行由 axios 内部保证。\n return { request, interceptors: undefined };\n}\n","/**\n * Adapter 入口\n * @see .docs/SPEC.md §4.3\n *\n * Route Forge 提供三种 adapter:\n * 1. 'auto'(默认):检测到宿主 axios 则用之;否则用内置 builtin adapter\n * 2. 'axios':强制宿主 axios,未安装抛 AdapterNotFoundError\n * 3. 'builtin':强制内置实现\n * 自定义 Fetcher 接口直接传入即可(绕过 auto 检测)。\n */\n\nimport type { Fetcher, InterceptorManager, RequestConfig, ResponseData } from '../types.js';\nimport { AdapterNotFoundError } from '../errors.js';\nimport { createBuiltinHttp } from './builtin-http.js';\nimport { wrapAxiosAdapter } from './axios.js';\n\nexport type ResolvedAdapter = {\n request: (config: RequestConfig) => Promise<ResponseData>;\n interceptors?: Fetcher['interceptors'];\n runsInterceptors?: boolean;\n /**\n * 便捷方法(可选)。\n * - builtin adapter 提供全部 5 个方法\n * - axios / 自定义 Fetcher 可不提供(调用方需先判断存在性)\n * @see .docs/SPEC.md §4.3.1\n */\n get?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n post?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n put?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n patch?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n delete?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n};\n\nexport interface ResolveAdapterOptions {\n adapter: 'auto' | 'axios' | 'builtin' | Fetcher;\n forgeInterceptors?: {\n request: InterceptorManager<RequestConfig, RequestConfig>;\n response: InterceptorManager<ResponseData, unknown>;\n };\n}\n\n/**\n * 解析 adapter 配置;同步阶段尝试 import('axios'),失败则降级。\n * 注意:实际 axios 探测在生产实现里需要 lazy import;此处仅为框架占位。\n */\nexport async function resolveAdapter(opts: ResolveAdapterOptions): Promise<ResolvedAdapter> {\n const { adapter } = opts;\n\n if (adapter && typeof adapter === 'object') {\n return {\n request: (config: RequestConfig) => adapter.request(config),\n interceptors: adapter.interceptors,\n };\n }\n\n if (adapter === 'builtin') {\n return createBuiltinHttp(opts.forgeInterceptors);\n }\n\n if (adapter === 'axios') {\n const wrapped = await wrapAxiosAdapter();\n if (!wrapped) throw new AdapterNotFoundError('axios');\n return wrapped;\n }\n\n // auto: 优先尝试 axios,失败则 builtin\n const wrapped = await wrapAxiosAdapter().catch(() => null);\n if (wrapped) return wrapped;\n return createBuiltinHttp(opts.forgeInterceptors);\n}\n","/**\n * Route Forge 主入口:createRouteForge\n * @see .docs/SPEC.md §4.1.1 ~ §4.1.6\n *\n * 能力清单(v1.0 MVP):\n * - 按层级懒加载与隔离缓存(§4.1.2)\n * - 并发去重(§4.1.4)\n * - 登录态感知(§4.1.5)\n * - 严格模式(§4.1.6)\n * - 通过路由名调用 API(§4.1.3)\n * - 拦截器(§4.1.3a)\n * - Adapter auto 检测 / builtin / axios / 自定义 Fetcher(§4.3)\n */\n\nimport { RouteCache } from './cache.js';\nimport {\n InterceptorManagerImpl,\n createInterceptorManager,\n runRequestInterceptors,\n runResponseInterceptors,\n} from './interceptors.js';\nimport { resolveAdapter } from './adapters/index.js';\nimport {\n AdapterNotFoundError,\n ForgeError,\n HTTPError,\n InsufficientAuthError,\n MissingRouteParamError,\n NetworkError,\n UnknownLevelError,\n UnknownRouteError,\n} from './errors.js';\nimport type {\n ApiCallParams,\n InterceptorManager,\n LevelRoutesResponse,\n RequestConfig,\n ResponseData,\n RouteForge,\n RouteForgeOptions,\n RouteMeta,\n SummaryResponse,\n} from './types.js';\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_CACHE_TTL = 3600;\nconst DEFAULT_NAME_SEPARATOR = '.';\n\nexport function createRouteForge(options: RouteForgeOptions): RouteForge {\n if (!options.endpoint) throw new TypeError('options.endpoint is required');\n\n const {\n adapter = 'auto',\n timeout = DEFAULT_TIMEOUT,\n baseURL = '',\n nameSeparator = DEFAULT_NAME_SEPARATOR,\n auth,\n interceptors: declarativeInterceptors,\n cache: cacheOpts = {},\n } = options;\n\n // --- 自动发现(SPEC §4.1.1 + §5.3)---\n const explicitLevels = options.levels;\n const explicitEager = options.eager;\n const explicitStrict = options.strict ?? false;\n const explicitEndpoint = options.endpoint;\n\n // effective* 状态:在摘要端点响应到达后被填充\n let effectiveLevels: string[] = explicitLevels ?? [];\n let effectiveEager: string[] = explicitEager ?? [];\n let effectiveStrict = explicitStrict;\n let effectiveEndpoint = explicitEndpoint;\n\n // 拉取摘要端点(用于 strict_mode / endpoint / levels / eager 自动发现)\n const summaryPromise = (async (): Promise<SummaryResponse | null> => {\n try {\n const summaryUrl = explicitEndpoint; // GET {endpoint} = 摘要端点\n const resp = await fetch(summaryUrl, { method: 'GET' });\n if (!resp.ok) {\n console.warn(\n `[route-forge] summary endpoint ${summaryUrl} unreachable (HTTP ${resp.status}); falling back to explicit options`,\n );\n return null;\n }\n return (await resp.json()) as SummaryResponse;\n } catch (e) {\n if (explicitLevels && explicitLevels.length > 0) {\n console.warn(\n `[route-forge] summary endpoint unreachable: ${(e as Error).message}; using explicit levels`,\n );\n return null;\n }\n // 未传 levels 且摘要端点不可达 → 抛 UnknownLevelError\n throw new UnknownLevelError('(auto-discovery)');\n }\n })();\n\n // 自动发现异步填充(不阻塞 createRouteForge 返回)\n const autoDiscoveryPromise = summaryPromise.then((summary) => {\n if (summary === null) {\n return;\n }\n\n // 1. endpoint 后端权威\n if (summary.config.endpoint_prefix && summary.config.endpoint_prefix !== explicitEndpoint) {\n console.warn(\n `[route-forge] backend endpoint_prefix \"${summary.config.endpoint_prefix}\" overrides frontend endpoint \"${explicitEndpoint}\"`,\n );\n effectiveEndpoint = summary.config.endpoint_prefix;\n }\n\n // 2. strict_mode 后端权威:不能放宽,可收紧\n if (summary.config.strict_mode && !explicitStrict) {\n console.warn(\n '[route-forge] backend strict_mode=true overrides frontend strict=false; forcing strict=true',\n );\n effectiveStrict = true;\n }\n\n // 3. levels 取交集或自动发现\n const backendLevels = Object.keys(summary.levels);\n if (explicitLevels && explicitLevels.length > 0) {\n const intersection = explicitLevels.filter((l) => backendLevels.includes(l));\n const removed = explicitLevels.filter((l) => !backendLevels.includes(l));\n if (removed.length > 0) {\n console.warn(\n `[route-forge] levels not in backend summary and dropped: ${removed.join(', ')}`,\n );\n }\n effectiveLevels = intersection;\n } else {\n effectiveLevels = backendLevels;\n }\n\n // 4. eager 未传时取后端 load:'eager' 层级\n if (!explicitEager) {\n effectiveEager = backendLevels.filter((lvl) => summary.levels[lvl]?.load === 'eager');\n }\n });\n\n // 防止 autoDiscoveryPromise 未被 await 时产生 unhandled rejection\n autoDiscoveryPromise.catch(() => {\n /* 自动发现失败:在 load/api await 时会重新抛出 */\n });\n\n const cacheTtl = cacheOpts.ttl ?? DEFAULT_CACHE_TTL;\n const cacheStorage = cacheOpts.storage ?? 'memory';\n const cache = new RouteCache({ storage: cacheStorage, ttl: cacheTtl });\n\n const requestInterceptors: InterceptorManager<RequestConfig, RequestConfig> = new InterceptorManagerImpl();\n const responseInterceptors: InterceptorManager<ResponseData, unknown> = new InterceptorManagerImpl();\n\n // 声明式拦截器先注册(按数组顺序),随后允许运行时 use() 追加\n if (declarativeInterceptors?.request) {\n for (const pair of declarativeInterceptors.request) {\n const [onFulfilled, onRejected] = pair;\n requestInterceptors.use(onFulfilled, onRejected);\n }\n }\n if (declarativeInterceptors?.response) {\n for (const pair of declarativeInterceptors.response) {\n const [onFulfilled, onRejected] = pair;\n responseInterceptors.use(onFulfilled, onRejected);\n }\n }\n\n const adapterPromise = resolveAdapter({\n adapter,\n forgeInterceptors: { request: requestInterceptors, response: responseInterceptors },\n });\n let adapterResolved = false;\n let adapterObj: Awaited<ReturnType<typeof resolveAdapter>> | null = null;\n\n async function ensureAdapter() {\n if (!adapterResolved) {\n adapterObj = await adapterPromise.catch((e) => {\n if (e instanceof AdapterNotFoundError) throw e;\n // 其他错误降级到 builtin(避免初始化失败)\n return resolveAdapter({ adapter: 'builtin' });\n });\n adapterResolved = true;\n }\n return adapterObj!;\n }\n\n const inflight = new Map<string, Promise<void>>();\n\n function isAuthRequired(level: string): boolean {\n return Boolean(auth?.levels?.[level]);\n }\n\n function assertAuth(level: string): void {\n if (isAuthRequired(level) && auth?.state && !auth.state()) {\n throw new InsufficientAuthError(level);\n }\n }\n\n function assertLevelDeclared(level: string): void {\n if (!effectiveLevels.includes(level)) {\n throw new UnknownLevelError(level);\n }\n }\n\n function buildUrl(level: string): string {\n const base = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;\n const ep = effectiveEndpoint.startsWith('/') ? effectiveEndpoint : `/${effectiveEndpoint}`;\n return `${base}${ep}/${encodeURIComponent(level)}`;\n }\n\n async function fetchLevel(level: string): Promise<LevelRoutesResponse> {\n const adp = await ensureAdapter();\n const config: RequestConfig = {\n route: `__forge__.load.${level}`,\n level,\n method: 'GET',\n url: buildUrl(level),\n headers: { Accept: 'application/json' },\n params: {},\n timeout,\n meta: {\n name: `__forge__.load.${level}`,\n uri: buildUrl(level),\n methods: ['GET'],\n parameters: [],\n level,\n },\n };\n // 拉取元信息直接走 adapter(不走 forge.interceptors 链,避免与业务调用混淆)\n const resp = await adp.request(config);\n if (!resp || resp.status < 200 || resp.status >= 300) {\n throw new Error(`Failed to load level ${level}: HTTP ${resp?.status}`);\n }\n const data = resp.data as LevelRoutesResponse;\n // 后端可能下发 cache 字段,让 RouteCache 优先采用\n return data;\n }\n\n async function loadOne(level: string): Promise<void> {\n assertLevelDeclared(level);\n assertAuth(level);\n\n // 缓存命中直接返回\n if (cache.get(level)) return;\n\n // inflight 去重\n const existing = inflight.get(level);\n if (existing) return existing;\n\n const p = (async () => {\n try {\n const resp = await fetchLevel(level);\n cache.set(resp);\n } finally {\n inflight.delete(level);\n }\n })();\n inflight.set(level, p);\n return p;\n }\n\n async function load(level: string | string[]): Promise<void> {\n await autoDiscoveryPromise;\n const list = Array.isArray(level) ? level : [level];\n await Promise.all(list.map(loadOne));\n }\n\n function route(name: string, params?: Record<string, unknown>): string {\n // 静态生成 URL:仅查已加载缓存,未加载时 strict 抛 UnknownRouteError\n const meta = findRouteMeta(name);\n if (!meta) {\n if (effectiveStrict) throw new UnknownRouteError(name);\n return '';\n }\n return buildRequestUrl(meta, params ?? {});\n }\n\n function buildRequestUrl(meta: RouteMeta, params: Record<string, unknown>): string {\n let uri = meta.uri;\n for (const p of meta.parameters) {\n const v = params[p];\n if (v === undefined) {\n if (effectiveStrict) throw new MissingRouteParamError(meta.name, [p]);\n uri = uri.replace(`{${p}}`, '');\n } else {\n uri = uri.replace(`{${p}}`, encodeURIComponent(String(v)));\n }\n }\n const base = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;\n return uri.startsWith('/') ? `${base}${uri}` : `${base}/${uri}`;\n }\n\n function findRouteMeta(name: string): RouteMeta | undefined {\n for (const level of effectiveLevels) {\n const entry = cache.get(level);\n const meta = entry?.routes[name];\n if (meta) {\n return { ...meta, level };\n }\n }\n return undefined;\n }\n\n async function api(name: string, params: ApiCallParams = {}): Promise<unknown> {\n await autoDiscoveryPromise;\n const meta = findRouteMeta(name);\n if (!meta) {\n // 隐式懒加载:路由名不在缓存中,可能是其层级尚未加载\n // 1. 尝试通过 name 分隔符拆出可能的 level 名(如 'admin.users.show' → 'admin')\n const firstSeg = name.split(nameSeparator)[0];\n if (firstSeg && effectiveLevels.includes(firstSeg)) {\n await load(firstSeg);\n }\n // 重新查询\n const reMeta = findRouteMeta(name);\n if (!reMeta) {\n if (effectiveStrict) throw new UnknownRouteError(name);\n return undefined;\n }\n return doApiCall(reMeta, params);\n }\n return doApiCall(meta, params);\n }\n\n async function doApiCall(meta: RouteMeta, params: ApiCallParams): Promise<unknown> {\n assertAuth(meta.level ?? '');\n const { query, body, headers, ...pathParams } = params;\n\n // 校验路径参数\n for (const p of meta.parameters) {\n if (pathParams[p] === undefined) {\n if (effectiveStrict) throw new MissingRouteParamError(meta.name, [p]);\n }\n }\n\n const method = pickMethod(meta);\n const urlWithQuery = appendQuery(buildRequestUrl(meta, pathParams as Record<string, unknown>), query);\n const config: RequestConfig = {\n route: meta.name,\n level: meta.level ?? '',\n method,\n url: urlWithQuery,\n headers: { Accept: 'application/json', ...(headers ?? {}) },\n body,\n params: pathParams as Record<string, unknown>,\n timeout,\n meta,\n };\n\n const adp = await ensureAdapter();\n\n // 5. 请求拦截链(LIFO,对齐 axios);任一段抛错且 onRejected 未消化 → 进入调用方 catch,不发请求\n // builtin adapter 内部已执行 forge 拦截器(同一管理器对象引用,runsInterceptors=true)→ 跳过\n const finalConfig = adp.runsInterceptors\n ? config\n : await runRequestInterceptors(requestInterceptors, config);\n\n // 6. adapter 调用 → 7/8 的错误转换 + 响应拦截链\n // HTTP 非 2xx 转 HTTPError;底层网络错误(非 ForgeError)转 NetworkError\n // 注意:source 始终构造(含错误转换逻辑),runsInterceptors=true 时直接返回 source\n const source: Promise<ResponseData> = adp.request(finalConfig).then(\n (resp) => {\n if (resp.status < 200 || resp.status >= 300) {\n throw new HTTPError(\n `HTTP ${resp.status} for route \"${resp.route}\" (${resp.method} ${resp.url})`,\n {\n route: resp.route,\n level: resp.level,\n status: resp.status,\n url: resp.url,\n method: resp.method,\n },\n );\n }\n return resp;\n },\n (err) => {\n // 已经是 ForgeError(如拦截器内重新抛的)→ 原样抛\n if (err instanceof ForgeError) throw err;\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n meta.name,\n meta.level,\n err,\n );\n },\n );\n\n // 响应拦截链(FIFO,对齐 axios);末段返回值即 api() resolve 值\n // builtin adapter 内部已执行 forge 响应拦截器(runsInterceptors=true)→ 直接返回 source\n if (adp.runsInterceptors) return source;\n return runResponseInterceptors(responseInterceptors, source);\n }\n\n function invalidate(level?: string): void {\n if (level) cache.del(level);\n else cache.clear();\n }\n\n // eager 层级自动加载(不阻塞 createRouteForge 返回;在自动发现完成后触发)\n void autoDiscoveryPromise\n .then(() => {\n if (effectiveEager.length > 0) {\n void Promise.all(effectiveEager.map((lvl) => load(lvl))).catch((e) => {\n console.warn(`[route-forge] eager load failed: ${(e as Error).message}`);\n });\n }\n })\n .catch(() => {\n /* 自动发现失败时不触发 eager */\n });\n\n return {\n api,\n load,\n route,\n invalidate,\n interceptors: {\n request: requestInterceptors,\n response: responseInterceptors,\n },\n };\n}\n\nfunction pickMethod(meta: RouteMeta): string {\n const m = meta.methods.find((x) => x.toUpperCase() !== 'HEAD');\n return (m ?? meta.methods[0] ?? 'GET').toUpperCase();\n}\n\nfunction appendQuery(url: string, query?: Record<string, unknown>): string {\n if (!query) return url;\n const usp = new URLSearchParams();\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n usp.append(k, String(v));\n }\n const qs = usp.toString();\n if (!qs) return url;\n return url.includes('?') ? `${url}&${qs}` : `${url}?${qs}`;\n}\n\n// 显式重导出,便于业务代码按需导入工具件\nexport { createInterceptorManager } from './interceptors.js';\nexport { RouteCache } from './cache.js';\nexport { ForgeError } from './errors.js';\n"]}
1
+ {"version":3,"sources":["../src/cache.ts","../src/errors.ts","../src/interceptors.ts","../src/adapters/builtin-http.ts","../src/adapters/axios.ts","../src/adapters/index.ts","../src/forge.ts"],"names":["wrapped","prefix","result"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 按层级隔离的路由表缓存\n * @see .docs/SPEC.md §4.1.2\n *\n * 规则:\n * - 每层级独立条目,互不污染(cache key = `route-forge:${level}`)\n * - TTL 优先用后端响应里的 cache 字段,本地 cache.ttl 仅作兜底\n * - storage: 'memory' | 'sessionStorage' | 'localStorage'\n */\n\nimport type { CacheStorage, LevelRoutesResponse, RouteMeta } from './types.js';\n\ninterface CacheEntry {\n level: string;\n routes: Record<string, RouteMeta>;\n ttl: number | null;\n cachedAt: number;\n}\n\nconst KEY_PREFIX = 'route-forge:';\n\nfunction pickStorage(storage: CacheStorage): Storage | null {\n if (storage === 'memory') return null;\n if (typeof globalThis === 'undefined') return null;\n if (storage === 'sessionStorage') {\n return globalThis.sessionStorage ?? null;\n }\n if (storage === 'localStorage') {\n return globalThis.localStorage ?? null;\n }\n return null;\n}\n\nexport class RouteCache {\n private readonly storage: CacheStorage;\n private readonly fallbackTtl: number;\n private readonly backend: Storage | null;\n private readonly memory = new Map<string, CacheEntry>();\n\n constructor(opts: { storage: CacheStorage; ttl: number }) {\n this.storage = opts.storage;\n this.fallbackTtl = opts.ttl;\n this.backend = pickStorage(opts.storage);\n }\n\n private key(level: string): string {\n return `${KEY_PREFIX}${level}`;\n }\n\n get(level: string): CacheEntry | undefined {\n if (this.storage === 'memory' || !this.backend) {\n return this.getFromMemory(level);\n }\n const raw = this.backend.getItem(this.key(level));\n if (!raw) return undefined;\n try {\n const entry = JSON.parse(raw) as CacheEntry;\n if (this.isExpired(entry)) {\n this.del(level);\n return undefined;\n }\n return entry;\n } catch {\n return undefined;\n }\n }\n\n private getFromMemory(level: string): CacheEntry | undefined {\n const entry = this.memory.get(level);\n if (!entry) return undefined;\n if (this.isExpired(entry)) {\n this.memory.delete(level);\n return undefined;\n }\n return entry;\n }\n\n set(resp: LevelRoutesResponse): void {\n const ttl = resp.cache !== undefined && resp.cache !== null ? resp.cache : this.fallbackTtl;\n const entry: CacheEntry = {\n level: resp.level,\n routes: resp.routes,\n ttl,\n cachedAt: Date.now(),\n };\n if (this.storage === 'memory' || !this.backend) {\n this.memory.set(resp.level, entry);\n return;\n }\n try {\n this.backend.setItem(this.key(resp.level), JSON.stringify(entry));\n } catch {\n // 容量满或被禁用:回退内存\n this.memory.set(resp.level, entry);\n }\n }\n\n del(level: string): void {\n this.memory.delete(level);\n if (this.backend) {\n try {\n this.backend.removeItem(this.key(level));\n } catch {\n /* noop */\n }\n }\n }\n\n clear(): void {\n this.memory.clear();\n if (this.backend) {\n try {\n const toRemove: string[] = [];\n for (let i = 0; i < this.backend.length; i++) {\n const k = this.backend.key(i);\n if (k && k.startsWith(KEY_PREFIX)) toRemove.push(k);\n }\n for (const k of toRemove) this.backend.removeItem(k);\n } catch {\n /* noop */\n }\n }\n }\n\n private isExpired(entry: CacheEntry): boolean {\n if (entry.ttl === null) return false;\n if (entry.ttl === 0) return false; // 0 表示永久\n return Date.now() - entry.cachedAt > entry.ttl * 1000;\n }\n}\n","/**\n * Route Forge 错误基类与具体错误类\n * @see .docs/SPEC.md §6\n */\n\nexport interface ForgeErrorContext {\n [key: string]: unknown;\n}\n\nexport class ForgeError extends Error {\n readonly code: string;\n readonly route?: string;\n readonly level?: string;\n readonly context?: ForgeErrorContext;\n readonly cause?: unknown;\n\n constructor(\n message: string,\n opts: {\n code: string;\n route?: string;\n level?: string;\n context?: ForgeErrorContext;\n cause?: unknown;\n },\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = opts.code;\n if (opts.route !== undefined) this.route = opts.route;\n if (opts.level !== undefined) this.level = opts.level;\n if (opts.context !== undefined) this.context = opts.context;\n if (opts.cause !== undefined) this.cause = opts.cause;\n }\n}\n\n/** RF_FE_001:路由名不存在于已加载层级中 */\nexport class UnknownRouteError extends ForgeError {\n constructor(route: string, level?: string) {\n super(`Route \"${route}\" not found${level ? ` in level \"${level}\"` : ''}`, {\n code: 'RF_FE_001',\n route,\n level,\n });\n }\n}\n\n/** RF_FE_002:路由所在层级未在 levels 声明 */\nexport class UnknownLevelError extends ForgeError {\n constructor(level: string) {\n super(`Level \"${level}\" not declared in options.levels`, {\n code: 'RF_FE_002',\n level,\n });\n }\n}\n\n/** RF_FE_003:路径参数缺失(strict=true 时) */\nexport class MissingRouteParamError extends ForgeError {\n constructor(route: string, missingParams: string[]) {\n super(`Missing path parameter(s) ${missingParams.join(', ')} for route \"${route}\"`, {\n code: 'RF_FE_003',\n route,\n context: { missingParams },\n });\n }\n}\n\n/** RF_FE_004:未登录访问受保护层级 */\nexport class InsufficientAuthError extends ForgeError {\n constructor(level: string) {\n super(`Insufficient auth: level \"${level}\" requires login`, {\n code: 'RF_FE_004',\n level,\n });\n }\n}\n\n/** RF_FE_005:adapter: 'axios' 但未检测到 axios */\nexport class AdapterNotFoundError extends ForgeError {\n constructor(adapter: string) {\n super(`Adapter \"${adapter}\" not available; install axios or use 'builtin'`, {\n code: 'RF_FE_005',\n context: { adapter },\n });\n }\n}\n\n/** RF_FE_006:请求拦截器返回非 RequestConfig */\nexport class InvalidInterceptorReturnError extends ForgeError {\n constructor(route?: string) {\n super(`Request interceptor must return a RequestConfig object`, {\n code: 'RF_FE_006',\n route,\n });\n }\n}\n\n/** RF_FE_007:adapter 抛出的网络错误(DNS、连接超时等) */\nexport class NetworkError extends ForgeError {\n constructor(message: string, route?: string, level?: string, cause?: unknown) {\n super(message, { code: 'RF_FE_007', route, level, cause });\n }\n}\n\n/** RF_FE_008:HTTP 非 2xx 且未被 onRejected 拦截器恢复 */\nexport class HTTPError extends ForgeError {\n constructor(\n message: string,\n opts: { route?: string; level?: string; status?: number; url?: string; method?: string; cause?: unknown },\n ) {\n super(message, {\n code: 'RF_FE_008',\n route: opts.route,\n level: opts.level,\n context: { status: opts.status, url: opts.url, method: opts.method },\n cause: opts.cause,\n });\n }\n}\n","/**\n * 拦截器管理器实现\n * @see .docs/SPEC.md §4.1.3a, §4.1.1\n *\n * 执行顺序约定(对齐 axios):\n * - 请求拦截器:LIFO(后注册先执行),onRejected 与 onFulfilled 同序\n * - 响应拦截器:FIFO(先注册先执行),onRejected 与 onFulfilled 同序\n *\n * 实现策略:\n * - InterceptorManagerImpl.forEach 保持正序迭代(与 use/eject 语义一致)\n * - runRequestInterceptors 收集 handlers 后 reverse() 再串联 Promise 链,实现 LIFO\n * - runResponseInterceptors 直接正序串联,实现 FIFO\n *\n * 串联实现:采用标准 Promise 链语义\n * `Promise.resolve(initial).then(f0, r0).then(f1, r1).then(f2, r2)...`\n * - onFulfilled 抛错 → 下一组 onRejected 接住\n * - onRejected 返回值 → 后续 onFulfilled 继续执行(恢复为正常流程)\n * - onRejected 抛错 → 下一组 onRejected 接住 / 进入调用方 catch\n */\n\nimport type {\n InterceptorHandler,\n InterceptorManager,\n RequestConfig,\n ResponseData,\n} from './types.js';\nimport { InvalidInterceptorReturnError } from './errors.js';\n\nexport class InterceptorManagerImpl<TIn, TOut = TIn> implements InterceptorManager<TIn, TOut> {\n private handlers: InterceptorHandler<TIn, TOut>[] = [];\n private nextId = 0;\n\n use(\n onFulfilled?: (value: TIn) => TOut | Promise<TOut>,\n onRejected?: (error: unknown) => unknown | Promise<unknown>,\n ): number {\n const id = this.nextId++;\n this.handlers.push({ id, onFulfilled, onRejected });\n return id;\n }\n\n eject(id: number): void {\n const idx = this.handlers.findIndex((h) => h.id === id);\n if (idx >= 0) this.handlers.splice(idx, 1);\n }\n\n clear(): void {\n this.handlers = [];\n }\n\n forEach(fn: (handler: InterceptorHandler<TIn, TOut>) => void): void {\n for (const h of this.handlers) fn(h);\n }\n\n /** 测试用:当前注册数量 */\n get size(): number {\n return this.handlers.length;\n }\n}\n\n/**\n * 串联请求拦截器(LIFO,对齐 axios)。\n *\n * - onFulfilled 必须返回对象(RequestConfig);非对象抛 InvalidInterceptorReturnError\n * - onFulfilled 抛错 → 同管理器的 onRejected 链;某段 onRejected 返回值则恢复正序流程\n * - 仍未消化则向上抛,不发请求\n */\nexport async function runRequestInterceptors(\n manager: InterceptorManager<RequestConfig, RequestConfig>,\n initial: RequestConfig,\n): Promise<RequestConfig> {\n const handlers: InterceptorHandler<RequestConfig, RequestConfig>[] = [];\n manager.forEach((h) => handlers.push(h));\n // 请求拦截器 LIFO(对齐 axios):后注册先执行\n handlers.reverse();\n\n let p: Promise<unknown> = Promise.resolve(initial);\n for (const h of handlers) {\n const onF = h.onFulfilled;\n const onR = h.onRejected;\n p = p.then(\n async (v) => {\n if (!onF) return v;\n const result = await onF(v as RequestConfig);\n if (result === null || typeof result !== 'object') {\n throw new InvalidInterceptorReturnError();\n }\n return result;\n },\n (e) => (onR ? onR(e) : Promise.reject(e)),\n );\n }\n return p as Promise<RequestConfig>;\n}\n\n/**\n * 串联响应拦截器(FIFO,对齐 axios)。\n *\n * - HTTP 非 2xx 或任一 onFulfilled 抛错 → onRejected 链;onRejected 返回值则恢复正序流程\n * - 首段 onFulfilled 接收 ResponseData;后续段接收上一段返回值(类型由用户约束)\n * - 末段返回值即 forge.api() 的 resolve 值\n *\n * @param source 已包含 HTTP 错误转换逻辑的 ResponseData Promise\n * (HTTP 非 2xx 时 reject 为 HTTPError;网络层错误 reject 为 NetworkError)\n */\nexport async function runResponseInterceptors(\n manager: InterceptorManager<ResponseData, unknown>,\n source: Promise<ResponseData>,\n): Promise<unknown> {\n const handlers: InterceptorHandler<ResponseData, unknown>[] = [];\n manager.forEach((h) => handlers.push(h));\n\n let p: Promise<unknown> = source;\n for (const h of handlers) {\n const onF = h.onFulfilled;\n const onR = h.onRejected;\n p = p.then(\n (v) => (onF ? onF(v as ResponseData) : v),\n (e) => (onR ? onR(e) : Promise.reject(e)),\n );\n }\n return p;\n}\n\n/**\n * 工厂函数:供自定义 Fetcher 复用同一套拦截器实现\n * @see .docs/SPEC.md §4.3.3\n */\nexport function createInterceptorManager<TIn, TOut = TIn>(): InterceptorManager<TIn, TOut> {\n return new InterceptorManagerImpl<TIn, TOut>();\n}\n","/**\n * 内置类 axios 精简实现(builtin adapter)\n * @see .docs/SPEC.md §4.3.1\n *\n * 设计目标:\n * - API 兼容 axios(use/eject/clear、request/get/post/...)便于业务代码零成本切换\n * - 拦截器执行顺序对齐 axios(请求 LIFO、响应 FIFO),与 SPEC §4.1.3a 一致\n * - 仅实现 Route Forge 调用链需要的能力:拦截器、JSON、超时、取消\n * - 零依赖,仅基于宿主原生 fetch(Node 18+ / 现代浏览器原生支持)\n * - 体积目标:min+gzip < 3KB,仅作为兜底,不追求覆盖 axios 全部 API\n */\n\nimport type { RequestConfig, ResponseData, InterceptorManager } from '../types.js';\nimport {\n createInterceptorManager,\n runRequestInterceptors,\n runResponseInterceptors,\n} from '../interceptors.js';\n\nexport function createBuiltinHttp(forgeInterceptors?: {\n request: InterceptorManager<RequestConfig, RequestConfig>;\n response: InterceptorManager<ResponseData, unknown>;\n}) {\n const requestMgr = forgeInterceptors?.request ?? createInterceptorManager<RequestConfig>();\n const responseMgr = forgeInterceptors?.response ?? createInterceptorManager<ResponseData>();\n\n async function request(config: RequestConfig): Promise<ResponseData> {\n // 1. 执行请求拦截器(LIFO,对齐 axios)\n const finalConfig = await runRequestInterceptors(requestMgr, config);\n\n // 2. 超时控制:timeout > 0 时用 AbortSignal.timeout\n const signal: AbortSignal | undefined =\n finalConfig.timeout && finalConfig.timeout > 0\n ? AbortSignal.timeout(finalConfig.timeout)\n : undefined;\n\n // 3. paramsSerializer:自定义 query 序列化\n let url = finalConfig.url;\n if (finalConfig.paramsSerializer && finalConfig.params) {\n const qs = finalConfig.paramsSerializer(finalConfig.params);\n if (qs) {\n url = url.includes('?') ? `${url}&${qs}` : `${url}?${qs}`;\n }\n }\n\n // 4. 构建 fetchInit\n const fetchInit: RequestInit = {\n method: finalConfig.method,\n headers: new Headers(finalConfig.headers),\n };\n if (signal) fetchInit.signal = signal;\n if (\n finalConfig.body !== undefined &&\n !['GET', 'HEAD'].includes(finalConfig.method.toUpperCase())\n ) {\n fetchInit.body =\n typeof finalConfig.body === 'string'\n ? finalConfig.body\n : JSON.stringify(finalConfig.body);\n }\n\n // 5. 调用 fetch\n const res = await fetch(url, fetchInit);\n const text = await res.text();\n let data: unknown = text;\n const contentType = res.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n try {\n data = JSON.parse(text);\n } catch {\n /* 保留原始文本 */\n }\n }\n\n // 6. 构建 ResponseData\n const responseData: ResponseData = {\n route: finalConfig.route,\n level: finalConfig.level,\n method: finalConfig.method,\n url,\n status: res.status,\n headers: res.headers,\n data,\n config: finalConfig,\n };\n\n // 7. 执行响应拦截器(FIFO,对齐 axios);末段返回值即 request() 的 resolve 值\n return runResponseInterceptors(\n responseMgr,\n Promise.resolve(responseData),\n ) as Promise<ResponseData>;\n }\n\n // 便捷方法\n const get = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'GET' } as RequestConfig);\n const post = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'POST' } as RequestConfig);\n const put = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'PUT' } as RequestConfig);\n const patch = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'PATCH' } as RequestConfig);\n const del = (url: string, config?: Partial<RequestConfig>) =>\n request({ ...config, url, method: 'DELETE' } as RequestConfig);\n\n return {\n request,\n interceptors: {\n request: requestMgr,\n response: responseMgr,\n },\n runsInterceptors: true,\n get,\n post,\n put,\n patch,\n delete: del,\n };\n}\n","/**\n * 把宿主项目的 axios 实例包装为 Fetcher adapter\n * @see .docs/SPEC.md §4.3.2, §4.3.4\n *\n * 设计约定:\n * - 不接管或修改宿主 axios 已有拦截器/defaults 配置,仅调用其 request 入口\n * - 宿主 axios 的 defaults.baseURL/defaults.headers 自动生效\n * - 宿主已注册的拦截器会先执行;Route Forge 自身拦截器在宿主拦截器之后执行\n * (由 forge.interceptors 注入到宿主 axios 时序)后续阶段填充\n * - 未检测到 axios 时返回 null(让 'auto' 自动降级到 builtin)\n */\n\nimport type { RequestConfig, ResponseData } from '../types.js';\nimport type { ResolvedAdapter } from './index.js';\n\nexport async function wrapAxiosAdapter(): Promise<ResolvedAdapter | null> {\n // ESM 友好的动态探测:尝试 import('axios'),失败则查全局 window.axios\n let axios: any;\n try {\n const mod = await import(/* @vite-ignore */ 'axios');\n axios = mod.default ?? mod;\n } catch {\n if (typeof globalThis !== 'undefined' && (globalThis as any).axios) {\n axios = (globalThis as any).axios;\n }\n }\n if (!axios || typeof axios.request !== 'function') return null;\n\n async function request(config: RequestConfig): Promise<ResponseData> {\n const headers: Record<string, string> = { ...config.headers };\n const res = await axios.request({\n url: config.url,\n method: config.method,\n headers,\n data: config.body,\n // axios 会处理 baseURL/transformRequest 等 defaults\n });\n\n return {\n route: config.route,\n level: config.level,\n method: config.method,\n url: config.url,\n status: res.status,\n headers: new Headers(res.headers ?? {}),\n data: res.data,\n config,\n };\n }\n\n // 不暴露宿主 axios 的 interceptors manager(避免覆盖 Route Forge 的统一时序);\n // Route Forge 调用链由 forge.interceptors 控制,宿主拦截器先执行由 axios 内部保证。\n return { request, interceptors: undefined };\n}\n","/**\n * Adapter 入口\n * @see .docs/SPEC.md §4.3\n *\n * Route Forge 提供三种 adapter:\n * 1. 'auto'(默认):检测到宿主 axios 则用之;否则用内置 builtin adapter\n * 2. 'axios':强制宿主 axios,未安装抛 AdapterNotFoundError\n * 3. 'builtin':强制内置实现\n * 自定义 Fetcher 接口直接传入即可(绕过 auto 检测)。\n */\n\nimport type { Fetcher, InterceptorManager, RequestConfig, ResponseData } from '../types.js';\nimport { AdapterNotFoundError } from '../errors.js';\nimport { createBuiltinHttp } from './builtin-http.js';\nimport { wrapAxiosAdapter } from './axios.js';\n\nexport type ResolvedAdapter = {\n request: (config: RequestConfig) => Promise<ResponseData>;\n interceptors?: Fetcher['interceptors'];\n runsInterceptors?: boolean;\n /**\n * 便捷方法(可选)。\n * - builtin adapter 提供全部 5 个方法\n * - axios / 自定义 Fetcher 可不提供(调用方需先判断存在性)\n * @see .docs/SPEC.md §4.3.1\n */\n get?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n post?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n put?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n patch?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n delete?: (url: string, config?: Partial<RequestConfig>) => Promise<ResponseData>;\n};\n\nexport interface ResolveAdapterOptions {\n adapter: 'auto' | 'axios' | 'builtin' | Fetcher;\n forgeInterceptors?: {\n request: InterceptorManager<RequestConfig, RequestConfig>;\n response: InterceptorManager<ResponseData, unknown>;\n };\n}\n\n/**\n * 解析 adapter 配置;同步阶段尝试 import('axios'),失败则降级。\n * 注意:实际 axios 探测在生产实现里需要 lazy import;此处仅为框架占位。\n */\nexport async function resolveAdapter(opts: ResolveAdapterOptions): Promise<ResolvedAdapter> {\n const { adapter } = opts;\n\n if (adapter && typeof adapter === 'object') {\n return {\n request: (config: RequestConfig) => adapter.request(config),\n interceptors: adapter.interceptors,\n };\n }\n\n if (adapter === 'builtin') {\n return createBuiltinHttp(opts.forgeInterceptors);\n }\n\n if (adapter === 'axios') {\n const wrapped = await wrapAxiosAdapter();\n if (!wrapped) throw new AdapterNotFoundError('axios');\n return wrapped;\n }\n\n // auto: 优先尝试 axios,失败则 builtin\n const wrapped = await wrapAxiosAdapter().catch(() => null);\n if (wrapped) return wrapped;\n return createBuiltinHttp(opts.forgeInterceptors);\n}\n","/**\n * Route Forge 主入口:createRouteForge\n * @see .docs/SPEC.md §4.1.1 ~ §4.1.6\n *\n * 能力清单(v1.0 MVP):\n * - 按层级懒加载与隔离缓存(§4.1.2)\n * - 并发去重(§4.1.4)\n * - 登录态感知(§4.1.5)\n * - 严格模式(§4.1.6)\n * - 通过路由名调用 API(§4.1.3)\n * - 拦截器(§4.1.3a)\n * - Adapter auto 检测 / builtin / axios / 自定义 Fetcher(§4.3)\n */\n\nimport { RouteCache } from './cache.js';\nimport {\n createInterceptorManager,\n InterceptorManagerImpl,\n runRequestInterceptors,\n runResponseInterceptors,\n} from './interceptors.js';\nimport { resolveAdapter } from './adapters/index.js';\nimport {\n AdapterNotFoundError,\n ForgeError,\n HTTPError,\n InsufficientAuthError,\n MissingRouteParamError,\n NetworkError,\n UnknownLevelError,\n UnknownRouteError,\n} from './errors.js';\nimport type {\n ApiCallParams,\n InterceptorManager,\n LevelRoutesResponse,\n RequestConfig,\n ResponseData,\n RouteForge,\n RouteForgeOptions,\n RouteMeta,\n SummaryResponse,\n} from './types.js';\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_CACHE_TTL = 3600;\n\nexport function createRouteForge(options: RouteForgeOptions): RouteForge {\n if (!options.endpoint) throw new TypeError('options.endpoint is required');\n\n const {\n adapter = 'auto',\n timeout = DEFAULT_TIMEOUT,\n baseURL = '',\n auth,\n interceptors: declarativeInterceptors,\n cache: cacheOpts = {},\n } = options;\n\n // --- 自动发现(SPEC §4.1.1 + §5.3)---\n const explicitLevels = options.levels;\n const explicitEager = options.eager;\n const explicitStrict = options.strict ?? false;\n const explicitEndpoint = options.endpoint;\n\n // effective* 状态:在摘要端点响应到达后被填充\n let effectiveLevels: string[] = explicitLevels ?? [];\n let effectiveEager: string[] = explicitEager ?? [];\n let effectiveStrict = explicitStrict;\n let effectiveEndpoint = explicitEndpoint;\n let effectiveUrlPrefix = ''; // 后端下发的 URL 前缀,默认为空\n\n // 拉取摘要端点(用于 strict_mode / endpoint / levels / eager 自动发现)\n const summaryPromise = (async (): Promise<SummaryResponse | null> => {\n try {\n const summaryUrl = explicitEndpoint; // GET {endpoint} = 摘要端点\n const resp = await fetch(summaryUrl, { method: 'GET' });\n if (!resp.ok) {\n console.warn(\n `[route-forge] summary endpoint ${summaryUrl} unreachable (HTTP ${resp.status}); falling back to explicit options`,\n );\n return null;\n }\n return (await resp.json()) as SummaryResponse;\n } catch (e) {\n if (explicitLevels && explicitLevels.length > 0) {\n console.warn(\n `[route-forge] summary endpoint unreachable: ${(e as Error).message}; using explicit levels`,\n );\n return null;\n }\n // 未传 levels 且摘要端点不可达 → 抛 UnknownLevelError\n throw new UnknownLevelError('(auto-discovery)');\n }\n })();\n\n // 自动发现异步填充(不阻塞 createRouteForge 返回)\n const autoDiscoveryPromise = summaryPromise.then((summary) => {\n if (summary === null) {\n return;\n }\n\n // 1. endpoint 后端权威\n if (summary.config.endpoint_prefix && summary.config.endpoint_prefix !== explicitEndpoint) {\n console.warn(\n `[route-forge] backend endpoint_prefix \"${summary.config.endpoint_prefix}\" overrides frontend endpoint \"${explicitEndpoint}\"`,\n );\n effectiveEndpoint = summary.config.endpoint_prefix;\n }\n\n // 1a. url_prefix 后端权威:后端下发时覆盖\n if (summary.config.url_prefix) {\n effectiveUrlPrefix = summary.config.url_prefix.endsWith('/')\n ? summary.config.url_prefix.slice(0, -1)\n : summary.config.url_prefix;\n }\n\n // 2. strict_mode 后端权威:不能放宽,可收紧\n if (summary.config.strict_mode && !explicitStrict) {\n console.warn(\n '[route-forge] backend strict_mode=true overrides frontend strict=false; forcing strict=true',\n );\n effectiveStrict = true;\n }\n\n // 3. levels 取交集或自动发现\n const backendLevels = Object.keys(summary.levels);\n if (explicitLevels && explicitLevels.length > 0) {\n const intersection = explicitLevels.filter((l) => backendLevels.includes(l));\n const removed = explicitLevels.filter((l) => !backendLevels.includes(l));\n if (removed.length > 0) {\n console.warn(\n `[route-forge] levels not in backend summary and dropped: ${removed.join(', ')}`,\n );\n }\n effectiveLevels = intersection;\n } else {\n effectiveLevels = backendLevels;\n }\n\n // 4. eager 未传时取后端 load:'eager' 层级\n if (!explicitEager) {\n effectiveEager = backendLevels.filter((lvl) => summary.levels[lvl]?.load === 'eager');\n }\n });\n\n // 防止 autoDiscoveryPromise 未被 await 时产生 unhandled rejection\n autoDiscoveryPromise.catch(() => {\n /* 自动发现失败:在 load/api await 时会重新抛出 */\n });\n\n const cacheTtl = cacheOpts.ttl ?? DEFAULT_CACHE_TTL;\n const cacheStorage = cacheOpts.storage ?? 'memory';\n const cache = new RouteCache({ storage: cacheStorage, ttl: cacheTtl });\n\n const requestInterceptors: InterceptorManager<RequestConfig, RequestConfig> = new InterceptorManagerImpl();\n const responseInterceptors: InterceptorManager<ResponseData, unknown> = new InterceptorManagerImpl();\n\n // 声明式拦截器先注册(按数组顺序),随后允许运行时 use() 追加\n if (declarativeInterceptors?.request) {\n for (const pair of declarativeInterceptors.request) {\n const [onFulfilled, onRejected] = pair;\n requestInterceptors.use(onFulfilled, onRejected);\n }\n }\n if (declarativeInterceptors?.response) {\n for (const pair of declarativeInterceptors.response) {\n const [onFulfilled, onRejected] = pair;\n responseInterceptors.use(onFulfilled, onRejected);\n }\n }\n\n const adapterPromise = resolveAdapter({\n adapter,\n forgeInterceptors: { request: requestInterceptors, response: responseInterceptors },\n });\n let adapterResolved = false;\n let adapterObj: Awaited<ReturnType<typeof resolveAdapter>> | null = null;\n\n async function ensureAdapter() {\n if (!adapterResolved) {\n adapterObj = await adapterPromise.catch((e) => {\n if (e instanceof AdapterNotFoundError) throw e;\n // 其他错误降级到 builtin(避免初始化失败)\n return resolveAdapter({ adapter: 'builtin' });\n });\n adapterResolved = true;\n }\n return adapterObj!;\n }\n\n const inflight = new Map<string, Promise<void>>();\n\n function isAuthRequired(level: string): boolean {\n return Boolean(auth?.levels?.[level]);\n }\n\n function assertAuth(level: string): void {\n if (isAuthRequired(level) && auth?.state && !auth.state()) {\n throw new InsufficientAuthError(level);\n }\n }\n\n function assertLevelDeclared(level: string): void {\n if (!effectiveLevels.includes(level)) {\n throw new UnknownLevelError(level);\n }\n }\n\n function buildUrl(level: string): string {\n const base = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;\n const ep = effectiveEndpoint.startsWith('/') ? effectiveEndpoint : `/${effectiveEndpoint}`;\n return `${base}${ep}/${encodeURIComponent(level)}`;\n }\n\n async function fetchLevel(level: string): Promise<LevelRoutesResponse> {\n const adp = await ensureAdapter();\n const config: RequestConfig = {\n route: `__forge__.load.${level}`,\n level,\n method: 'GET',\n url: buildUrl(level),\n headers: { Accept: 'application/json' },\n params: {},\n timeout,\n meta: {\n name: `__forge__.load.${level}`,\n uri: buildUrl(level),\n methods: ['GET'],\n parameters: [],\n level,\n },\n };\n // 拉取元信息直接走 adapter(不走 forge.interceptors 链,避免与业务调用混淆)\n const resp = await adp.request(config);\n if (!resp || resp.status < 200 || resp.status >= 300) {\n throw new Error(`Failed to load level ${level}: HTTP ${resp?.status}`);\n }\n const data = resp.data as LevelRoutesResponse;\n // 后端可能下发 cache 字段,让 RouteCache 优先采用\n return data;\n }\n\n async function loadOne(level: string): Promise<void> {\n assertLevelDeclared(level);\n assertAuth(level);\n\n // 缓存命中直接返回\n if (cache.get(level)) return;\n\n // inflight 去重\n const existing = inflight.get(level);\n if (existing) return existing;\n\n const p = (async () => {\n try {\n const resp = await fetchLevel(level);\n cache.set(resp);\n } finally {\n inflight.delete(level);\n }\n })();\n inflight.set(level, p);\n return p;\n }\n\n async function load(level: string | string[]): Promise<void> {\n await autoDiscoveryPromise;\n const list = Array.isArray(level) ? level : [level];\n await Promise.all(list.map(loadOne));\n }\n\n function route(level: string, name: string, params?: Record<string, unknown>): string {\n // 静态生成 URL:仅查已加载缓存,未加载时抛 UnknownRouteError\n const meta = findRouteMeta(level, name);\n if (!meta) {\n throw new UnknownRouteError(name, level);\n }\n return buildRequestUrl(meta, params ?? {});\n }\n\n function buildRequestUrl(meta: RouteMeta, params: Record<string, unknown>): string {\n let uri = meta.uri;\n const defaults = meta.parameter_defaults ?? {};\n const missingRequired: string[] = [];\n for (const p of meta.parameters) {\n let v = params[p];\n // 参数未传时回退到后端下发的默认值\n if ((v === undefined || v === null) && p in defaults) {\n v = defaults[p];\n }\n if (v === undefined || v === null) {\n // 可选参数(URI 中 {param?}):替换为空字符串\n if (uri.includes(`{${p}?}`)) {\n uri = uri.replace(`{${p}?}`, '');\n continue;\n }\n missingRequired.push(p);\n } else {\n // 替换 {param} 或 {param?}\n uri = uri.replace(`{${p}?}`, encodeURIComponent(String(v))).replace(`{${p}}`, encodeURIComponent(String(v)));\n }\n }\n if (missingRequired.length > 0) {\n throw new MissingRouteParamError(meta.name, missingRequired);\n }\n // 清理可选参数移除后残留的连续 / 或尾部 /\n uri = uri.replace(/\\/+/g, '/').replace(/\\/$/, '');\n // url_prefix 含协议(如 https://api.example.com)时直接作为完整基础 URL,跳过 baseURL\n if (effectiveUrlPrefix.includes('://')) {\n const prefix = effectiveUrlPrefix.endsWith('/') ? effectiveUrlPrefix.slice(0, -1) : effectiveUrlPrefix;\n return uri.startsWith('/') ? `${prefix}${uri}` : `${prefix}/${uri}`;\n }\n const base = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;\n const prefix = effectiveUrlPrefix;\n return uri.startsWith('/') ? `${base}${prefix}${uri}` : `${base}${prefix}/${uri}`;\n }\n\n function findRouteMeta(level: string, name: string): RouteMeta | undefined {\n const entry = cache.get(level);\n const meta = entry?.routes[name];\n if (meta) {\n return { ...meta, level };\n }\n return undefined;\n }\n\n async function api(level: string, name: string, params: ApiCallParams = {}): Promise<unknown> {\n await autoDiscoveryPromise;\n // 确保指定层级的路由元信息已加载\n await load(level);\n const meta = findRouteMeta(level, name);\n if (!meta) {\n throw new UnknownRouteError(name, level);\n }\n return doApiCall(meta, params);\n }\n\n async function doApiCall(meta: RouteMeta, params: ApiCallParams): Promise<unknown> {\n assertAuth(meta.level ?? '');\n const { pathParams, query, body, headers } = resolveApiParams(params);\n\n const method = pickMethod(meta);\n const urlWithQuery = appendQuery(buildRequestUrl(meta, pathParams), query);\n const config: RequestConfig = {\n route: meta.name,\n level: meta.level ?? '',\n method,\n url: urlWithQuery,\n headers: { Accept: 'application/json', ...(headers ?? {}) },\n body,\n params: pathParams,\n timeout,\n meta,\n };\n\n const adp = await ensureAdapter();\n\n // 5. 请求拦截链(LIFO,对齐 axios);任一段抛错且 onRejected 未消化 → 进入调用方 catch,不发请求\n // builtin adapter 内部已执行 forge 拦截器(同一管理器对象引用,runsInterceptors=true)→ 跳过\n const finalConfig = adp.runsInterceptors\n ? config\n : await runRequestInterceptors(requestInterceptors, config);\n\n // 6. adapter 调用 → 7/8 的错误转换 + 响应拦截链\n // HTTP 非 2xx 转 HTTPError;底层网络错误(非 ForgeError)转 NetworkError\n // 注意:source 始终构造(含错误转换逻辑),runsInterceptors=true 时直接返回 source\n const source: Promise<ResponseData> = adp.request(finalConfig).then(\n (resp) => {\n if (resp.status < 200 || resp.status >= 300) {\n throw new HTTPError(\n `HTTP ${resp.status} for route \"${resp.route}\" (${resp.method} ${resp.url})`,\n {\n route: resp.route,\n level: resp.level,\n status: resp.status,\n url: resp.url,\n method: resp.method,\n },\n );\n }\n return resp;\n },\n (err) => {\n // 已经是 ForgeError(如拦截器内重新抛的)→ 原样抛\n if (err instanceof ForgeError) throw err;\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n meta.name,\n meta.level,\n err,\n );\n },\n );\n\n // 响应拦截链(FIFO,对齐 axios);末段返回值即 api() resolve 值\n // builtin adapter 内部已执行 forge 响应拦截器(runsInterceptors=true)→ 直接返回 source\n if (adp.runsInterceptors) return source;\n return runResponseInterceptors(responseInterceptors, source);\n }\n\n function invalidate(level?: string): void {\n if (level) cache.del(level);\n else cache.clear();\n }\n\n function isLoaded(level?: string): boolean {\n if (level) return cache.get(level) !== undefined;\n return effectiveLevels.every((lvl) => cache.get(lvl) !== undefined);\n }\n\n function hasRoute(level: string, name: string): boolean {\n return findRouteMeta(level, name) !== undefined;\n }\n\n function getRoutes(level: string): Record<string, RouteMeta>;\n function getRoutes(): Record<string, Record<string, RouteMeta>>;\n function getRoutes(level?: string): Record<string, RouteMeta> | Record<string, Record<string, RouteMeta>> {\n if (level !== undefined) {\n const entry = cache.get(level);\n const routes = entry?.routes ?? {};\n const result: Record<string, RouteMeta> = {};\n for (const [k, v] of Object.entries(routes)) {\n result[k] = { ...v };\n }\n return result;\n }\n const result: Record<string, Record<string, RouteMeta>> = {};\n for (const lvl of effectiveLevels) {\n const entry = cache.get(lvl);\n if (entry) {\n const levelRoutes: Record<string, RouteMeta> = {};\n for (const [k, v] of Object.entries(entry.routes)) {\n levelRoutes[k] = { ...v };\n }\n result[lvl] = levelRoutes;\n }\n }\n return result;\n }\n\n // eager 层级自动加载(不阻塞 createRouteForge 返回;在自动发现完成后触发)\n void autoDiscoveryPromise\n .then(() => {\n if (effectiveEager.length > 0) {\n void Promise.all(effectiveEager.map((lvl) => load(lvl))).catch((e) => {\n console.warn(`[route-forge] eager load failed: ${(e as Error).message}`);\n });\n }\n })\n .catch(() => {\n /* 自动发现失败时不触发 eager */\n });\n\n return {\n api,\n load,\n route,\n url: route,\n invalidate,\n isLoaded,\n hasRoute,\n getRoutes,\n interceptors: {\n request: requestInterceptors,\n response: responseInterceptors,\n },\n };\n}\n\nfunction pickMethod(meta: RouteMeta): string {\n const m = meta.methods.find((x) => x.toUpperCase() !== 'HEAD');\n return (m ?? meta.methods[0] ?? 'GET').toUpperCase();\n}\n\nfunction appendQuery(url: string, query?: Record<string, unknown>): string {\n if (!query) return url;\n const usp = new URLSearchParams();\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n usp.append(k, String(v));\n }\n const qs = usp.toString();\n if (!qs) return url;\n return url.includes('?') ? `${url}&${qs}` : `${url}?${qs}`;\n}\n\n/**\n * 智能解析 ApiCallParams,分离路径参数 / query / body / headers。\n *\n * 规则:\n * 1. `params` 显式指定路径参数 → 优先级最高\n * 2. 平铺的 string | number 值(含与 query/body/headers 同名的 key)→ 路径参数\n * 3. `query` (对象) → 查询参数;`body` (非 string/number) → 请求体;`headers` (对象) → 请求头\n *\n * @see .docs/SPEC.md §4.1.3\n */\nfunction resolveApiParams(input: ApiCallParams): {\n pathParams: Record<string, unknown>;\n query?: Record<string, unknown>;\n body?: unknown;\n headers?: Record<string, string>;\n} {\n const {\n params: explicitParams,\n query: rawQuery,\n body: rawBody,\n headers: rawHeaders,\n ...flatRest\n } = input;\n\n // 1. params 显式指定 → 作为路径参数基础\n const pathParams: Record<string, unknown> = explicitParams\n ? { ...explicitParams }\n : {};\n\n // 2. 其余平铺 key → 路径参数(params 优先,不覆盖已存在的 key)\n for (const [k, v] of Object.entries(flatRest)) {\n if (!(k in pathParams)) {\n pathParams[k] = v;\n }\n }\n\n // 3. 固定 key 智能消解:string/number → 路径参数;对象 → 固定用途\n let query: Record<string, unknown> | undefined;\n let body: unknown;\n let headers: Record<string, string> | undefined;\n\n // query: 对象类型 → 查询参数;string/number → 路径参数\n if (rawQuery !== undefined) {\n if (typeof rawQuery === 'object' && rawQuery !== null) {\n query = rawQuery as Record<string, unknown>;\n } else if (!('query' in pathParams)) {\n pathParams.query = rawQuery;\n }\n }\n\n // body: 非 string/number → 请求体;string/number → 路径参数\n if (rawBody !== undefined) {\n if (typeof rawBody !== 'string' && typeof rawBody !== 'number') {\n body = rawBody;\n } else if (!('body' in pathParams)) {\n pathParams.body = rawBody;\n }\n }\n\n // headers: 对象类型 → 请求头;string/number → 路径参数\n if (rawHeaders !== undefined) {\n if (typeof rawHeaders === 'object' && rawHeaders !== null) {\n headers = rawHeaders as Record<string, string>;\n } else if (!('headers' in pathParams)) {\n pathParams.headers = rawHeaders;\n }\n }\n\n return { pathParams, query, body, headers };\n}\n\n// 显式重导出,便于业务代码按需导入工具件\nexport { createInterceptorManager } from './interceptors.js';\nexport { RouteCache } from './cache.js';\nexport { ForgeError } from './errors.js';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InterceptorManager, a as InterceptorHandler, C as CacheStorage, R as RouteMeta, L as LevelRoutesResponse, b as RouteForgeOptions, c as RouteForge } from './types-UxdZAlmW.cjs';
2
- export { A as AdapterOption, d as ApiCallParams, F as Fetcher, e as RequestConfig, f as ResponseData, S as SummaryResponse } from './types-UxdZAlmW.cjs';
1
+ import { I as InterceptorManager, a as InterceptorHandler, C as CacheStorage, R as RouteMeta, L as LevelRoutesResponse, b as RouteForgeOptions, c as RouteForge } from './types-CBurRtGK.cjs';
2
+ export { A as AdapterOption, d as ApiCallParams, F as Fetcher, e as ForgeApiParams, f as ForgeApiResponse, g as ForgeRouteMap, h as ForgeRouteName, i as RequestConfig, j as ResponseData, S as SummaryResponse } from './types-CBurRtGK.cjs';
3
3
 
4
4
  /**
5
5
  * 拦截器管理器实现
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InterceptorManager, a as InterceptorHandler, C as CacheStorage, R as RouteMeta, L as LevelRoutesResponse, b as RouteForgeOptions, c as RouteForge } from './types-UxdZAlmW.js';
2
- export { A as AdapterOption, d as ApiCallParams, F as Fetcher, e as RequestConfig, f as ResponseData, S as SummaryResponse } from './types-UxdZAlmW.js';
1
+ import { I as InterceptorManager, a as InterceptorHandler, C as CacheStorage, R as RouteMeta, L as LevelRoutesResponse, b as RouteForgeOptions, c as RouteForge } from './types-CBurRtGK.js';
2
+ export { A as AdapterOption, d as ApiCallParams, F as Fetcher, e as ForgeApiParams, f as ForgeApiResponse, g as ForgeRouteMap, h as ForgeRouteName, i as RequestConfig, j as ResponseData, S as SummaryResponse } from './types-CBurRtGK.js';
3
3
 
4
4
  /**
5
5
  * 拦截器管理器实现