@route-forge/core 1.1.0 → 1.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/README.md +55 -3
- package/dist/codegen.d.cts +1 -1
- package/dist/codegen.d.ts +1 -1
- package/dist/defineImmutableProps.cjs +19 -0
- package/dist/defineImmutableProps.cjs.map +1 -0
- package/dist/defineImmutableProps.d.cts +10 -0
- package/dist/defineImmutableProps.d.ts +10 -0
- package/dist/defineImmutableProps.js +17 -0
- package/dist/defineImmutableProps.js.map +1 -0
- package/dist/index.cjs +87 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -3
- package/dist/index.d.ts +34 -3
- package/dist/index.js +86 -10
- package/dist/index.js.map +1 -1
- package/dist/route-forge.global.js +1094 -0
- package/dist/route-forge.global.js.map +1 -0
- package/dist/route-forge.global.min.js +2 -0
- package/dist/{types-pHQLqpYF.d.cts → types-CMouq7zD.d.cts} +104 -1
- package/dist/{types-pHQLqpYF.d.ts → types-CMouq7zD.d.ts} +104 -1
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -186,11 +186,63 @@ unsub()
|
|
|
186
186
|
|
|
187
187
|
> 加载状态始终跟踪,用户不使用则不订阅即可。Vue/React 包可通过 `onLoadingChange` 订阅状态变更驱动组件显隐。
|
|
188
188
|
|
|
189
|
+
## 初始化合时序与推荐模式
|
|
190
|
+
|
|
191
|
+
### 三种加载状态
|
|
192
|
+
|
|
193
|
+
| 类型 | 说明 | 跟踪方式 |
|
|
194
|
+
|----------------|--------------------------------|-----------------------------|
|
|
195
|
+
| Auto-discovery | 拉取摘要端点发现 levels/config | 内部 `autoDiscoveryPromise` |
|
|
196
|
+
| Level load | 拉取某层级路由元数据 | `forge.isLoaded(level)` |
|
|
197
|
+
| API request | 业务接口请求 | `forge.isLoading()` |
|
|
198
|
+
|
|
199
|
+
### `onSummaryReady` 回调
|
|
200
|
+
|
|
201
|
+
推荐在回调中挂载应用,确保路由数据就绪:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const forge = createRouteForge({
|
|
205
|
+
endpoint: '/_forge/routes',
|
|
206
|
+
onSummaryReady: () => {
|
|
207
|
+
// 摘要端点完成,路由数据已可用
|
|
208
|
+
app.mount('#app')
|
|
209
|
+
},
|
|
210
|
+
})
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### `forge.ready` Promise
|
|
214
|
+
|
|
215
|
+
auto-discovery + eager load 完成后 resolve,适合 async/await 风格:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
const forge = createRouteForge({ endpoint: '/_forge/routes' })
|
|
219
|
+
await forge.ready
|
|
220
|
+
// 路由数据已就绪,可安全调用 route() / hasRoute()
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### `onLevelLoaded` 订阅
|
|
224
|
+
|
|
225
|
+
订阅指定 level 加载完成事件:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
const unsub = forge.onLevelLoaded('admin', () => {
|
|
229
|
+
console.log('admin level loaded')
|
|
230
|
+
})
|
|
231
|
+
// 取消订阅
|
|
232
|
+
unsub()
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Auto-discovery 守卫
|
|
236
|
+
|
|
237
|
+
`route()` / `hasRoute()` 在 auto-discovery 未完成且无 explicit levels 时抛出
|
|
238
|
+
`ForgeError (RF_FE_010)`, 防止在路由数据未就绪时返回错误结果。`api()` 不受影响(内部自动 await
|
|
239
|
+
discovery)。
|
|
240
|
+
|
|
189
241
|
## 文档
|
|
190
242
|
|
|
191
|
-
- 仓库主页: https://github.com/
|
|
192
|
-
- 设计文档: https://github.com/
|
|
193
|
-
- 规范: https://github.com/
|
|
243
|
+
- 仓库主页: https://github.com/route-forge/route-forge
|
|
244
|
+
- 设计文档: https://github.com/route-forge/route-forge/blob/main/.docs/DESIGN.md
|
|
245
|
+
- 规范: https://github.com/route-forge/route-forge/blob/main/.docs/SPEC.md
|
|
194
246
|
|
|
195
247
|
## License
|
|
196
248
|
|
package/dist/codegen.d.cts
CHANGED
package/dist/codegen.d.ts
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/defineImmutableProps.ts
|
|
4
|
+
function defineImmutableProps(target, props) {
|
|
5
|
+
for (const key of Object.keys(props)) {
|
|
6
|
+
const val = props[key];
|
|
7
|
+
Object.defineProperty(target, key, {
|
|
8
|
+
value: val !== null && typeof val === "object" ? Object.freeze(val) : val,
|
|
9
|
+
writable: false,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
configurable: false
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return target;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.defineImmutableProps = defineImmutableProps;
|
|
18
|
+
//# sourceMappingURL=defineImmutableProps.cjs.map
|
|
19
|
+
//# sourceMappingURL=defineImmutableProps.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/defineImmutableProps.ts"],"names":[],"mappings":";;;AAOO,SAAS,oBAAA,CAAuC,QAAW,KAAA,EAAmC;AACnG,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACpC,IAAA,MAAM,GAAA,GAAM,MAAM,GAAG,CAAA;AACrB,IAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,GAAA,EAAK;AAAA,MACjC,KAAA,EAAO,QAAQ,IAAA,IAAQ,OAAO,QAAQ,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,GAAI,GAAA;AAAA,MACtE,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,KAAA;AAAA,MACZ,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT","file":"defineImmutableProps.cjs","sourcesContent":["/**\n * 以不可变、不可枚举、不可重配置的方式将属性挂载到目标对象上。\n * 相比 Object.assign 更安全——外部无法通过遍历/删除/重写篡改这些方法。\n * 对象类型的值会浅冻结(Object.freeze),防止内部键被增删改。\n *\n * @internal 仅供框架适配层(vue/react)内部使用,不作为公共 API 导出\n */\nexport function defineImmutableProps<T extends object>(target: T, props: Record<string, unknown>): T {\n for (const key of Object.keys(props)) {\n const val = props[key];\n Object.defineProperty(target, key, {\n value: val !== null && typeof val === 'object' ? Object.freeze(val) : val,\n writable: false,\n enumerable: false,\n configurable: false,\n });\n }\n return target;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 以不可变、不可枚举、不可重配置的方式将属性挂载到目标对象上。
|
|
3
|
+
* 相比 Object.assign 更安全——外部无法通过遍历/删除/重写篡改这些方法。
|
|
4
|
+
* 对象类型的值会浅冻结(Object.freeze),防止内部键被增删改。
|
|
5
|
+
*
|
|
6
|
+
* @internal 仅供框架适配层(vue/react)内部使用,不作为公共 API 导出
|
|
7
|
+
*/
|
|
8
|
+
declare function defineImmutableProps<T extends object>(target: T, props: Record<string, unknown>): T;
|
|
9
|
+
|
|
10
|
+
export { defineImmutableProps };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 以不可变、不可枚举、不可重配置的方式将属性挂载到目标对象上。
|
|
3
|
+
* 相比 Object.assign 更安全——外部无法通过遍历/删除/重写篡改这些方法。
|
|
4
|
+
* 对象类型的值会浅冻结(Object.freeze),防止内部键被增删改。
|
|
5
|
+
*
|
|
6
|
+
* @internal 仅供框架适配层(vue/react)内部使用,不作为公共 API 导出
|
|
7
|
+
*/
|
|
8
|
+
declare function defineImmutableProps<T extends object>(target: T, props: Record<string, unknown>): T;
|
|
9
|
+
|
|
10
|
+
export { defineImmutableProps };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/defineImmutableProps.ts
|
|
2
|
+
function defineImmutableProps(target, props) {
|
|
3
|
+
for (const key of Object.keys(props)) {
|
|
4
|
+
const val = props[key];
|
|
5
|
+
Object.defineProperty(target, key, {
|
|
6
|
+
value: val !== null && typeof val === "object" ? Object.freeze(val) : val,
|
|
7
|
+
writable: false,
|
|
8
|
+
enumerable: false,
|
|
9
|
+
configurable: false
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return target;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { defineImmutableProps };
|
|
16
|
+
//# sourceMappingURL=defineImmutableProps.js.map
|
|
17
|
+
//# sourceMappingURL=defineImmutableProps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/defineImmutableProps.ts"],"names":[],"mappings":";AAOO,SAAS,oBAAA,CAAuC,QAAW,KAAA,EAAmC;AACnG,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACpC,IAAA,MAAM,GAAA,GAAM,MAAM,GAAG,CAAA;AACrB,IAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,GAAA,EAAK;AAAA,MACjC,KAAA,EAAO,QAAQ,IAAA,IAAQ,OAAO,QAAQ,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,GAAI,GAAA;AAAA,MACtE,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,KAAA;AAAA,MACZ,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT","file":"defineImmutableProps.js","sourcesContent":["/**\n * 以不可变、不可枚举、不可重配置的方式将属性挂载到目标对象上。\n * 相比 Object.assign 更安全——外部无法通过遍历/删除/重写篡改这些方法。\n * 对象类型的值会浅冻结(Object.freeze),防止内部键被增删改。\n *\n * @internal 仅供框架适配层(vue/react)内部使用,不作为公共 API 导出\n */\nexport function defineImmutableProps<T extends object>(target: T, props: Record<string, unknown>): T {\n for (const key of Object.keys(props)) {\n const val = props[key];\n Object.defineProperty(target, key, {\n value: val !== null && typeof val === 'object' ? Object.freeze(val) : val,\n writable: false,\n enumerable: false,\n configurable: false,\n });\n }\n return target;\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -389,10 +389,11 @@ function toHeaders(raw) {
|
|
|
389
389
|
}
|
|
390
390
|
async function wrapAxiosAdapter() {
|
|
391
391
|
let axios;
|
|
392
|
+
const axiosModule = "axios";
|
|
392
393
|
try {
|
|
393
394
|
const mod = await import(
|
|
394
395
|
/* @vite-ignore */
|
|
395
|
-
|
|
396
|
+
axiosModule
|
|
396
397
|
);
|
|
397
398
|
axios = mod.default ?? mod;
|
|
398
399
|
} catch {
|
|
@@ -623,8 +624,16 @@ function createRouteForge(options) {
|
|
|
623
624
|
effectiveEager = [...union];
|
|
624
625
|
}
|
|
625
626
|
});
|
|
626
|
-
|
|
627
|
+
let autoDiscoveryError = null;
|
|
628
|
+
autoDiscoveryPromise.catch((e) => {
|
|
629
|
+
autoDiscoveryError = e;
|
|
627
630
|
});
|
|
631
|
+
let autoDiscoveryCompleted = false;
|
|
632
|
+
let resolveReady;
|
|
633
|
+
const readyPromise = new Promise((resolve) => {
|
|
634
|
+
resolveReady = resolve;
|
|
635
|
+
});
|
|
636
|
+
const levelLoadedListeners = /* @__PURE__ */ new Map();
|
|
628
637
|
const cacheTtl = cacheOpts.ttl ?? DEFAULT_CACHE_TTL;
|
|
629
638
|
const cacheStorage = cacheOpts.storage ?? "memory";
|
|
630
639
|
const cache = new RouteCache({ storage: cacheStorage, ttl: cacheTtl });
|
|
@@ -667,11 +676,20 @@ function createRouteForge(options) {
|
|
|
667
676
|
return adapterObj;
|
|
668
677
|
}
|
|
669
678
|
const inflight = /* @__PURE__ */ new Map();
|
|
679
|
+
const invalidationGens = /* @__PURE__ */ new Map();
|
|
670
680
|
function assertLevelDeclared(level) {
|
|
671
681
|
if (!effectiveLevels.includes(level)) {
|
|
672
682
|
throw new UnknownLevelError(level);
|
|
673
683
|
}
|
|
674
684
|
}
|
|
685
|
+
function assertDiscoveryReady() {
|
|
686
|
+
if (!autoDiscoveryCompleted && !explicitLevels?.length) {
|
|
687
|
+
throw new ForgeError(
|
|
688
|
+
"Route data not available. Auto-discovery has not completed. Use onSummaryReady callback to mount app, or await forge.ready / forge.load(level) first.",
|
|
689
|
+
{ code: "RF_FE_010" }
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
675
693
|
function buildUrl(level) {
|
|
676
694
|
const base = baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL;
|
|
677
695
|
const ep = effectiveEndpoint.startsWith("/") ? effectiveEndpoint : `/${effectiveEndpoint}`;
|
|
@@ -706,10 +724,12 @@ function createRouteForge(options) {
|
|
|
706
724
|
return data;
|
|
707
725
|
}
|
|
708
726
|
async function loadOne(level) {
|
|
727
|
+
if (autoDiscoveryError) throw autoDiscoveryError;
|
|
709
728
|
assertLevelDeclared(level);
|
|
710
729
|
if (cache.get(level)) return;
|
|
711
730
|
const existing = inflight.get(level);
|
|
712
731
|
if (existing) return existing;
|
|
732
|
+
const gen = invalidationGens.get(level) ?? 0;
|
|
713
733
|
const p = (async () => {
|
|
714
734
|
try {
|
|
715
735
|
if (level === UNASSIGNED_LEVEL && !backendHasUnassignedLevel && summaryUnassigned) {
|
|
@@ -718,10 +738,16 @@ function createRouteForge(options) {
|
|
|
718
738
|
routes[r.name] = { ...r, level: UNASSIGNED_LEVEL };
|
|
719
739
|
}
|
|
720
740
|
cache.set({ level: UNASSIGNED_LEVEL, routes, cache: null });
|
|
741
|
+
const listeners = levelLoadedListeners.get(level);
|
|
742
|
+
if (listeners) listeners.forEach((cb) => cb());
|
|
721
743
|
return;
|
|
722
744
|
}
|
|
723
745
|
const resp = await fetchLevel(level);
|
|
724
|
-
|
|
746
|
+
if ((invalidationGens.get(level) ?? 0) === gen) {
|
|
747
|
+
cache.set(resp);
|
|
748
|
+
const listeners = levelLoadedListeners.get(level);
|
|
749
|
+
if (listeners) listeners.forEach((cb) => cb());
|
|
750
|
+
}
|
|
725
751
|
} finally {
|
|
726
752
|
inflight.delete(level);
|
|
727
753
|
}
|
|
@@ -735,6 +761,7 @@ function createRouteForge(options) {
|
|
|
735
761
|
await Promise.all(list.map(loadOne));
|
|
736
762
|
}
|
|
737
763
|
function route(level, name, params) {
|
|
764
|
+
assertDiscoveryReady();
|
|
738
765
|
const meta = findRouteMeta(level, name);
|
|
739
766
|
if (!meta) {
|
|
740
767
|
throw new UnknownRouteError(name, level);
|
|
@@ -765,12 +792,19 @@ function createRouteForge(options) {
|
|
|
765
792
|
const optional = raw.endsWith("?");
|
|
766
793
|
const name = optional ? raw.slice(0, -1) : raw;
|
|
767
794
|
if (values[name] !== void 0) {
|
|
768
|
-
|
|
795
|
+
const val = values[name];
|
|
796
|
+
if (typeof val === "object") {
|
|
797
|
+
throw new ForgeError(
|
|
798
|
+
`Path parameter "${name}" must be a primitive value (string, number, boolean), got ${typeof val}`,
|
|
799
|
+
{ code: "RF_FE_003", route: meta.name, context: { param: name, value: val } }
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
return encodeURIComponent(String(val));
|
|
769
803
|
}
|
|
770
804
|
return optional ? "" : match;
|
|
771
805
|
});
|
|
772
806
|
uri = uri.replace(/\/+/g, "/").replace(/\/$/, "");
|
|
773
|
-
if (effectiveUrlPrefix
|
|
807
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(effectiveUrlPrefix)) {
|
|
774
808
|
const prefix2 = effectiveUrlPrefix.endsWith("/") ? effectiveUrlPrefix.slice(0, -1) : effectiveUrlPrefix;
|
|
775
809
|
return uri.startsWith("/") ? `${prefix2}${uri}` : `${prefix2}/${uri}`;
|
|
776
810
|
}
|
|
@@ -866,10 +900,20 @@ function createRouteForge(options) {
|
|
|
866
900
|
function invalidate(level) {
|
|
867
901
|
if (level === void 0) {
|
|
868
902
|
cache.clear();
|
|
903
|
+
inflight.clear();
|
|
904
|
+
for (const lvl of effectiveLevels) {
|
|
905
|
+
invalidationGens.set(lvl, (invalidationGens.get(lvl) ?? 0) + 1);
|
|
906
|
+
}
|
|
869
907
|
} else if (Array.isArray(level)) {
|
|
870
|
-
for (const lvl of level)
|
|
908
|
+
for (const lvl of level) {
|
|
909
|
+
cache.del(lvl);
|
|
910
|
+
inflight.delete(lvl);
|
|
911
|
+
invalidationGens.set(lvl, (invalidationGens.get(lvl) ?? 0) + 1);
|
|
912
|
+
}
|
|
871
913
|
} else {
|
|
872
914
|
cache.del(level);
|
|
915
|
+
inflight.delete(level);
|
|
916
|
+
invalidationGens.set(level, (invalidationGens.get(level) ?? 0) + 1);
|
|
873
917
|
}
|
|
874
918
|
}
|
|
875
919
|
function isLoaded(level) {
|
|
@@ -877,6 +921,7 @@ function createRouteForge(options) {
|
|
|
877
921
|
return effectiveLevels.length > 0 && effectiveLevels.every((lvl) => cache.get(lvl) !== void 0);
|
|
878
922
|
}
|
|
879
923
|
function hasRoute(level, name) {
|
|
924
|
+
assertDiscoveryReady();
|
|
880
925
|
return findRouteMeta(level, name) !== void 0;
|
|
881
926
|
}
|
|
882
927
|
function getRoutes(level) {
|
|
@@ -885,7 +930,7 @@ function createRouteForge(options) {
|
|
|
885
930
|
const routes = entry?.routes ?? {};
|
|
886
931
|
const result2 = {};
|
|
887
932
|
for (const [k, v] of Object.entries(routes)) {
|
|
888
|
-
result2[k] =
|
|
933
|
+
result2[k] = JSON.parse(JSON.stringify(v));
|
|
889
934
|
}
|
|
890
935
|
return result2;
|
|
891
936
|
}
|
|
@@ -895,7 +940,7 @@ function createRouteForge(options) {
|
|
|
895
940
|
if (entry) {
|
|
896
941
|
const levelRoutes = {};
|
|
897
942
|
for (const [k, v] of Object.entries(entry.routes)) {
|
|
898
|
-
levelRoutes[k] =
|
|
943
|
+
levelRoutes[k] = JSON.parse(JSON.stringify(v));
|
|
899
944
|
}
|
|
900
945
|
result[lvl] = levelRoutes;
|
|
901
946
|
}
|
|
@@ -903,11 +948,15 @@ function createRouteForge(options) {
|
|
|
903
948
|
return result;
|
|
904
949
|
}
|
|
905
950
|
void autoDiscoveryPromise.then(() => {
|
|
951
|
+
options.onSummaryReady?.();
|
|
906
952
|
if (effectiveEager.length > 0) {
|
|
907
|
-
|
|
953
|
+
return Promise.all(effectiveEager.map((lvl) => load(lvl))).catch((e) => {
|
|
908
954
|
console.warn(`[route-forge] eager load failed: ${e.message}`);
|
|
909
955
|
});
|
|
910
956
|
}
|
|
957
|
+
}).then(() => {
|
|
958
|
+
autoDiscoveryCompleted = true;
|
|
959
|
+
resolveReady();
|
|
911
960
|
}).catch(() => {
|
|
912
961
|
});
|
|
913
962
|
return {
|
|
@@ -924,6 +973,14 @@ function createRouteForge(options) {
|
|
|
924
973
|
interceptors: {
|
|
925
974
|
request: requestInterceptors,
|
|
926
975
|
response: responseInterceptors
|
|
976
|
+
},
|
|
977
|
+
ready: readyPromise,
|
|
978
|
+
onLevelLoaded(level, cb) {
|
|
979
|
+
if (!levelLoadedListeners.has(level)) {
|
|
980
|
+
levelLoadedListeners.set(level, /* @__PURE__ */ new Set());
|
|
981
|
+
}
|
|
982
|
+
levelLoadedListeners.get(level).add(cb);
|
|
983
|
+
return () => levelLoadedListeners.get(level)?.delete(cb);
|
|
927
984
|
}
|
|
928
985
|
};
|
|
929
986
|
}
|
|
@@ -993,6 +1050,25 @@ function isAbortError2(err, signal) {
|
|
|
993
1050
|
return false;
|
|
994
1051
|
}
|
|
995
1052
|
|
|
1053
|
+
// src/resolveRouteName.ts
|
|
1054
|
+
async function resolveRouteName(forge, level, prefix, suffix, separator = ".") {
|
|
1055
|
+
if (!suffix) return prefix;
|
|
1056
|
+
const joined = `${prefix}${separator}${suffix}`;
|
|
1057
|
+
if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
|
|
1058
|
+
await forge.load(level);
|
|
1059
|
+
if (forge.hasRoute(level, joined)) return joined;
|
|
1060
|
+
if (forge.hasRoute(level, suffix)) return suffix;
|
|
1061
|
+
throw new UnknownRouteError(joined, level);
|
|
1062
|
+
}
|
|
1063
|
+
function resolveRouteNameSync(forge, level, prefix, suffix, separator = ".") {
|
|
1064
|
+
if (!suffix) return prefix;
|
|
1065
|
+
const joined = `${prefix}${separator}${suffix}`;
|
|
1066
|
+
if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
|
|
1067
|
+
if (forge.hasRoute(level, joined)) return joined;
|
|
1068
|
+
if (forge.hasRoute(level, suffix)) return suffix;
|
|
1069
|
+
throw new UnknownRouteError(joined, level);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
996
1072
|
exports.AdapterNotFoundError = AdapterNotFoundError;
|
|
997
1073
|
exports.ForgeError = ForgeError;
|
|
998
1074
|
exports.HTTPError = HTTPError;
|
|
@@ -1007,5 +1083,7 @@ exports.UnknownLevelError = UnknownLevelError;
|
|
|
1007
1083
|
exports.UnknownRouteError = UnknownRouteError;
|
|
1008
1084
|
exports.createInterceptorManager = createInterceptorManager;
|
|
1009
1085
|
exports.createRouteForge = createRouteForge;
|
|
1086
|
+
exports.resolveRouteName = resolveRouteName;
|
|
1087
|
+
exports.resolveRouteNameSync = resolveRouteNameSync;
|
|
1010
1088
|
//# sourceMappingURL=index.cjs.map
|
|
1011
1089
|
//# sourceMappingURL=index.cjs.map
|