@route-forge/core 2.0.0 → 2.2.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
@@ -63,12 +63,28 @@ var RouteCache = class {
63
63
  }
64
64
  return entry;
65
65
  }
66
- set(resp) {
66
+ /**
67
+ * 写入某层级缓存。后端 TTL 唯一来源为摘要 config.cache_ttl(全局),经参数 backendTtl 传入:
68
+ * - null → 后端声明"不缓存":不写 storage,仅留内存镜像供 route() 同步读(load 层"每次重取"由调用方跳过 get 短路实现)
69
+ * - 0 → 永久缓存(内存 + storage)
70
+ * - undefined → 后端未下发该字段:用前端兜底 TTL(options.cache.ttl)
71
+ * - 正整数 → min(后端, 前端兜底):后端为上限,前端只能缩短不能延长(SPEC §5.3)
72
+ */
73
+ set(resp, backendTtl) {
67
74
  let ttl;
68
- if (resp.cache !== void 0 && resp.cache !== null) {
69
- ttl = resp.cache > 0 ? Math.min(resp.cache, this.fallbackTtl) : resp.cache;
70
- } else {
75
+ let persist;
76
+ if (backendTtl === null) {
77
+ ttl = 0;
78
+ persist = false;
79
+ } else if (backendTtl === void 0) {
71
80
  ttl = this.fallbackTtl;
81
+ persist = true;
82
+ } else if (backendTtl === 0) {
83
+ ttl = 0;
84
+ persist = true;
85
+ } else {
86
+ ttl = Math.min(backendTtl, this.fallbackTtl);
87
+ persist = true;
72
88
  }
73
89
  const entry = {
74
90
  level: resp.level,
@@ -77,7 +93,7 @@ var RouteCache = class {
77
93
  cachedAt: Date.now()
78
94
  };
79
95
  this.memory.set(resp.level, entry);
80
- if (this.storage === "memory" || !this.backend) {
96
+ if (!persist || this.storage === "memory" || !this.backend) {
81
97
  return;
82
98
  }
83
99
  try {
@@ -490,39 +506,6 @@ async function resolveAdapter(opts) {
490
506
  return createBuiltinHttp(opts.forgeInterceptors);
491
507
  }
492
508
 
493
- // src/resolveRouteName.ts
494
- async function resolveRouteName(forge, level, prefix, suffix, separator = ".") {
495
- if (!suffix) return prefix;
496
- const joined = `${prefix}${separator}${suffix}`;
497
- if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
498
- await forge.load(level);
499
- if (forge.hasRoute(level, joined)) return joined;
500
- if (forge.hasRoute(level, suffix)) return suffix;
501
- throw new UnknownRouteError(joined, level);
502
- }
503
- function resolveRouteNameSync(forge, level, prefix, suffix, separator = ".") {
504
- if (!suffix) return prefix;
505
- const joined = `${prefix}${separator}${suffix}`;
506
- if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
507
- if (forge.hasRoute(level, joined)) return joined;
508
- if (forge.hasRoute(level, suffix)) return suffix;
509
- throw new UnknownRouteError(joined, level);
510
- }
511
-
512
- // src/defineImmutableProps.ts
513
- function defineImmutableProps(target, props) {
514
- for (const key of Object.keys(props)) {
515
- const val = props[key];
516
- Object.defineProperty(target, key, {
517
- value: val !== null && typeof val === "object" ? Object.freeze(val) : val,
518
- writable: false,
519
- enumerable: false,
520
- configurable: false
521
- });
522
- }
523
- return target;
524
- }
525
-
526
509
  // src/loading.ts
527
510
  var LoadingTracker = class {
528
511
  constructor() {
@@ -582,328 +565,333 @@ var LoadingTracker = class {
582
565
  }
583
566
  };
584
567
 
585
- // src/forge.ts
586
- var DEFAULT_TIMEOUT = 3e4;
587
- var DEFAULT_CACHE_TTL = 3600;
588
- var UNASSIGNED_LEVEL = "unassigned";
589
- function createRouteForge(options) {
590
- if (!options.endpoint) throw new TypeError("options.endpoint is required");
591
- const {
592
- adapter = "auto",
593
- timeout = DEFAULT_TIMEOUT,
594
- baseURL = "",
595
- interceptors: declarativeInterceptors,
596
- cache: cacheOpts = {}
597
- } = options;
598
- const loadingTracker = new LoadingTracker();
599
- const explicitLevels = options.levels;
600
- const explicitEager = options.eager;
601
- const explicitEndpoint = options.endpoint;
602
- let effectiveLevels = explicitLevels ?? [];
603
- let effectiveEager = explicitEager ?? [];
604
- let effectiveEndpoint = explicitEndpoint;
605
- let effectiveUrlPrefix = "";
606
- let summaryUnassigned;
607
- let backendHasUnassignedLevel = false;
608
- const fetchSummary = async () => {
609
- try {
610
- const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
611
- const ep = explicitEndpoint.startsWith("/") ? explicitEndpoint : `/${explicitEndpoint}`;
612
- const data = await fetchMeta("__forge__.summary", `${base}${ep}`);
613
- return data;
614
- } catch (e) {
615
- if (explicitLevels && explicitLevels.length > 0) {
616
- console.warn(
617
- `[route-forge] summary endpoint unreachable: ${e.message}; using explicit levels`
618
- );
619
- return null;
620
- }
621
- throw new UnknownLevelError("(auto-discovery)");
622
- }
623
- };
624
- let summaryPromise;
625
- const summaryWaiters = [];
626
- const whenSummary = () => summaryPromise ?? new Promise((resolve) => summaryWaiters.push(resolve));
627
- const autoDiscoveryPromise = whenSummary().then((summary) => {
628
- if (summary === null) {
629
- return;
630
- }
631
- const schemaVersion = summary.schemaVersion ?? 1;
632
- if (schemaVersion > 1) {
633
- console.warn(
634
- `[route-forge] backend schemaVersion=${schemaVersion} > client supported 1; some features may be unavailable`
635
- );
636
- }
637
- if (summary.config.endpoint_prefix && summary.config.endpoint_prefix !== explicitEndpoint) {
638
- console.warn(
639
- `[route-forge] backend endpoint_prefix "${summary.config.endpoint_prefix}" overrides frontend endpoint "${explicitEndpoint}"`
640
- );
641
- effectiveEndpoint = summary.config.endpoint_prefix;
642
- }
643
- if (summary.config.url_prefix) {
644
- effectiveUrlPrefix = summary.config.url_prefix.endsWith("/") ? summary.config.url_prefix.slice(0, -1) : summary.config.url_prefix;
645
- }
646
- const backendLevels = Object.keys(summary.levels);
647
- backendHasUnassignedLevel = backendLevels.includes(UNASSIGNED_LEVEL);
648
- if (Array.isArray(summary.unassigned) && summary.unassigned.length > 0 && !backendHasUnassignedLevel) {
649
- summaryUnassigned = summary.unassigned;
650
- }
651
- const availableLevels = backendLevels.slice();
652
- if (summaryUnassigned && !backendHasUnassignedLevel) {
653
- availableLevels.push(UNASSIGNED_LEVEL);
568
+ // src/url-builder.ts
569
+ function buildUrl(level, ctx) {
570
+ const base = ctx.baseURL.endsWith("/") ? ctx.baseURL.slice(0, -1) : ctx.baseURL;
571
+ const ep = ctx.endpoint.startsWith("/") ? ctx.endpoint : `/${ctx.endpoint}`;
572
+ return `${base}${ep}/${encodeURIComponent(level)}`;
573
+ }
574
+ function buildRequestUrl(meta, params, ctx) {
575
+ const defaults = meta.parameter_defaults ?? {};
576
+ const missingRequired = [];
577
+ const values = {};
578
+ for (const p of meta.parameters) {
579
+ let v = params[p];
580
+ if ((v === void 0 || v === null) && p in defaults) {
581
+ v = defaults[p];
654
582
  }
655
- if (explicitLevels && explicitLevels.length > 0) {
656
- const intersection = explicitLevels.filter((l) => availableLevels.includes(l));
657
- const removed = explicitLevels.filter((l) => !availableLevels.includes(l));
658
- if (removed.length > 0) {
659
- console.warn(
660
- `[route-forge] levels not in backend summary and dropped: ${removed.join(", ")}`
661
- );
583
+ if (v === void 0 || v === null) {
584
+ if (!meta.uri.includes(`{${p}?}`)) {
585
+ missingRequired.push(p);
662
586
  }
663
- effectiveLevels = intersection;
664
587
  } else {
665
- effectiveLevels = availableLevels;
588
+ values[p] = v;
666
589
  }
667
- const backendEager = backendLevels.filter((lvl) => summary.levels[lvl]?.load === "eager");
668
- if (!explicitEager) {
669
- effectiveEager = backendEager;
670
- } else {
671
- const union = /* @__PURE__ */ new Set([...backendEager, ...explicitEager]);
672
- effectiveEager = [...union];
590
+ }
591
+ if (missingRequired.length > 0) {
592
+ throw new MissingRouteParamError(meta.name, missingRequired);
593
+ }
594
+ let uri = meta.uri.replace(/\{([^{}]+)\}/g, (match, raw) => {
595
+ const optional = raw.endsWith("?");
596
+ const name = optional ? raw.slice(0, -1) : raw;
597
+ if (values[name] !== void 0) {
598
+ const val = values[name];
599
+ if (typeof val === "object") {
600
+ throw new ForgeError(
601
+ `Path parameter "${name}" must be a primitive value (string, number, boolean), got ${typeof val}`,
602
+ { code: "RF_FE_003", route: meta.name, context: { param: name, value: val } }
603
+ );
604
+ }
605
+ return encodeURIComponent(String(val));
673
606
  }
607
+ return optional ? "" : match;
674
608
  });
675
- let autoDiscoveryError = null;
676
- autoDiscoveryPromise.catch((e) => {
677
- autoDiscoveryError = e;
678
- });
679
- let autoDiscoveryCompleted = false;
680
- let resolveReady;
681
- let rejectReady;
682
- const readyPromise = new Promise((resolve, reject) => {
683
- resolveReady = resolve;
684
- rejectReady = reject;
685
- });
686
- readyPromise.catch(() => {
687
- });
688
- const cacheTtl = cacheOpts.ttl ?? DEFAULT_CACHE_TTL;
689
- const cacheStorage = cacheOpts.storage ?? "memory";
690
- const cache = new RouteCache({ storage: cacheStorage, ttl: cacheTtl });
691
- const requestInterceptors = new InterceptorManagerImpl();
692
- const responseInterceptors = new InterceptorManagerImpl();
693
- if (declarativeInterceptors?.request) {
694
- for (const entry of declarativeInterceptors.request) {
695
- if (typeof entry === "function") {
696
- requestInterceptors.use(entry);
697
- } else {
698
- const [onFulfilled, onRejected] = entry;
699
- requestInterceptors.use(onFulfilled, onRejected);
700
- }
609
+ uri = uri.replace(/\/+/g, "/").replace(/\/$/, "");
610
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(ctx.urlPrefix)) {
611
+ const prefix2 = ctx.urlPrefix.endsWith("/") ? ctx.urlPrefix.slice(0, -1) : ctx.urlPrefix;
612
+ return uri.startsWith("/") ? `${prefix2}${uri}` : `${prefix2}/${uri}`;
613
+ }
614
+ const base = ctx.baseURL.endsWith("/") ? ctx.baseURL.slice(0, -1) : ctx.baseURL;
615
+ const prefix = ctx.urlPrefix;
616
+ return uri.startsWith("/") ? `${base}${prefix}${uri}` : `${base}${prefix}/${uri}`;
617
+ }
618
+ function pickMethod(meta) {
619
+ const m = meta.methods.find((x) => x.toUpperCase() !== "HEAD");
620
+ return (m ?? meta.methods[0] ?? "GET").toUpperCase();
621
+ }
622
+ function appendQuery(url, query) {
623
+ if (!query) return url;
624
+ const usp = new URLSearchParams();
625
+ for (const [k, v] of Object.entries(query)) {
626
+ if (v === void 0 || v === null) continue;
627
+ usp.append(k, String(v));
628
+ }
629
+ const qs = usp.toString();
630
+ if (!qs) return url;
631
+ return url.includes("?") ? `${url}&${qs}` : `${url}?${qs}`;
632
+ }
633
+ function resolveApiParams(input) {
634
+ const {
635
+ params: explicitParams,
636
+ query: rawQuery,
637
+ body: rawBody,
638
+ headers: rawHeaders,
639
+ timeout: perCallTimeout,
640
+ ...flatRest
641
+ } = input;
642
+ const pathParams = explicitParams ? { ...explicitParams } : {};
643
+ for (const [k, v] of Object.entries(flatRest)) {
644
+ if (!(k in pathParams)) {
645
+ pathParams[k] = v;
701
646
  }
702
647
  }
703
- if (declarativeInterceptors?.response) {
704
- for (const entry of declarativeInterceptors.response) {
705
- if (typeof entry === "function") {
706
- responseInterceptors.use(entry);
707
- } else {
708
- const [onFulfilled, onRejected] = entry;
709
- responseInterceptors.use(onFulfilled, onRejected);
710
- }
648
+ let query;
649
+ let body;
650
+ let headers;
651
+ if (rawQuery !== void 0) {
652
+ if (typeof rawQuery === "object" && rawQuery !== null) {
653
+ query = rawQuery;
654
+ } else if (!("query" in pathParams)) {
655
+ pathParams.query = rawQuery;
711
656
  }
712
657
  }
713
- const adapterPromise = resolveAdapter({
714
- adapter,
715
- forgeInterceptors: { request: requestInterceptors, response: responseInterceptors }
716
- });
717
- Promise.resolve().then(() => {
718
- summaryPromise = fetchSummary();
719
- for (const resolve of summaryWaiters) resolve(summaryPromise);
720
- });
721
- let adapterResolved = false;
722
- let adapterObj = null;
723
- async function ensureAdapter() {
724
- if (!adapterResolved) {
725
- adapterObj = await adapterPromise.catch((e) => {
726
- if (e instanceof AdapterNotFoundError) throw e;
727
- return resolveAdapter({
728
- adapter: "builtin",
729
- forgeInterceptors: { request: requestInterceptors, response: responseInterceptors }
730
- });
731
- });
732
- adapterResolved = true;
658
+ if (rawBody !== void 0) {
659
+ if (typeof rawBody !== "string" && typeof rawBody !== "number") {
660
+ body = rawBody;
661
+ } else if (!("body" in pathParams)) {
662
+ pathParams.body = rawBody;
733
663
  }
734
- return adapterObj;
735
664
  }
736
- const inflight = /* @__PURE__ */ new Map();
737
- const invalidationGens = /* @__PURE__ */ new Map();
738
- function assertLevelDeclared(level) {
739
- if (!effectiveLevels.includes(level)) {
740
- throw new UnknownLevelError(level);
665
+ if (rawHeaders !== void 0) {
666
+ if (typeof rawHeaders === "object" && rawHeaders !== null) {
667
+ headers = rawHeaders;
668
+ } else if (!("headers" in pathParams)) {
669
+ pathParams.headers = rawHeaders;
741
670
  }
742
671
  }
743
- function assertDiscoveryReady() {
744
- if (!autoDiscoveryCompleted && !explicitLevels?.length) {
745
- throw new ForgeError(
746
- "Route data not available. Auto-discovery has not completed. Use forge.ready() or forge.use(level) first.",
747
- { code: "RF_FE_010" }
672
+ return { pathParams, query, body, headers, timeout: perCallTimeout };
673
+ }
674
+
675
+ // src/auto-discovery.ts
676
+ async function fetchSummary(inputs, baseURL, fetchMeta) {
677
+ const { explicitLevels, explicitEndpoint } = inputs;
678
+ if (!explicitEndpoint) {
679
+ throw new UnknownLevelError("(auto-discovery)");
680
+ }
681
+ try {
682
+ const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
683
+ const ep = explicitEndpoint.startsWith("/") ? explicitEndpoint : `/${explicitEndpoint}`;
684
+ const data = await fetchMeta("__forge__.summary", `${base}${ep}`);
685
+ return data;
686
+ } catch (e) {
687
+ if (explicitLevels && explicitLevels.length > 0) {
688
+ console.warn(
689
+ `[route-forge] summary endpoint unreachable: ${e.message}; using explicit levels`
748
690
  );
691
+ return null;
749
692
  }
693
+ throw new UnknownLevelError("(auto-discovery)");
750
694
  }
751
- function buildUrl(level) {
752
- const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
753
- const ep = effectiveEndpoint.startsWith("/") ? effectiveEndpoint : `/${effectiveEndpoint}`;
754
- return `${base}${ep}/${encodeURIComponent(level)}`;
695
+ }
696
+ function normalizeCacheTtl(raw) {
697
+ if (typeof raw === "number" && raw < 0) return null;
698
+ return raw;
699
+ }
700
+ function applySummaryToState(summary, state, inputs) {
701
+ const { explicitLevels, explicitEager, explicitEndpoint } = inputs;
702
+ const schemeVersion = summary.schemeVersion ?? 1;
703
+ if (schemeVersion > 1) {
704
+ console.warn(
705
+ `[route-forge] backend schemeVersion=${schemeVersion} > client supported 1; some features may be unavailable`
706
+ );
755
707
  }
756
- async function fetchMeta(routeTag, url, level = "") {
757
- const adp = await ensureAdapter();
758
- const config = {
759
- route: routeTag,
760
- level,
761
- method: "GET",
762
- url,
763
- headers: { Accept: "application/json" },
764
- params: {},
765
- timeout,
766
- meta: {
767
- name: routeTag,
768
- uri: url,
769
- methods: ["GET"],
770
- parameters: [],
771
- level
772
- }
773
- };
774
- const doRawRequest = adp.requestRaw ?? adp.request;
775
- const resp = await doRawRequest(config);
776
- if (!resp || resp.status < 200 || resp.status >= 300) {
777
- throw new HTTPError(
778
- `Failed to fetch "${routeTag}": HTTP ${resp?.status}`,
779
- { level, status: resp?.status, url, method: "GET" }
708
+ if (summary.config.endpoint_prefix && summary.config.endpoint_prefix !== explicitEndpoint) {
709
+ if (explicitEndpoint) {
710
+ console.warn(
711
+ `[route-forge] backend endpoint_prefix "${summary.config.endpoint_prefix}" overrides frontend endpoint "${explicitEndpoint}"`
780
712
  );
781
713
  }
782
- return resp.data;
714
+ state.endpoint = summary.config.endpoint_prefix;
715
+ }
716
+ if (summary.config.url_prefix) {
717
+ state.urlPrefix = summary.config.url_prefix.endsWith("/") ? summary.config.url_prefix.slice(0, -1) : summary.config.url_prefix;
718
+ }
719
+ state.cacheTtl = normalizeCacheTtl(summary.config.cache_ttl);
720
+ const backendLevels = Object.keys(summary.levels);
721
+ const levelRoutes = {};
722
+ for (const lvl of backendLevels) {
723
+ const r = summary.levels[lvl]?.route;
724
+ if (r && typeof r.uri === "string") {
725
+ levelRoutes[lvl] = { uri: r.uri, methods: r.methods ?? ["GET", "HEAD"] };
726
+ }
727
+ }
728
+ state.levelRoutes = levelRoutes;
729
+ if (explicitLevels && explicitLevels.length > 0) {
730
+ const intersection = explicitLevels.filter((l) => backendLevels.includes(l));
731
+ const removed = explicitLevels.filter((l) => !backendLevels.includes(l));
732
+ if (removed.length > 0) {
733
+ console.warn(
734
+ `[route-forge] levels not in backend summary and dropped: ${removed.join(", ")}`
735
+ );
736
+ }
737
+ state.levels = intersection;
738
+ } else {
739
+ state.levels = backendLevels.slice();
740
+ }
741
+ const backendEager = backendLevels.filter((lvl) => summary.levels[lvl]?.load === "eager");
742
+ if (!explicitEager) {
743
+ state.eager = backendEager;
744
+ } else {
745
+ const union = /* @__PURE__ */ new Set([...backendEager, ...explicitEager]);
746
+ state.eager = [...union];
747
+ }
748
+ }
749
+
750
+ // src/embedded-summary.ts
751
+ var EMBEDDED_GLOBAL_KEY = "__ROUTE_FORGE__";
752
+ var memo;
753
+ function readEmbeddedSummary() {
754
+ if (memo !== void 0) return memo;
755
+ if (typeof window === "undefined") {
756
+ memo = null;
757
+ return null;
758
+ }
759
+ let raw;
760
+ try {
761
+ raw = window[EMBEDDED_GLOBAL_KEY];
762
+ } catch {
763
+ raw = void 0;
764
+ }
765
+ memo = raw !== null && typeof raw === "object" ? raw : null;
766
+ return memo;
767
+ }
768
+
769
+ // src/route-store.ts
770
+ var RouteStore = class {
771
+ constructor(deps) {
772
+ this.inflight = /* @__PURE__ */ new Map();
773
+ /** 每个层级的失效代数,用于检测 loadOne 期间是否发生了 invalidate */
774
+ this.invalidationGens = /* @__PURE__ */ new Map();
775
+ this.cache = deps.cache;
776
+ this.state = deps.state;
777
+ this.baseURL = deps.baseURL;
778
+ this.fetchMeta = deps.fetchMeta;
779
+ this.autoDiscoveryPromise = deps.autoDiscoveryPromise;
780
+ this.getAutoDiscoveryError = deps.getAutoDiscoveryError;
781
+ }
782
+ assertLevelDeclared(level) {
783
+ if (!this.state.levels.includes(level)) {
784
+ throw new UnknownLevelError(level);
785
+ }
783
786
  }
784
- async function fetchLevel(level) {
785
- return await fetchMeta(`__forge__.load.${level}`, buildUrl(level), level);
787
+ async fetchLevel(level) {
788
+ const uri = this.state.levelRoutes[level]?.uri;
789
+ const url = uri ? this.joinBaseAndPath(this.baseURL, uri) : buildUrl(level, { baseURL: this.baseURL, endpoint: this.state.endpoint });
790
+ return await this.fetchMeta(`route-forge.${level}`, url, level);
791
+ }
792
+ /** baseURL 与后端下发的绝对 path 拼接(规范化斜杠),与 buildUrl 的 base 处理一致 */
793
+ joinBaseAndPath(baseURL, path) {
794
+ const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
795
+ const p = path.startsWith("/") ? path : `/${path}`;
796
+ return `${base}${p}`;
786
797
  }
787
- async function loadOne(level) {
798
+ async loadOne(level) {
799
+ const autoDiscoveryError = this.getAutoDiscoveryError();
788
800
  if (autoDiscoveryError) throw autoDiscoveryError;
789
- assertLevelDeclared(level);
790
- if (cache.get(level)) return;
791
- const existing = inflight.get(level);
801
+ this.assertLevelDeclared(level);
802
+ const noCache = this.state.cacheTtl === null;
803
+ if (!noCache && this.cache.get(level)) return;
804
+ const existing = this.inflight.get(level);
792
805
  if (existing) return existing;
793
- const gen = invalidationGens.get(level) ?? 0;
806
+ const gen = this.invalidationGens.get(level) ?? 0;
794
807
  const p = (async () => {
795
808
  try {
796
- if (level === UNASSIGNED_LEVEL && !backendHasUnassignedLevel && summaryUnassigned) {
797
- const routes = {};
798
- for (const r of summaryUnassigned) {
799
- routes[r.name] = { ...r, level: UNASSIGNED_LEVEL };
800
- }
801
- cache.set({ level: UNASSIGNED_LEVEL, routes, cache: null });
802
- return;
803
- }
804
- const resp = await fetchLevel(level);
805
- if ((invalidationGens.get(level) ?? 0) === gen) {
806
- cache.set(resp);
809
+ const resp = await this.fetchLevel(level);
810
+ if ((this.invalidationGens.get(level) ?? 0) === gen) {
811
+ this.cache.set(resp, this.state.cacheTtl);
807
812
  }
808
813
  } finally {
809
- inflight.delete(level);
814
+ this.inflight.delete(level);
810
815
  }
811
816
  })();
812
- inflight.set(level, p);
817
+ this.inflight.set(level, p);
813
818
  return p;
814
819
  }
815
- async function load(level) {
816
- await autoDiscoveryPromise;
820
+ async load(level) {
821
+ await this.autoDiscoveryPromise;
817
822
  const list = Array.isArray(level) ? level : [level];
818
- await Promise.all(list.map(loadOne));
823
+ await Promise.all(list.map((l) => this.loadOne(l)));
819
824
  }
820
- function route(level, name, params) {
821
- assertDiscoveryReady();
822
- const meta = findRouteMeta(level, name);
823
- if (!meta) {
824
- throw new UnknownRouteError(name, level);
825
- }
826
- return buildRequestUrl(meta, params ?? {});
827
- }
828
- function buildRequestUrl(meta, params) {
829
- const defaults = meta.parameter_defaults ?? {};
830
- const missingRequired = [];
831
- const values = {};
832
- for (const p of meta.parameters) {
833
- let v = params[p];
834
- if ((v === void 0 || v === null) && p in defaults) {
835
- v = defaults[p];
825
+ invalidate(level) {
826
+ if (level === void 0) {
827
+ this.cache.clear();
828
+ this.inflight.clear();
829
+ for (const lvl of this.state.levels) {
830
+ this.invalidationGens.set(lvl, (this.invalidationGens.get(lvl) ?? 0) + 1);
836
831
  }
837
- if (v === void 0 || v === null) {
838
- if (!meta.uri.includes(`{${p}?}`)) {
839
- missingRequired.push(p);
840
- }
841
- } else {
842
- values[p] = v;
832
+ } else if (Array.isArray(level)) {
833
+ for (const lvl of level) {
834
+ this.cache.del(lvl);
835
+ this.inflight.delete(lvl);
836
+ this.invalidationGens.set(lvl, (this.invalidationGens.get(lvl) ?? 0) + 1);
843
837
  }
838
+ } else {
839
+ this.cache.del(level);
840
+ this.inflight.delete(level);
841
+ this.invalidationGens.set(level, (this.invalidationGens.get(level) ?? 0) + 1);
844
842
  }
845
- if (missingRequired.length > 0) {
846
- throw new MissingRouteParamError(meta.name, missingRequired);
847
- }
848
- let uri = meta.uri.replace(/\{([^{}]+)\}/g, (match, raw) => {
849
- const optional = raw.endsWith("?");
850
- const name = optional ? raw.slice(0, -1) : raw;
851
- if (values[name] !== void 0) {
852
- const val = values[name];
853
- if (typeof val === "object") {
854
- throw new ForgeError(
855
- `Path parameter "${name}" must be a primitive value (string, number, boolean), got ${typeof val}`,
856
- { code: "RF_FE_003", route: meta.name, context: { param: name, value: val } }
857
- );
858
- }
859
- return encodeURIComponent(String(val));
860
- }
861
- return optional ? "" : match;
862
- });
863
- uri = uri.replace(/\/+/g, "/").replace(/\/$/, "");
864
- if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(effectiveUrlPrefix)) {
865
- const prefix2 = effectiveUrlPrefix.endsWith("/") ? effectiveUrlPrefix.slice(0, -1) : effectiveUrlPrefix;
866
- return uri.startsWith("/") ? `${prefix2}${uri}` : `${prefix2}/${uri}`;
867
- }
868
- const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
869
- const prefix = effectiveUrlPrefix;
870
- return uri.startsWith("/") ? `${base}${prefix}${uri}` : `${base}${prefix}/${uri}`;
871
843
  }
872
- function findRouteMeta(level, name) {
873
- const entry = cache.get(level);
844
+ isLoaded(level) {
845
+ if (level) return this.cache.get(level) !== void 0;
846
+ return this.state.levels.length > 0 && this.state.levels.every((lvl) => this.cache.get(lvl) !== void 0);
847
+ }
848
+ findRouteMeta(level, name) {
849
+ const entry = this.cache.get(level);
874
850
  const meta = entry?.routes[name];
875
851
  if (meta) {
876
852
  return { ...meta, level };
877
853
  }
878
854
  return void 0;
879
855
  }
880
- function api(level, name, params = {}) {
881
- let ctrl;
882
- let abortedBeforeInit = false;
883
- let abortReason;
884
- const work = (async () => {
885
- ctrl = new AbortController();
886
- if (abortedBeforeInit) {
887
- ctrl.abort(abortReason);
888
- }
889
- await autoDiscoveryPromise;
890
- await load(level);
891
- const meta = findRouteMeta(level, name);
892
- if (!meta) {
893
- throw new UnknownRouteError(name, level);
856
+ getRoutes(level) {
857
+ if (level !== void 0) {
858
+ const entry = this.cache.get(level);
859
+ const routes = entry?.routes ?? {};
860
+ const result2 = {};
861
+ for (const [k, v] of Object.entries(routes)) {
862
+ result2[k] = JSON.parse(JSON.stringify(v));
894
863
  }
895
- return doApiCall(meta, params, ctrl.signal);
896
- })();
897
- const request = work;
898
- request.abort = () => {
899
- if (ctrl) {
900
- ctrl.abort();
901
- } else {
902
- abortedBeforeInit = true;
864
+ return result2;
865
+ }
866
+ const result = {};
867
+ for (const lvl of this.state.levels) {
868
+ const entry = this.cache.get(lvl);
869
+ if (entry) {
870
+ const levelRoutes = {};
871
+ for (const [k, v] of Object.entries(entry.routes)) {
872
+ levelRoutes[k] = JSON.parse(JSON.stringify(v));
873
+ }
874
+ result[lvl] = levelRoutes;
903
875
  }
904
- };
905
- return request;
876
+ }
877
+ return result;
906
878
  }
879
+ };
880
+
881
+ // src/http-runner.ts
882
+ function createHttpRunner(deps) {
883
+ const {
884
+ ensureAdapter,
885
+ requestInterceptors,
886
+ responseInterceptors,
887
+ load,
888
+ findRouteMeta,
889
+ baseURL,
890
+ state,
891
+ timeout,
892
+ loadingTracker,
893
+ autoDiscoveryPromise
894
+ } = deps;
907
895
  async function doApiCall(meta, params, signal) {
908
896
  const {
909
897
  pathParams,
@@ -916,7 +904,10 @@ function createRouteForge(options) {
916
904
  throw new RequestAbortedError(meta.name, meta.level, signal.reason);
917
905
  }
918
906
  const method = pickMethod(meta);
919
- const urlWithQuery = appendQuery(buildRequestUrl(meta, pathParams), query);
907
+ const urlWithQuery = appendQuery(
908
+ buildRequestUrl(meta, pathParams, { baseURL, urlPrefix: state.urlPrefix }),
909
+ query
910
+ );
920
911
  const config = {
921
912
  route: meta.name,
922
913
  level: meta.level ?? "",
@@ -971,88 +962,77 @@ function createRouteForge(options) {
971
962
  loadingTracker.stop();
972
963
  }
973
964
  }
974
- function invalidate(level) {
975
- if (level === void 0) {
976
- cache.clear();
977
- inflight.clear();
978
- for (const lvl of effectiveLevels) {
979
- invalidationGens.set(lvl, (invalidationGens.get(lvl) ?? 0) + 1);
980
- }
981
- } else if (Array.isArray(level)) {
982
- for (const lvl of level) {
983
- cache.del(lvl);
984
- inflight.delete(lvl);
985
- invalidationGens.set(lvl, (invalidationGens.get(lvl) ?? 0) + 1);
965
+ return function api(level, name, params = {}) {
966
+ let ctrl;
967
+ let abortedBeforeInit = false;
968
+ let abortReason;
969
+ const work = (async () => {
970
+ ctrl = new AbortController();
971
+ if (abortedBeforeInit) {
972
+ ctrl.abort(abortReason);
986
973
  }
987
- } else {
988
- cache.del(level);
989
- inflight.delete(level);
990
- invalidationGens.set(level, (invalidationGens.get(level) ?? 0) + 1);
991
- }
992
- }
993
- function isLoaded(level) {
994
- if (level) return cache.get(level) !== void 0;
995
- return effectiveLevels.length > 0 && effectiveLevels.every((lvl) => cache.get(lvl) !== void 0);
996
- }
997
- function hasRoute(level, name) {
998
- assertDiscoveryReady();
999
- return findRouteMeta(level, name) !== void 0;
1000
- }
1001
- function getRoutes(level) {
1002
- if (level !== void 0) {
1003
- const entry = cache.get(level);
1004
- const routes = entry?.routes ?? {};
1005
- const result2 = {};
1006
- for (const [k, v] of Object.entries(routes)) {
1007
- result2[k] = JSON.parse(JSON.stringify(v));
974
+ await autoDiscoveryPromise;
975
+ await load(level);
976
+ const meta = findRouteMeta(level, name);
977
+ if (!meta) {
978
+ throw new UnknownRouteError(name, level);
1008
979
  }
1009
- return result2;
1010
- }
1011
- const result = {};
1012
- for (const lvl of effectiveLevels) {
1013
- const entry = cache.get(lvl);
1014
- if (entry) {
1015
- const levelRoutes = {};
1016
- for (const [k, v] of Object.entries(entry.routes)) {
1017
- levelRoutes[k] = JSON.parse(JSON.stringify(v));
1018
- }
1019
- result[lvl] = levelRoutes;
980
+ return doApiCall(meta, params, ctrl.signal);
981
+ })();
982
+ const request = work;
983
+ request.abort = () => {
984
+ if (ctrl) {
985
+ ctrl.abort();
986
+ } else {
987
+ abortedBeforeInit = true;
1020
988
  }
1021
- }
1022
- return result;
1023
- }
1024
- void autoDiscoveryPromise.then(() => {
1025
- autoDiscoveryCompleted = true;
1026
- if (effectiveEager.length > 0) {
1027
- return Promise.allSettled(effectiveEager.map((lvl) => load(lvl))).then((results) => {
1028
- results.forEach((r, i) => {
1029
- if (r.status === "rejected") {
1030
- console.error(
1031
- `[route-forge] eager load failed for level "${effectiveEager[i]}":`,
1032
- r.reason
1033
- );
1034
- }
1035
- });
1036
- });
1037
- }
1038
- }).then(() => {
1039
- resolveReady(forgeInstance);
1040
- }).catch((e) => {
1041
- rejectReady(e);
1042
- });
1043
- function ready(onFulfilled, onRejected) {
1044
- if (onFulfilled) {
1045
- const p = readyPromise.then(onFulfilled, onRejected);
1046
- return p.then(() => forgeInstance);
1047
- }
1048
- return readyPromise;
989
+ };
990
+ return request;
991
+ };
992
+ }
993
+
994
+ // src/resolveRouteName.ts
995
+ async function resolveRouteName(forge, level, prefix, suffix, separator = ".") {
996
+ if (!suffix) return prefix;
997
+ const joined = `${prefix}${separator}${suffix}`;
998
+ if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
999
+ await forge.load(level);
1000
+ if (forge.hasRoute(level, joined)) return joined;
1001
+ if (forge.hasRoute(level, suffix)) return suffix;
1002
+ throw new UnknownRouteError(joined, level);
1003
+ }
1004
+ function resolveRouteNameSync(forge, level, prefix, suffix, separator = ".") {
1005
+ if (!suffix) return prefix;
1006
+ const joined = `${prefix}${separator}${suffix}`;
1007
+ if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
1008
+ if (forge.hasRoute(level, joined)) return joined;
1009
+ if (forge.hasRoute(level, suffix)) return suffix;
1010
+ throw new UnknownRouteError(joined, level);
1011
+ }
1012
+
1013
+ // src/defineImmutableProps.ts
1014
+ function defineImmutableProps(target, props) {
1015
+ for (const key of Object.keys(props)) {
1016
+ const val = props[key];
1017
+ Object.defineProperty(target, key, {
1018
+ value: val !== null && typeof val === "object" ? Object.freeze(val) : val,
1019
+ writable: false,
1020
+ enumerable: false,
1021
+ configurable: false
1022
+ });
1049
1023
  }
1050
- const forgeResolver = { load, hasRoute };
1024
+ return target;
1025
+ }
1026
+
1027
+ // src/bound-forge.ts
1028
+ function createBoundForgeFactory(deps) {
1029
+ const { load, api, route, hasRoute, getRoutes, invalidate, isLoaded, loadingTracker } = deps;
1030
+ const resolver = { load, hasRoute };
1051
1031
  function createBoundForge(level, prefix) {
1052
1032
  const levelLoadedPromise = load(level);
1053
1033
  levelLoadedPromise.catch(() => {
1054
1034
  });
1055
- const apiFn = prefix ? (name, params) => resolveRouteName(forgeResolver, level, prefix, name).then(
1035
+ const apiFn = prefix ? (name, params) => resolveRouteName(resolver, level, prefix, name).then(
1056
1036
  (resolved) => api(level, resolved, params)
1057
1037
  ) : (name, params) => api(level, name, params);
1058
1038
  const callable = apiFn;
@@ -1060,8 +1040,8 @@ function createRouteForge(options) {
1060
1040
  level,
1061
1041
  ...prefix !== void 0 ? { prefix } : {},
1062
1042
  api: apiFn,
1063
- route: prefix ? (name, params) => route(level, resolveRouteNameSync(forgeResolver, level, prefix, name), params) : (name, params) => route(level, name, params),
1064
- url: prefix ? (name, params) => route(level, resolveRouteNameSync(forgeResolver, level, prefix, name), params) : (name, params) => route(level, name, params),
1043
+ route: prefix ? (name, params) => route(level, resolveRouteNameSync(resolver, level, prefix, name), params) : (name, params) => route(level, name, params),
1044
+ url: prefix ? (name, params) => route(level, resolveRouteNameSync(resolver, level, prefix, name), params) : (name, params) => route(level, name, params),
1065
1045
  hasRoute: (name) => hasRoute(level, name),
1066
1046
  getRoutes: () => getRoutes(level),
1067
1047
  load: () => load(level),
@@ -1105,6 +1085,220 @@ function createRouteForge(options) {
1105
1085
  attachBoundMethods(bound, levelLoadedPromise, level);
1106
1086
  return bound;
1107
1087
  }
1088
+ return createBoundForgeWithMethods;
1089
+ }
1090
+
1091
+ // src/forge.ts
1092
+ var DEFAULT_TIMEOUT = 3e4;
1093
+ var DEFAULT_CACHE_TTL = 3600;
1094
+ function createRouteForge(options) {
1095
+ const bootstrapSummary = readEmbeddedSummary() ?? options.summary ?? null;
1096
+ if (!bootstrapSummary && !options.endpoint) {
1097
+ throw new TypeError(
1098
+ "createRouteForge: \u9700\u8981 options.endpoint\uFF0C\u6216 options.summary\uFF0C\u6216\u9875\u9762\u5185\u5D4C window.__ROUTE_FORGE__"
1099
+ );
1100
+ }
1101
+ const {
1102
+ adapter = "auto",
1103
+ timeout = DEFAULT_TIMEOUT,
1104
+ baseURL = "",
1105
+ interceptors: declarativeInterceptors,
1106
+ cache: cacheOpts = {}
1107
+ } = options;
1108
+ const loadingTracker = new LoadingTracker();
1109
+ const explicitLevels = options.levels;
1110
+ const explicitEager = options.eager;
1111
+ const explicitEndpoint = options.endpoint;
1112
+ const discoveryState = {
1113
+ levels: explicitLevels ?? [],
1114
+ eager: explicitEager ?? [],
1115
+ endpoint: explicitEndpoint ?? bootstrapSummary?.config?.endpoint_prefix ?? "",
1116
+ urlPrefix: "",
1117
+ cacheTtl: void 0,
1118
+ levelRoutes: {}
1119
+ };
1120
+ const discoveryInputs = { explicitLevels, explicitEager, explicitEndpoint };
1121
+ let autoDiscoveryCompleted = false;
1122
+ let resolveReady;
1123
+ let rejectReady;
1124
+ const readyPromise = new Promise((resolve, reject) => {
1125
+ resolveReady = resolve;
1126
+ rejectReady = reject;
1127
+ });
1128
+ readyPromise.catch(() => {
1129
+ });
1130
+ const cacheTtl = cacheOpts.ttl ?? DEFAULT_CACHE_TTL;
1131
+ const cacheStorage = cacheOpts.storage ?? "memory";
1132
+ const cache = new RouteCache({ storage: cacheStorage, ttl: cacheTtl });
1133
+ const requestInterceptors = new InterceptorManagerImpl();
1134
+ const responseInterceptors = new InterceptorManagerImpl();
1135
+ if (declarativeInterceptors?.request) {
1136
+ for (const entry of declarativeInterceptors.request) {
1137
+ if (typeof entry === "function") {
1138
+ requestInterceptors.use(entry);
1139
+ } else {
1140
+ const [onFulfilled, onRejected] = entry;
1141
+ requestInterceptors.use(onFulfilled, onRejected);
1142
+ }
1143
+ }
1144
+ }
1145
+ if (declarativeInterceptors?.response) {
1146
+ for (const entry of declarativeInterceptors.response) {
1147
+ if (typeof entry === "function") {
1148
+ responseInterceptors.use(entry);
1149
+ } else {
1150
+ const [onFulfilled, onRejected] = entry;
1151
+ responseInterceptors.use(onFulfilled, onRejected);
1152
+ }
1153
+ }
1154
+ }
1155
+ const adapterPromise = resolveAdapter({
1156
+ adapter,
1157
+ forgeInterceptors: { request: requestInterceptors, response: responseInterceptors }
1158
+ });
1159
+ let adapterResolved = false;
1160
+ let adapterObj = null;
1161
+ async function ensureAdapter() {
1162
+ if (!adapterResolved) {
1163
+ adapterObj = await adapterPromise.catch((e) => {
1164
+ if (e instanceof AdapterNotFoundError) throw e;
1165
+ return resolveAdapter({
1166
+ adapter: "builtin",
1167
+ forgeInterceptors: { request: requestInterceptors, response: responseInterceptors }
1168
+ });
1169
+ });
1170
+ adapterResolved = true;
1171
+ }
1172
+ return adapterObj;
1173
+ }
1174
+ function assertDiscoveryReady() {
1175
+ if (!autoDiscoveryCompleted && !explicitLevels?.length) {
1176
+ throw new ForgeError(
1177
+ "Route data not available. Auto-discovery has not completed. Use forge.ready() or forge.use(level) first.",
1178
+ { code: "RF_FE_010" }
1179
+ );
1180
+ }
1181
+ }
1182
+ async function fetchMeta(routeTag, url, level = "") {
1183
+ const adp = await ensureAdapter();
1184
+ const config = {
1185
+ route: routeTag,
1186
+ level,
1187
+ method: "GET",
1188
+ url,
1189
+ headers: { Accept: "application/json" },
1190
+ params: {},
1191
+ timeout,
1192
+ meta: {
1193
+ name: routeTag,
1194
+ uri: url,
1195
+ methods: ["GET"],
1196
+ parameters: [],
1197
+ level
1198
+ }
1199
+ };
1200
+ const doRawRequest = adp.requestRaw ?? adp.request;
1201
+ const resp = await doRawRequest(config);
1202
+ if (!resp || resp.status < 200 || resp.status >= 300) {
1203
+ throw new HTTPError(
1204
+ `Failed to fetch "${routeTag}": HTTP ${resp?.status}`,
1205
+ { level, status: resp?.status, url, method: "GET" }
1206
+ );
1207
+ }
1208
+ return resp.data;
1209
+ }
1210
+ let autoDiscoveryPromise;
1211
+ if (bootstrapSummary) {
1212
+ applySummaryToState(bootstrapSummary, discoveryState, discoveryInputs);
1213
+ autoDiscoveryCompleted = true;
1214
+ autoDiscoveryPromise = Promise.resolve();
1215
+ } else {
1216
+ autoDiscoveryPromise = fetchSummary(discoveryInputs, baseURL, fetchMeta).then((summary) => {
1217
+ if (summary === null) {
1218
+ return;
1219
+ }
1220
+ applySummaryToState(summary, discoveryState, discoveryInputs);
1221
+ });
1222
+ }
1223
+ let autoDiscoveryError = null;
1224
+ autoDiscoveryPromise.catch((e) => {
1225
+ autoDiscoveryError = e;
1226
+ });
1227
+ const store = new RouteStore({
1228
+ cache,
1229
+ state: discoveryState,
1230
+ baseURL,
1231
+ fetchMeta,
1232
+ autoDiscoveryPromise,
1233
+ getAutoDiscoveryError: () => autoDiscoveryError
1234
+ });
1235
+ const load = (level) => store.load(level);
1236
+ const findRouteMeta = (level, name) => store.findRouteMeta(level, name);
1237
+ const invalidate = (level) => store.invalidate(level);
1238
+ const isLoaded = (level) => store.isLoaded(level);
1239
+ function getRoutes(level) {
1240
+ return level === void 0 ? store.getRoutes() : store.getRoutes(level);
1241
+ }
1242
+ function route(level, name, params) {
1243
+ assertDiscoveryReady();
1244
+ const meta = findRouteMeta(level, name);
1245
+ if (!meta) {
1246
+ throw new UnknownRouteError(name, level);
1247
+ }
1248
+ return buildRequestUrl(meta, params ?? {}, { baseURL, urlPrefix: discoveryState.urlPrefix });
1249
+ }
1250
+ const api = createHttpRunner({
1251
+ ensureAdapter,
1252
+ requestInterceptors,
1253
+ responseInterceptors,
1254
+ load,
1255
+ findRouteMeta,
1256
+ baseURL,
1257
+ state: discoveryState,
1258
+ timeout,
1259
+ loadingTracker,
1260
+ autoDiscoveryPromise
1261
+ });
1262
+ function hasRoute(level, name) {
1263
+ assertDiscoveryReady();
1264
+ return findRouteMeta(level, name) !== void 0;
1265
+ }
1266
+ void autoDiscoveryPromise.then(() => {
1267
+ autoDiscoveryCompleted = true;
1268
+ if (discoveryState.eager.length > 0) {
1269
+ return Promise.allSettled(discoveryState.eager.map((lvl) => load(lvl))).then((results) => {
1270
+ results.forEach((r, i) => {
1271
+ if (r.status === "rejected") {
1272
+ console.error(
1273
+ `[route-forge] eager load failed for level "${discoveryState.eager[i]}":`,
1274
+ r.reason
1275
+ );
1276
+ }
1277
+ });
1278
+ });
1279
+ }
1280
+ }).then(() => {
1281
+ resolveReady(forgeInstance);
1282
+ }).catch((e) => {
1283
+ rejectReady(e);
1284
+ });
1285
+ function ready(onFulfilled, onRejected) {
1286
+ if (onFulfilled) {
1287
+ const p = readyPromise.then(onFulfilled, onRejected);
1288
+ return p.then(() => forgeInstance);
1289
+ }
1290
+ return readyPromise;
1291
+ }
1292
+ const createBoundForgeWithMethods = createBoundForgeFactory({
1293
+ load,
1294
+ api,
1295
+ route,
1296
+ hasRoute,
1297
+ getRoutes,
1298
+ invalidate,
1299
+ isLoaded,
1300
+ loadingTracker
1301
+ });
1108
1302
  const forgeInstance = {
1109
1303
  api,
1110
1304
  load,
@@ -1128,62 +1322,6 @@ function createRouteForge(options) {
1128
1322
  };
1129
1323
  return forgeInstance;
1130
1324
  }
1131
- function pickMethod(meta) {
1132
- const m = meta.methods.find((x) => x.toUpperCase() !== "HEAD");
1133
- return (m ?? meta.methods[0] ?? "GET").toUpperCase();
1134
- }
1135
- function appendQuery(url, query) {
1136
- if (!query) return url;
1137
- const usp = new URLSearchParams();
1138
- for (const [k, v] of Object.entries(query)) {
1139
- if (v === void 0 || v === null) continue;
1140
- usp.append(k, String(v));
1141
- }
1142
- const qs = usp.toString();
1143
- if (!qs) return url;
1144
- return url.includes("?") ? `${url}&${qs}` : `${url}?${qs}`;
1145
- }
1146
- function resolveApiParams(input) {
1147
- const {
1148
- params: explicitParams,
1149
- query: rawQuery,
1150
- body: rawBody,
1151
- headers: rawHeaders,
1152
- timeout: perCallTimeout,
1153
- ...flatRest
1154
- } = input;
1155
- const pathParams = explicitParams ? { ...explicitParams } : {};
1156
- for (const [k, v] of Object.entries(flatRest)) {
1157
- if (!(k in pathParams)) {
1158
- pathParams[k] = v;
1159
- }
1160
- }
1161
- let query;
1162
- let body;
1163
- let headers;
1164
- if (rawQuery !== void 0) {
1165
- if (typeof rawQuery === "object" && rawQuery !== null) {
1166
- query = rawQuery;
1167
- } else if (!("query" in pathParams)) {
1168
- pathParams.query = rawQuery;
1169
- }
1170
- }
1171
- if (rawBody !== void 0) {
1172
- if (typeof rawBody !== "string" && typeof rawBody !== "number") {
1173
- body = rawBody;
1174
- } else if (!("body" in pathParams)) {
1175
- pathParams.body = rawBody;
1176
- }
1177
- }
1178
- if (rawHeaders !== void 0) {
1179
- if (typeof rawHeaders === "object" && rawHeaders !== null) {
1180
- headers = rawHeaders;
1181
- } else if (!("headers" in pathParams)) {
1182
- pathParams.headers = rawHeaders;
1183
- }
1184
- }
1185
- return { pathParams, query, body, headers, timeout: perCallTimeout };
1186
- }
1187
1325
 
1188
1326
  exports.AdapterNotFoundError = AdapterNotFoundError;
1189
1327
  exports.ForgeError = ForgeError;