@route-forge/core 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -281,30 +281,29 @@ var RouteForge = (function (exports) {
281
281
  function createBuiltinHttp(forgeInterceptors) {
282
282
  const requestMgr = forgeInterceptors?.request ?? createInterceptorManager();
283
283
  const responseMgr = forgeInterceptors?.response ?? createInterceptorManager();
284
- async function request(config) {
285
- const finalConfig = await runRequestInterceptors(requestMgr, config);
284
+ async function requestRaw(config) {
286
285
  const signal = combineSignals(
287
- finalConfig.signal,
288
- finalConfig.timeout && finalConfig.timeout > 0 ? AbortSignal.timeout(finalConfig.timeout) : void 0
286
+ config.signal,
287
+ config.timeout && config.timeout > 0 ? AbortSignal.timeout(config.timeout) : void 0
289
288
  );
290
- let url = finalConfig.url;
291
- if (finalConfig.paramsSerializer && finalConfig.params) {
292
- const qs = finalConfig.paramsSerializer(finalConfig.params);
289
+ let url = config.url;
290
+ if (config.paramsSerializer && config.params) {
291
+ const qs = config.paramsSerializer(config.params);
293
292
  if (qs) {
294
293
  url = url.includes("?") ? `${url}&${qs}` : `${url}?${qs}`;
295
294
  }
296
295
  }
297
- const headers = new Headers(finalConfig.headers);
296
+ const headers = new Headers(config.headers);
298
297
  const fetchInit = {
299
- method: finalConfig.method,
298
+ method: config.method,
300
299
  headers
301
300
  };
302
301
  if (signal) fetchInit.signal = signal;
303
- if (finalConfig.body !== void 0 && !["GET", "HEAD"].includes(finalConfig.method.toUpperCase())) {
304
- if (typeof finalConfig.body === "string" || isPassthroughBody(finalConfig.body)) {
305
- fetchInit.body = finalConfig.body;
302
+ if (config.body !== void 0 && !["GET", "HEAD"].includes(config.method.toUpperCase())) {
303
+ if (typeof config.body === "string" || isPassthroughBody(config.body)) {
304
+ fetchInit.body = config.body;
306
305
  } else {
307
- fetchInit.body = JSON.stringify(finalConfig.body);
306
+ fetchInit.body = JSON.stringify(config.body);
308
307
  if (!headers.has("Content-Type")) {
309
308
  headers.set("Content-Type", "application/json");
310
309
  }
@@ -317,8 +316,8 @@ var RouteForge = (function (exports) {
317
316
  if (isAbortError(e)) throw e;
318
317
  throw new NetworkError(
319
318
  e instanceof Error ? e.message : String(e),
320
- finalConfig.route,
321
- finalConfig.level,
319
+ config.route,
320
+ config.level,
322
321
  e
323
322
  );
324
323
  }
@@ -332,27 +331,32 @@ var RouteForge = (function (exports) {
332
331
  }
333
332
  }
334
333
  const responseData = {
335
- route: finalConfig.route,
336
- level: finalConfig.level,
337
- method: finalConfig.method,
334
+ route: config.route,
335
+ level: config.level,
336
+ method: config.method,
338
337
  url,
339
338
  status: res.status,
340
339
  headers: res.headers,
341
340
  data,
342
- config: finalConfig
341
+ config
343
342
  };
344
- const source = res.status >= 200 && res.status < 300 ? Promise.resolve(responseData) : Promise.reject(
345
- new HTTPError(
346
- `HTTP ${res.status} for route "${finalConfig.route}" (${finalConfig.method} ${url})`,
347
- {
348
- route: finalConfig.route,
349
- level: finalConfig.level,
350
- status: res.status,
351
- url,
352
- method: finalConfig.method
353
- }
354
- )
343
+ if (res.status >= 200 && res.status < 300) {
344
+ return responseData;
345
+ }
346
+ throw new HTTPError(
347
+ `HTTP ${res.status} for route "${config.route}" (${config.method} ${url})`,
348
+ {
349
+ route: config.route,
350
+ level: config.level,
351
+ status: res.status,
352
+ url,
353
+ method: config.method
354
+ }
355
355
  );
356
+ }
357
+ async function request(config) {
358
+ const finalConfig = await runRequestInterceptors(requestMgr, config);
359
+ const source = Promise.resolve(finalConfig).then(requestRaw);
356
360
  return runResponseInterceptors(
357
361
  responseMgr,
358
362
  source
@@ -365,6 +369,7 @@ var RouteForge = (function (exports) {
365
369
  const del = (url, config) => request({ ...config, url, method: "DELETE" });
366
370
  return {
367
371
  request,
372
+ requestRaw,
368
373
  interceptors: {
369
374
  request: requestMgr,
370
375
  response: responseMgr
@@ -576,7 +581,6 @@ var RouteForge = (function (exports) {
576
581
  const loadingTracker = new LoadingTracker();
577
582
  const explicitLevels = options.levels;
578
583
  const explicitEager = options.eager;
579
- const explicitStrict = options.strict ?? false;
580
584
  const explicitEndpoint = options.endpoint;
581
585
  let effectiveLevels = explicitLevels ?? [];
582
586
  let effectiveEager = explicitEager ?? [];
@@ -624,11 +628,6 @@ var RouteForge = (function (exports) {
624
628
  if (summary.config.url_prefix) {
625
629
  effectiveUrlPrefix = summary.config.url_prefix.endsWith("/") ? summary.config.url_prefix.slice(0, -1) : summary.config.url_prefix;
626
630
  }
627
- if (summary.config.strict_mode && !explicitStrict) {
628
- console.warn(
629
- "[route-forge] backend strict_mode=true overrides frontend strict=false; forcing strict=true"
630
- );
631
- }
632
631
  const backendLevels = Object.keys(summary.levels);
633
632
  backendHasUnassignedLevel = backendLevels.includes(UNASSIGNED_LEVEL);
634
633
  if (Array.isArray(summary.unassigned) && summary.unassigned.length > 0 && !backendHasUnassignedLevel) {
@@ -702,7 +701,10 @@ var RouteForge = (function (exports) {
702
701
  if (!adapterResolved) {
703
702
  adapterObj = await adapterPromise.catch((e) => {
704
703
  if (e instanceof AdapterNotFoundError) throw e;
705
- return resolveAdapter({ adapter: "builtin" });
704
+ return resolveAdapter({
705
+ adapter: "builtin",
706
+ forgeInterceptors: { request: requestInterceptors, response: responseInterceptors }
707
+ });
706
708
  });
707
709
  adapterResolved = true;
708
710
  }
@@ -746,7 +748,8 @@ var RouteForge = (function (exports) {
746
748
  level
747
749
  }
748
750
  };
749
- const resp = await adp.request(config);
751
+ const doRawRequest = adp.requestRaw ?? adp.request;
752
+ const resp = await doRawRequest(config);
750
753
  if (!resp || resp.status < 200 || resp.status >= 300) {
751
754
  throw new HTTPError(
752
755
  `Failed to load level "${level}": HTTP ${resp?.status}`,
@@ -849,23 +852,40 @@ var RouteForge = (function (exports) {
849
852
  }
850
853
  return void 0;
851
854
  }
852
- async function api(level, name, params = {}) {
853
- await autoDiscoveryPromise;
854
- await load(level);
855
- const meta = findRouteMeta(level, name);
856
- if (!meta) {
857
- throw new UnknownRouteError(name, level);
858
- }
859
- return doApiCall(meta, params);
855
+ function api(level, name, params = {}) {
856
+ let ctrl;
857
+ let abortedBeforeInit = false;
858
+ let abortReason;
859
+ const work = (async () => {
860
+ ctrl = new AbortController();
861
+ if (abortedBeforeInit) {
862
+ ctrl.abort(abortReason);
863
+ }
864
+ await autoDiscoveryPromise;
865
+ await load(level);
866
+ const meta = findRouteMeta(level, name);
867
+ if (!meta) {
868
+ throw new UnknownRouteError(name, level);
869
+ }
870
+ return doApiCall(meta, params, ctrl.signal);
871
+ })();
872
+ const request = work;
873
+ request.abort = () => {
874
+ if (ctrl) {
875
+ ctrl.abort();
876
+ } else {
877
+ abortedBeforeInit = true;
878
+ }
879
+ };
880
+ return request;
860
881
  }
861
- async function doApiCall(meta, params) {
882
+ async function doApiCall(meta, params, signal) {
862
883
  const {
863
884
  pathParams,
864
885
  query,
865
886
  body,
866
887
  headers,
867
- timeout: perCallTimeout,
868
- signal
888
+ timeout: perCallTimeout
869
889
  } = resolveApiParams(params);
870
890
  if (signal?.aborted) {
871
891
  throw new RequestAbortedError(meta.name, meta.level, signal.reason);
@@ -909,7 +929,7 @@ var RouteForge = (function (exports) {
909
929
  },
910
930
  (err) => {
911
931
  if (err instanceof ForgeError) throw err;
912
- if (isAbortError2(err, finalConfig.signal)) {
932
+ if (isAbortError2(err, signal)) {
913
933
  throw new RequestAbortedError(meta.name, meta.level, err);
914
934
  }
915
935
  throw new NetworkError(
@@ -997,7 +1017,8 @@ var RouteForge = (function (exports) {
997
1017
  }
998
1018
  const forgeResolver = { load, hasRoute };
999
1019
  function createBoundForge(level, prefix) {
1000
- const levelLoadedPromise = load(level).catch(() => {
1020
+ const levelLoadedPromise = load(level);
1021
+ levelLoadedPromise.catch(() => {
1001
1022
  });
1002
1023
  const apiFn = prefix ? (name, params) => resolveRouteName(forgeResolver, level, prefix, name).then(
1003
1024
  (resolved) => api(level, resolved, params)
@@ -1097,7 +1118,6 @@ var RouteForge = (function (exports) {
1097
1118
  body: rawBody,
1098
1119
  headers: rawHeaders,
1099
1120
  timeout: perCallTimeout,
1100
- signal,
1101
1121
  ...flatRest
1102
1122
  } = input;
1103
1123
  const pathParams = explicitParams ? { ...explicitParams } : {};
@@ -1130,7 +1150,7 @@ var RouteForge = (function (exports) {
1130
1150
  pathParams.headers = rawHeaders;
1131
1151
  }
1132
1152
  }
1133
- return { pathParams, query, body, headers, timeout: perCallTimeout, signal };
1153
+ return { pathParams, query, body, headers, timeout: perCallTimeout };
1134
1154
  }
1135
1155
  function isAbortError2(err, signal) {
1136
1156
  if (signal?.aborted) return true;