@route-forge/core 1.2.2 → 1.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.
@@ -468,6 +468,39 @@ var RouteForge = (function (exports) {
468
468
  return createBuiltinHttp(opts.forgeInterceptors);
469
469
  }
470
470
 
471
+ // src/resolveRouteName.ts
472
+ async function resolveRouteName(forge, level, prefix, suffix, separator = ".") {
473
+ if (!suffix) return prefix;
474
+ const joined = `${prefix}${separator}${suffix}`;
475
+ if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
476
+ await forge.load(level);
477
+ if (forge.hasRoute(level, joined)) return joined;
478
+ if (forge.hasRoute(level, suffix)) return suffix;
479
+ throw new UnknownRouteError(joined, level);
480
+ }
481
+ function resolveRouteNameSync(forge, level, prefix, suffix, separator = ".") {
482
+ if (!suffix) return prefix;
483
+ const joined = `${prefix}${separator}${suffix}`;
484
+ if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
485
+ if (forge.hasRoute(level, joined)) return joined;
486
+ if (forge.hasRoute(level, suffix)) return suffix;
487
+ throw new UnknownRouteError(joined, level);
488
+ }
489
+
490
+ // src/defineImmutableProps.ts
491
+ function defineImmutableProps(target, props) {
492
+ for (const key of Object.keys(props)) {
493
+ const val = props[key];
494
+ Object.defineProperty(target, key, {
495
+ value: val !== null && typeof val === "object" ? Object.freeze(val) : val,
496
+ writable: false,
497
+ enumerable: false,
498
+ configurable: false
499
+ });
500
+ }
501
+ return target;
502
+ }
503
+
471
504
  // src/loading.ts
472
505
  var LoadingTracker = class {
473
506
  constructor() {
@@ -634,7 +667,6 @@ var RouteForge = (function (exports) {
634
667
  const readyPromise = new Promise((resolve) => {
635
668
  resolveReady = resolve;
636
669
  });
637
- const levelLoadedListeners = /* @__PURE__ */ new Map();
638
670
  const cacheTtl = cacheOpts.ttl ?? DEFAULT_CACHE_TTL;
639
671
  const cacheStorage = cacheOpts.storage ?? "memory";
640
672
  const cache = new RouteCache({ storage: cacheStorage, ttl: cacheTtl });
@@ -686,7 +718,7 @@ var RouteForge = (function (exports) {
686
718
  function assertDiscoveryReady() {
687
719
  if (!autoDiscoveryCompleted && !explicitLevels?.length) {
688
720
  throw new ForgeError(
689
- "Route data not available. Auto-discovery has not completed. Use onSummaryReady callback to mount app, or await forge.ready / forge.load(level) first.",
721
+ "Route data not available. Auto-discovery has not completed. Use forge.ready() or forge.use(level) first.",
690
722
  { code: "RF_FE_010" }
691
723
  );
692
724
  }
@@ -739,15 +771,11 @@ var RouteForge = (function (exports) {
739
771
  routes[r.name] = { ...r, level: UNASSIGNED_LEVEL };
740
772
  }
741
773
  cache.set({ level: UNASSIGNED_LEVEL, routes, cache: null });
742
- const listeners = levelLoadedListeners.get(level);
743
- if (listeners) listeners.forEach((cb) => cb());
744
774
  return;
745
775
  }
746
776
  const resp = await fetchLevel(level);
747
777
  if ((invalidationGens.get(level) ?? 0) === gen) {
748
778
  cache.set(resp);
749
- const listeners = levelLoadedListeners.get(level);
750
- if (listeners) listeners.forEach((cb) => cb());
751
779
  }
752
780
  } finally {
753
781
  inflight.delete(level);
@@ -949,6 +977,7 @@ var RouteForge = (function (exports) {
949
977
  return result;
950
978
  }
951
979
  void autoDiscoveryPromise.then(() => {
980
+ autoDiscoveryCompleted = true;
952
981
  options.onSummaryReady?.();
953
982
  if (effectiveEager.length > 0) {
954
983
  return Promise.all(effectiveEager.map((lvl) => load(lvl))).catch((e) => {
@@ -956,11 +985,74 @@ var RouteForge = (function (exports) {
956
985
  });
957
986
  }
958
987
  }).then(() => {
959
- autoDiscoveryCompleted = true;
960
- resolveReady();
988
+ resolveReady(forgeInstance);
961
989
  }).catch(() => {
962
990
  });
963
- return {
991
+ function ready(onFulfilled, onRejected) {
992
+ if (onFulfilled) {
993
+ const p = readyPromise.then(onFulfilled, onRejected);
994
+ return p.then(() => forgeInstance);
995
+ }
996
+ return readyPromise;
997
+ }
998
+ const forgeResolver = { load, hasRoute };
999
+ function createBoundForge(level, prefix) {
1000
+ const levelLoadedPromise = load(level).catch(() => {
1001
+ });
1002
+ const apiFn = prefix ? (name, params) => resolveRouteName(forgeResolver, level, prefix, name).then(
1003
+ (resolved) => api(level, resolved, params)
1004
+ ) : (name, params) => api(level, name, params);
1005
+ const callable = apiFn;
1006
+ defineImmutableProps(callable, {
1007
+ level,
1008
+ ...prefix !== void 0 ? { prefix } : {},
1009
+ api: apiFn,
1010
+ route: prefix ? (name, params) => route(level, resolveRouteNameSync(forgeResolver, level, prefix, name), params) : (name, params) => route(level, name, params),
1011
+ url: prefix ? (name, params) => route(level, resolveRouteNameSync(forgeResolver, level, prefix, name), params) : (name, params) => route(level, name, params),
1012
+ hasRoute: (name) => hasRoute(level, name),
1013
+ getRoutes: () => getRoutes(level),
1014
+ load: () => load(level),
1015
+ invalidate: () => invalidate(level),
1016
+ isLoaded: () => isLoaded(level),
1017
+ isLoading: () => loadingTracker.isLoading(),
1018
+ onLoadingChange: (cb) => loadingTracker.subscribe(cb)
1019
+ });
1020
+ Object.defineProperty(callable, "levelLoaded", {
1021
+ value: levelLoadedPromise,
1022
+ writable: false,
1023
+ enumerable: true,
1024
+ configurable: true
1025
+ });
1026
+ return callable;
1027
+ }
1028
+ function boundOnLevelLoaded(bound, levelLoadedPromise, onFulfilled, onRejected) {
1029
+ const p = levelLoadedPromise.then(() => bound);
1030
+ if (onFulfilled) {
1031
+ return p.then(onFulfilled, onRejected).then(() => bound);
1032
+ }
1033
+ return p;
1034
+ }
1035
+ function attachBoundMethods(bound, levelLoadedPromise, level) {
1036
+ Object.defineProperty(bound, "onLevelLoaded", {
1037
+ value: (onFulfilled, onRejected) => boundOnLevelLoaded(bound, levelLoadedPromise, onFulfilled, onRejected),
1038
+ writable: false,
1039
+ enumerable: false,
1040
+ configurable: false
1041
+ });
1042
+ Object.defineProperty(bound, "useRoutePrefix", {
1043
+ value: (prefix) => createBoundForgeWithMethods(level, prefix),
1044
+ writable: false,
1045
+ enumerable: false,
1046
+ configurable: false
1047
+ });
1048
+ }
1049
+ function createBoundForgeWithMethods(level, prefix) {
1050
+ const bound = createBoundForge(level, prefix);
1051
+ const levelLoadedPromise = bound.levelLoaded;
1052
+ attachBoundMethods(bound, levelLoadedPromise, level);
1053
+ return bound;
1054
+ }
1055
+ const forgeInstance = {
964
1056
  api,
965
1057
  load,
966
1058
  route,
@@ -975,15 +1067,13 @@ var RouteForge = (function (exports) {
975
1067
  request: requestInterceptors,
976
1068
  response: responseInterceptors
977
1069
  },
978
- ready: readyPromise,
979
- onLevelLoaded(level, cb) {
980
- if (!levelLoadedListeners.has(level)) {
981
- levelLoadedListeners.set(level, /* @__PURE__ */ new Set());
982
- }
983
- levelLoadedListeners.get(level).add(cb);
984
- return () => levelLoadedListeners.get(level)?.delete(cb);
1070
+ ready,
1071
+ use(level, prefix) {
1072
+ if (level === void 0) return forgeInstance;
1073
+ return createBoundForgeWithMethods(level, prefix);
985
1074
  }
986
1075
  };
1076
+ return forgeInstance;
987
1077
  }
988
1078
  function pickMethod(meta) {
989
1079
  const m = meta.methods.find((x) => x.toUpperCase() !== "HEAD");
@@ -1051,25 +1141,6 @@ var RouteForge = (function (exports) {
1051
1141
  return false;
1052
1142
  }
1053
1143
 
1054
- // src/resolveRouteName.ts
1055
- async function resolveRouteName(forge, level, prefix, suffix, separator = ".") {
1056
- if (!suffix) return prefix;
1057
- const joined = `${prefix}${separator}${suffix}`;
1058
- if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
1059
- await forge.load(level);
1060
- if (forge.hasRoute(level, joined)) return joined;
1061
- if (forge.hasRoute(level, suffix)) return suffix;
1062
- throw new UnknownRouteError(joined, level);
1063
- }
1064
- function resolveRouteNameSync(forge, level, prefix, suffix, separator = ".") {
1065
- if (!suffix) return prefix;
1066
- const joined = `${prefix}${separator}${suffix}`;
1067
- if (!suffix.startsWith(`${prefix}${separator}`)) return joined;
1068
- if (forge.hasRoute(level, joined)) return joined;
1069
- if (forge.hasRoute(level, suffix)) return suffix;
1070
- throw new UnknownRouteError(joined, level);
1071
- }
1072
-
1073
1144
  exports.AdapterNotFoundError = AdapterNotFoundError;
1074
1145
  exports.ForgeError = ForgeError;
1075
1146
  exports.HTTPError = HTTPError;