brass-runtime 1.17.0 → 1.18.1

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.
Files changed (120) hide show
  1. package/README.md +36 -3
  2. package/dist/agent/cli/main.cjs +31 -32
  3. package/dist/agent/cli/main.js +3 -4
  4. package/dist/agent/cli/main.mjs +3 -4
  5. package/dist/agent/index.cjs +4 -5
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +3 -4
  8. package/dist/agent/index.mjs +3 -4
  9. package/dist/{chunk-7X3K5RMS.js → chunk-22HZQG5F.js} +9 -11
  10. package/dist/{chunk-GLE2WY7Z.cjs → chunk-2JHJ4YHS.cjs} +417 -124
  11. package/dist/{chunk-Q2I37RP3.cjs → chunk-2OW6IFY2.cjs} +44 -323
  12. package/dist/{chunk-7ZPEZ57L.cjs → chunk-5LC7V2OZ.cjs} +18 -20
  13. package/dist/{chunk-AGR5B2BC.cjs → chunk-5RZ7YITF.cjs} +564 -12
  14. package/dist/{chunk-DNFJLJMW.mjs → chunk-6MLAZPBL.mjs} +48 -24
  15. package/dist/{chunk-EJ6BPYVR.mjs → chunk-6V2AWT4R.mjs} +1 -1
  16. package/dist/{chunk-3AYM6WPJ.js → chunk-7DU7IQHK.js} +20 -299
  17. package/dist/{chunk-SK7UZRNI.mjs → chunk-7GBJYOX7.mjs} +528 -23
  18. package/dist/chunk-7TKI527D.cjs +123 -0
  19. package/dist/{chunk-52OB2ROS.js → chunk-7VQLEN37.js} +2 -4
  20. package/dist/{chunk-KH4SYAOS.mjs → chunk-B5FKOLTB.mjs} +20 -299
  21. package/dist/{chunk-FHQGHPMO.mjs → chunk-BC6Q6BCO.mjs} +2 -4
  22. package/dist/{chunk-4P2HHGAX.mjs → chunk-COOW7BJX.mjs} +32 -11
  23. package/dist/{chunk-2HQTDLHF.mjs → chunk-EEN5OTCR.mjs} +555 -3
  24. package/dist/{chunk-KZJQ723N.cjs → chunk-EICAJDNX.cjs} +13 -15
  25. package/dist/chunk-ELIECDYN.cjs +33 -0
  26. package/dist/{chunk-GYM3LLGS.mjs → chunk-H626ZTDZ.mjs} +399 -106
  27. package/dist/{chunk-C3MDXTRZ.js → chunk-HCJ4S3YB.js} +48 -24
  28. package/dist/{chunk-7JIJOVCT.js → chunk-IPSMXUWA.js} +2 -4
  29. package/dist/{chunk-4ROBZFL6.cjs → chunk-J6DUHITE.cjs} +6 -8
  30. package/dist/{chunk-6RY2FFN4.mjs → chunk-JWIEMBE6.mjs} +9 -11
  31. package/dist/{chunk-PD4EJTQC.cjs → chunk-KNTJ7FQB.cjs} +5 -5
  32. package/dist/chunk-KTGDLBLD.mjs +123 -0
  33. package/dist/chunk-LSYQ3C2M.js +33 -0
  34. package/dist/{chunk-RKGKFN2A.js → chunk-OW5VHAOE.js} +1 -1
  35. package/dist/{chunk-EOC4UHBS.mjs → chunk-RBHNOKH4.mjs} +2 -2
  36. package/dist/{chunk-6IXXWIUM.js → chunk-S4HXADU4.js} +555 -3
  37. package/dist/{chunk-FH2X7BVP.js → chunk-TTSPIU3U.js} +399 -106
  38. package/dist/{chunk-5QC7LRZ3.js → chunk-UAKAF32U.js} +2 -2
  39. package/dist/{chunk-CZIVE6NT.cjs → chunk-UUMKZJRJ.cjs} +48 -24
  40. package/dist/{chunk-MBEJI5HF.mjs → chunk-WCBNXPN6.mjs} +2 -4
  41. package/dist/{chunk-52PPNNI4.cjs → chunk-WGE2FEZE.cjs} +2 -2
  42. package/dist/{chunk-WBGRHGBP.cjs → chunk-WI7GZF3B.cjs} +114 -93
  43. package/dist/chunk-WUDHOZIH.js +6234 -0
  44. package/dist/{chunk-F6XWZQY4.cjs → chunk-WVSZOPGQ.cjs} +583 -78
  45. package/dist/chunk-XPIMJQYS.cjs +6234 -0
  46. package/dist/{chunk-VWIPB6I5.js → chunk-YGR2IN4R.js} +528 -23
  47. package/dist/chunk-YM3EDNYD.js +123 -0
  48. package/dist/chunk-YWLLH27R.mjs +33 -0
  49. package/dist/{chunk-BKK77SBA.js → chunk-YZ5LQ32F.js} +32 -11
  50. package/dist/chunk-Z3ZZMQUZ.mjs +6234 -0
  51. package/dist/core/index.cjs +37 -9
  52. package/dist/core/index.d.ts +19 -152
  53. package/dist/core/index.js +86 -58
  54. package/dist/core/index.mjs +86 -58
  55. package/dist/defaultClient-Cid0JoUR.d.ts +1648 -0
  56. package/dist/{effect-DIUHZ9IN.d.ts → effect-DnGUuhw6.d.ts} +22 -1
  57. package/dist/http/index.cjs +206 -59
  58. package/dist/http/index.d.ts +55 -819
  59. package/dist/http/index.js +220 -73
  60. package/dist/http/index.mjs +220 -73
  61. package/dist/http/testing.cjs +31 -10
  62. package/dist/http/testing.d.ts +16 -5
  63. package/dist/http/testing.js +29 -8
  64. package/dist/http/testing.mjs +29 -8
  65. package/dist/index.cjs +116 -88
  66. package/dist/index.d.ts +9 -8
  67. package/dist/index.js +87 -59
  68. package/dist/index.mjs +87 -59
  69. package/dist/{schedule-CK3Ml_7p.d.ts → layer-D2LFcBVx.d.ts} +176 -2
  70. package/dist/observability/index.cjs +20 -7
  71. package/dist/observability/index.d.ts +32 -8
  72. package/dist/observability/index.js +19 -6
  73. package/dist/observability/index.mjs +19 -6
  74. package/dist/perf/cli.cjs +26 -28
  75. package/dist/perf/cli.js +11 -13
  76. package/dist/perf/cli.mjs +11 -13
  77. package/dist/perf/index.cjs +13 -15
  78. package/dist/perf/index.js +11 -13
  79. package/dist/perf/index.mjs +11 -13
  80. package/dist/schema/index.cjs +2 -2
  81. package/dist/schema/index.js +1 -1
  82. package/dist/schema/index.mjs +1 -1
  83. package/dist/{server-D6JZ15_e.d.ts → server-Bf1zNYZk.d.ts} +5 -5
  84. package/dist/{stream-B4oK9JFP.d.ts → stream-I7bkvF7a.d.ts} +1 -1
  85. package/dist/{tracer-Hwt1cl7h.d.ts → tracer-DF83nLn6.d.ts} +2 -2
  86. package/dist/{tracing-DqbTKGcf.d.ts → tracing-CWV4gT0u.d.ts} +1 -1
  87. package/docs/README.md +2 -0
  88. package/docs/ai/PUBLIC_API.md +28 -7
  89. package/docs/articles/brass-runtime-http-observability.md +467 -0
  90. package/docs/frameworks/angular.md +51 -0
  91. package/docs/frameworks/express.md +58 -0
  92. package/docs/frameworks/fastify.md +49 -0
  93. package/docs/frameworks/nestjs.md +53 -0
  94. package/docs/frameworks/nextjs.md +55 -0
  95. package/docs/frameworks/react.md +44 -0
  96. package/docs/frameworks/vanilla.md +56 -0
  97. package/docs/guides/layers.md +130 -0
  98. package/docs/http-recipes.md +31 -1
  99. package/docs/http.md +50 -1
  100. package/docs/observability.md +132 -0
  101. package/docs/performance-profiler.md +6 -2
  102. package/docs/recipes/layers.md +46 -2
  103. package/docs/recipes/testing.md +25 -0
  104. package/package.json +6 -2
  105. package/dist/chunk-3LOYJFRR.cjs +0 -300
  106. package/dist/chunk-3Y2RIUMM.js +0 -300
  107. package/dist/chunk-5EC274J5.cjs +0 -2874
  108. package/dist/chunk-5VRJNBLZ.mjs +0 -2874
  109. package/dist/chunk-62AZW6UT.cjs +0 -313
  110. package/dist/chunk-74ZTY6CP.js +0 -2871
  111. package/dist/chunk-7CMJS3QE.mjs +0 -2871
  112. package/dist/chunk-A2OM6NEH.mjs +0 -194
  113. package/dist/chunk-B33ICAKP.js +0 -313
  114. package/dist/chunk-JF5WGYJJ.cjs +0 -194
  115. package/dist/chunk-KN32XNTH.mjs +0 -313
  116. package/dist/chunk-KQLYONSE.cjs +0 -2871
  117. package/dist/chunk-L2SYFEBS.js +0 -194
  118. package/dist/chunk-MIIYDLGM.js +0 -2874
  119. package/dist/chunk-PWC3RBQE.mjs +0 -300
  120. package/dist/client-CZHU674n.d.ts +0 -820
@@ -128,6 +128,9 @@ HTTP layer profile:
128
128
  - `node-http-text`
129
129
  - `wire-raw`
130
130
  - `default-minimal-json`
131
+ - `default-proxy-json`
132
+ - `default-proxy-node-json`
133
+ - `high-throughput-proxy-node-json`
131
134
  - `default-balanced-no-adaptive-json`
132
135
  - `default-balanced-json`
133
136
  - `default-json`
@@ -141,8 +144,9 @@ HTTP long-run memory lab:
141
144
 
142
145
  - defaults to `forceGc: true`, so use `node --expose-gc` for the strongest
143
146
  retained-memory signal
144
- - compares node transport, wire raw, minimal, balanced without adaptive,
145
- balanced, default, and default+observability variants
147
+ - compares node transport, wire raw, minimal, proxy, proxy+node transport,
148
+ high-throughput proxy+node transport, balanced without adaptive, balanced,
149
+ default, and default+observability variants
146
150
  - reports heap/rss totals, max p99, mean throughput, errors, and
147
151
  `heapDeltaPer10kRequestsMb`
148
152
  - highlights whether memory is `ok`, `watch`, `critical`, or `unknown-gc`
@@ -32,8 +32,9 @@ const RepoLayer = Layer.effect(Repo, (ctx: LayerContext) => {
32
32
  const AppLayer = Layer.compose(ConfigLayer, RepoLayer);
33
33
 
34
34
  const userUrl = await runPromise(
35
- provideContext(AppLayer, (ctx) =>
36
- asyncSucceed(ctx.unsafeGet(Repo).findUser("u1")),
35
+ provideContext(
36
+ AppLayer,
37
+ Layer.use(Repo, (repo) => asyncSucceed(repo.findUser("u1"))),
37
38
  ),
38
39
  );
39
40
 
@@ -42,3 +43,46 @@ console.log(userUrl);
42
43
 
43
44
  Missing services throw `MissingLayerServiceError`; use `formatLayerError` when
44
45
  surfacing the message.
46
+
47
+ For independent layers, `Layer.all(...)` keeps composition readable. For
48
+ ordered context graphs where later layers read earlier services, use
49
+ `Layer.composeAll(...)`. `Layer.useAll(...)` reads multiple services without
50
+ manual context access:
51
+
52
+ ```ts
53
+ const Logger = defineService<{ readonly info: (message: string) => void }>("Logger");
54
+ const LoggerLayer = Layer.value(Logger, console);
55
+
56
+ const AppLayer2 = Layer.composeAll(ConfigLayer, RepoLayer, LoggerLayer);
57
+
58
+ await runPromise(
59
+ provideContext(
60
+ AppLayer2,
61
+ Layer.useAll({ repo: Repo, logger: Logger }, ({ repo, logger }) => {
62
+ logger.info("loading user");
63
+ return asyncSucceed(repo.findUser("u1"));
64
+ }),
65
+ ),
66
+ );
67
+ ```
68
+
69
+ For app wiring, prefer the focused helpers:
70
+
71
+ ```ts
72
+ import { RuntimeService, makeConfigLayer, makeRuntimeLayer, makeTestLayer } from "brass-runtime";
73
+ import { s } from "brass-runtime/schema";
74
+
75
+ const ConfigSchema = s.object({ baseUrl: s.url() });
76
+
77
+ const ConfigLayer2 = makeConfigLayer(Config, ConfigSchema, {
78
+ baseUrl: "https://api.example.com",
79
+ });
80
+
81
+ const RuntimeLayer = makeRuntimeLayer((ctx) => ({
82
+ config: ctx.unsafeGet(Config),
83
+ }));
84
+
85
+ const TestConfigLayer = makeTestLayer(Config, {
86
+ baseUrl: "https://test.example.com",
87
+ });
88
+ ```
@@ -33,6 +33,31 @@ const response = await runHttpEffect(client({ method: "GET", url: "/health" }));
33
33
  console.log(response.status);
34
34
  ```
35
35
 
36
+ Layer-based applications can swap services with `makeTestLayer`,
37
+ `makeTestLayers`, or a mock default HTTP client layer:
38
+
39
+ ```ts
40
+ import { Layer, makeTestLayer } from "brass-runtime/core";
41
+ import { HttpClientService } from "brass-runtime/http";
42
+ import {
43
+ makeJsonHttpResponse,
44
+ makeMockDefaultHttpClientLayer,
45
+ } from "brass-runtime/http/testing";
46
+
47
+ const Config = Layer.tag<{ readonly baseUrl: string }>("Config");
48
+
49
+ const TestLayer = Layer.composeAll(
50
+ makeTestLayer(Config, { baseUrl: "test://users" }),
51
+ makeMockDefaultHttpClientLayer((req) =>
52
+ makeJsonHttpResponse({ url: req.url }),
53
+ ),
54
+ );
55
+
56
+ const program = Layer.use(HttpClientService, (http) =>
57
+ http.getJson("/users/1"),
58
+ );
59
+ ```
60
+
36
61
  For typed failures, assert on `Exit` instead of catching thrown values.
37
62
 
38
63
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brass-runtime",
3
- "version": "1.17.0",
3
+ "version": "1.18.1",
4
4
  "description": "Effect runtime utilities for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Augusto Vivaldelli",
@@ -116,6 +116,9 @@
116
116
  "benchmark:runtime": "tsx src/benchmarks/runner.ts runtime-performance-track",
117
117
  "benchmark:runtime:budget": "node scripts/check-runtime-benchmark-budget.mjs",
118
118
  "benchmark:http": "tsx src/benchmarks/runner.ts http-concurrent",
119
+ "benchmark:http:proxy": "BRASS_HTTP_BENCH_VARIANTS=node-http-text,default-minimal-json,default-proxy-json,default-proxy-node-json,default-json tsx src/benchmarks/runner.ts http-concurrent",
120
+ "benchmark:http:proxy:300tps": "BRASS_HTTP_RAMP_CLIENT=proxy BRASS_HTTP_RAMP_MAX_TPS=300 BRASS_HTTP_RAMP_STEP_TPS=300 BRASS_HTTP_RAMP_STEP_SECONDS=180 BRASS_HTTP_RAMP_CONCURRENCY=600 tsx src/benchmarks/runner.ts http-ramp-tps",
121
+ "benchmark:http:overhead": "tsx src/benchmarks/runner.ts http-local-overhead",
119
122
  "benchmark:http:soak": "BRASS_HTTP_BENCH_MODE=soak tsx src/benchmarks/runner.ts http-concurrent",
120
123
  "benchmark:http:budget": "node scripts/check-http-benchmark-budget.mjs",
121
124
  "benchmark:http:ramp": "tsx src/benchmarks/runner.ts http-ramp-tps",
@@ -124,7 +127,8 @@
124
127
  "benchmark:observability": "tsx src/benchmarks/runner.ts observability-overhead",
125
128
  "benchmark:observability:budget": "node scripts/check-observability-benchmark-budget.mjs",
126
129
  "benchmark:perf": "tsx src/perf/cli.ts --json",
127
- "perf": "tsx src/perf/cli.ts",
130
+ "perf": "tsx src/perf/cli.ts && node --expose-gc --require tsx/cjs src/benchmarks/http-local-overhead-gate.ts",
131
+ "perf:profile": "tsx src/perf/cli.ts",
128
132
  "perf:json": "tsx src/perf/cli.ts --json",
129
133
  "perf:runtime:ab": "tsx src/perf/cli.ts --profile runtime-ab",
130
134
  "perf:runtime:soak": "tsx src/perf/cli.ts --profile runtime-soak",
@@ -1,300 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
-
3
-
4
- var _chunkMVGUEJ5Zcjs = require('./chunk-MVGUEJ5Z.cjs');
5
-
6
- // src/http/requestPolicy.ts
7
- var hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
8
- var isPolicyObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
9
- var defineHttpPolicyPresets = (presets) => presets;
10
- var httpPolicy = Object.freeze({
11
- preset: (preset, overrides = {}) => ({
12
- preset,
13
- ...overrides
14
- }),
15
- lane: (lane, overrides = {}) => ({
16
- preset: lane,
17
- lane,
18
- ...overrides
19
- }),
20
- define: defineHttpPolicyPresets
21
- });
22
- var getHttpRequestPolicy = (req, options = {}) => {
23
- const legacy = req;
24
- const source = req.policy;
25
- const sourcePolicy = resolvePolicySource(req, source, options.presets);
26
- const policy = {
27
- ...legacy.lane !== void 0 ? { lane: legacy.lane } : {},
28
- ...legacy.dedupKey !== void 0 ? { dedupKey: legacy.dedupKey } : {},
29
- ...legacy.priority !== void 0 ? { priority: legacy.priority } : {},
30
- ...legacy.retry !== void 0 ? { retry: legacy.retry } : {},
31
- ...req.poolKey !== void 0 ? { poolKey: req.poolKey } : {},
32
- ...sourcePolicy
33
- };
34
- return policy;
35
- };
36
- var withHttpRequestPolicy = (req, patch) => {
37
- const current = getHttpRequestPolicy(req);
38
- const next = {
39
- ...req,
40
- policy: {
41
- ...current,
42
- ...patch
43
- }
44
- };
45
- if (hasOwn(patch, "poolKey")) {
46
- next.poolKey = patch.poolKey;
47
- }
48
- if (hasOwn(patch, "lane")) {
49
- next.lane = patch.lane;
50
- }
51
- if (hasOwn(patch, "dedupKey")) {
52
- next.dedupKey = patch.dedupKey;
53
- }
54
- if (hasOwn(patch, "priority")) {
55
- next.priority = patch.priority;
56
- }
57
- if (hasOwn(patch, "retry")) {
58
- next.retry = patch.retry;
59
- }
60
- return next;
61
- };
62
- var resolveHttpRequestPolicyPresets = (req, presets) => {
63
- const policy = getHttpRequestPolicy(req, { presets });
64
- return withHttpRequestPolicy({ ...req, policy }, policy);
65
- };
66
- var withHttpPolicyPresets = (presets) => {
67
- return (next) => (req) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
68
- _chunkMVGUEJ5Zcjs.asyncSync.call(void 0, () => resolveHttpRequestPolicyPresets(req, presets)),
69
- (resolved) => next(resolved)
70
- );
71
- };
72
- function resolvePolicySource(req, source, presets) {
73
- if (typeof source === "string") {
74
- return resolveNamedPolicy(req, source, {}, presets);
75
- }
76
- if (!isPolicyObject(source)) return {};
77
- if (!source.preset) return source;
78
- return resolveNamedPolicy(req, source.preset, source, presets);
79
- }
80
- function resolveNamedPolicy(req, presetName, overrides, presets) {
81
- const named = _optionalChain([presets, 'optionalAccess', _ => _[presetName]]);
82
- const resolved = typeof named === "function" ? named(req, presetName) : named;
83
- return {
84
- lane: presetName,
85
- ...isPolicyObject(resolved) ? resolved : {},
86
- ...overrides,
87
- preset: presetName
88
- };
89
- }
90
-
91
- // src/http/errors.ts
92
- var HTTP_ERROR_TAGS = /* @__PURE__ */ new Set([
93
- "Abort",
94
- "BadUrl",
95
- "FetchError",
96
- "Timeout",
97
- "PoolRejected",
98
- "PoolTimeout",
99
- "PoolClosed",
100
- "BatchSplitError"
101
- ]);
102
- var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
103
- var TIMEOUT_CODES = /* @__PURE__ */ new Set([
104
- "ECONNABORTED",
105
- "ETIMEDOUT",
106
- "ESOCKETTIMEDOUT",
107
- "UND_ERR_CONNECT_TIMEOUT",
108
- "UND_ERR_HEADERS_TIMEOUT",
109
- "UND_ERR_BODY_TIMEOUT"
110
- ]);
111
- var ABORT_CODES = /* @__PURE__ */ new Set(["ERR_CANCELED", "ABORT_ERR"]);
112
- function isHttpError(error) {
113
- return hasTag(error) && HTTP_ERROR_TAGS.has(error._tag);
114
- }
115
- function isValidationError(error) {
116
- return hasTag(error) && error._tag === "ValidationError";
117
- }
118
- function isCircuitBreakerOpen(error) {
119
- return hasTag(error) && error._tag === "CircuitBreakerOpen";
120
- }
121
- function isKnownHttpError(error) {
122
- return isHttpError(error) || isValidationError(error) || isCircuitBreakerOpen(error);
123
- }
124
- function isAbortHttpError(error) {
125
- return isHttpError(error) && error._tag === "Abort";
126
- }
127
- function isTimeoutHttpError(error) {
128
- return isHttpError(error) && (error._tag === "Timeout" || error._tag === "PoolTimeout");
129
- }
130
- function isFetchHttpError(error) {
131
- return isHttpError(error) && error._tag === "FetchError";
132
- }
133
- function httpErrorStatus(error) {
134
- if (!isFetchHttpError(error)) return void 0;
135
- return typeof error.status === "number" && Number.isFinite(error.status) ? error.status : void 0;
136
- }
137
- function isRetryableHttpStatus(status) {
138
- return RETRYABLE_STATUS.has(status);
139
- }
140
- function isRetryableHttpError(error, options = {}) {
141
- if (!isHttpError(error)) return false;
142
- switch (error._tag) {
143
- case "Timeout":
144
- case "PoolTimeout":
145
- return true;
146
- case "FetchError": {
147
- const status = httpErrorStatus(error);
148
- if (status !== void 0) return (_nullishCoalesce(options.retryOnStatus, () => ( isRetryableHttpStatus)))(status);
149
- return true;
150
- }
151
- default:
152
- return false;
153
- }
154
- }
155
- function isExternalAbortError(error) {
156
- if (typeof error !== "object" || error === null) return false;
157
- const record = error;
158
- return record.name === "AbortError" || ABORT_CODES.has(String(_nullishCoalesce(record.code, () => ( ""))));
159
- }
160
- function isExternalTimeoutError(error) {
161
- if (typeof error !== "object" || error === null) return false;
162
- const record = error;
163
- return record.name === "TimeoutError" || TIMEOUT_CODES.has(String(_nullishCoalesce(record.code, () => ( ""))));
164
- }
165
- function toHttpError(error, options = {}) {
166
- if (isHttpError(error)) return error;
167
- if (_optionalChain([options, 'access', _2 => _2.signal, 'optionalAccess', _3 => _3.aborted]) || isExternalAbortError(error)) {
168
- return { _tag: "Abort" };
169
- }
170
- const status = externalStatus(error);
171
- const statusText = externalStatusText(error);
172
- const code = externalCode(error);
173
- const message = resolveMessage(error, options.message);
174
- if (isExternalTimeoutError(error)) {
175
- return {
176
- _tag: "Timeout",
177
- timeoutMs: _nullishCoalesce(options.timeoutMs, () => ( 0)),
178
- phase: _nullishCoalesce(options.phase, () => ( "request")),
179
- message
180
- };
181
- }
182
- return {
183
- _tag: "FetchError",
184
- message,
185
- ...code !== void 0 ? { code } : {},
186
- ...status !== void 0 ? { status } : {},
187
- ...statusText !== void 0 ? { statusText } : {},
188
- ...retryAfterMsFromExternal(error) !== void 0 ? { retryAfterMs: retryAfterMsFromExternal(error) } : {},
189
- cause: error
190
- };
191
- }
192
- function matchHttpError(error, handlers) {
193
- if (isKnownHttpError(error)) {
194
- const handler = handlers[error._tag];
195
- if (handler) return handler(error);
196
- }
197
- return _optionalChain([handlers, 'access', _4 => _4.default, 'optionalCall', _5 => _5(error)]);
198
- }
199
- function formatHttpError(error) {
200
- if (isValidationError(error)) {
201
- const phase = error.phase ? `${error.phase} ` : "";
202
- return `${phase}validation failed: ${error.message}`;
203
- }
204
- if (isCircuitBreakerOpen(error)) {
205
- return `Circuit breaker is open after ${error.failures} failure(s)`;
206
- }
207
- if (!isHttpError(error)) {
208
- return error instanceof Error ? error.message : String(error);
209
- }
210
- switch (error._tag) {
211
- case "Abort":
212
- return "HTTP request aborted";
213
- case "BadUrl":
214
- case "PoolRejected":
215
- case "PoolTimeout":
216
- case "PoolClosed":
217
- case "BatchSplitError":
218
- return error.message;
219
- case "FetchError":
220
- return formatFetchError(error);
221
- case "Timeout":
222
- return error.message;
223
- }
224
- }
225
- function hasTag(error) {
226
- return typeof error === "object" && error !== null && typeof error._tag === "string";
227
- }
228
- function externalCode(error) {
229
- if (typeof error !== "object" || error === null) return void 0;
230
- const code = error.code;
231
- return typeof code === "string" && code.length > 0 ? code : void 0;
232
- }
233
- function externalStatus(error) {
234
- if (typeof error !== "object" || error === null) return void 0;
235
- const record = error;
236
- const response = typeof record.response === "object" && record.response !== null ? record.response : void 0;
237
- const status = _nullishCoalesce(_nullishCoalesce(_optionalChain([response, 'optionalAccess', _6 => _6.status]), () => ( record.status)), () => ( record.statusCode));
238
- return typeof status === "number" && Number.isFinite(status) ? status : void 0;
239
- }
240
- function externalStatusText(error) {
241
- if (typeof error !== "object" || error === null) return void 0;
242
- const record = error;
243
- const response = typeof record.response === "object" && record.response !== null ? record.response : void 0;
244
- const statusText = _nullishCoalesce(_nullishCoalesce(_optionalChain([response, 'optionalAccess', _7 => _7.statusText]), () => ( record.statusText)), () => ( record.statusMessage));
245
- return typeof statusText === "string" && statusText.length > 0 ? statusText : void 0;
246
- }
247
- function retryAfterMsFromExternal(error) {
248
- if (typeof error !== "object" || error === null) return void 0;
249
- const record = error;
250
- const response = typeof record.response === "object" && record.response !== null ? record.response : void 0;
251
- const headers = _nullishCoalesce(_optionalChain([response, 'optionalAccess', _8 => _8.headers]), () => ( record.headers));
252
- if (typeof headers !== "object" || headers === null) return void 0;
253
- const headerRecord = headers;
254
- const raw = _nullishCoalesce(headerRecord["retry-after"], () => ( headerRecord["Retry-After"]));
255
- if (raw === void 0 || raw === null) return void 0;
256
- const seconds = Number(raw);
257
- if (Number.isFinite(seconds)) return Math.max(0, Math.floor(seconds * 1e3));
258
- const dateMs = Date.parse(String(raw));
259
- return Number.isFinite(dateMs) ? Math.max(0, dateMs - Date.now()) : void 0;
260
- }
261
- function resolveMessage(error, message) {
262
- if (typeof message === "function") return message(error);
263
- if (typeof message === "string") return message;
264
- if (error instanceof Error && error.message) return error.message;
265
- if (typeof error === "object" && error !== null) {
266
- const value = error.message;
267
- if (typeof value === "string" && value.length > 0) return value;
268
- }
269
- return String(error);
270
- }
271
- function formatFetchError(error) {
272
- const status = httpErrorStatus(error);
273
- if (status === void 0) return error.message;
274
- const statusText = error.statusText ? ` ${error.statusText}` : "";
275
- return `HTTP ${status}${statusText}: ${error.message}`;
276
- }
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
- exports.defineHttpPolicyPresets = defineHttpPolicyPresets; exports.httpPolicy = httpPolicy; exports.getHttpRequestPolicy = getHttpRequestPolicy; exports.withHttpRequestPolicy = withHttpRequestPolicy; exports.resolveHttpRequestPolicyPresets = resolveHttpRequestPolicyPresets; exports.withHttpPolicyPresets = withHttpPolicyPresets; exports.isHttpError = isHttpError; exports.isValidationError = isValidationError; exports.isCircuitBreakerOpen = isCircuitBreakerOpen; exports.isKnownHttpError = isKnownHttpError; exports.isAbortHttpError = isAbortHttpError; exports.isTimeoutHttpError = isTimeoutHttpError; exports.isFetchHttpError = isFetchHttpError; exports.httpErrorStatus = httpErrorStatus; exports.isRetryableHttpStatus = isRetryableHttpStatus; exports.isRetryableHttpError = isRetryableHttpError; exports.isExternalAbortError = isExternalAbortError; exports.isExternalTimeoutError = isExternalTimeoutError; exports.toHttpError = toHttpError; exports.matchHttpError = matchHttpError; exports.formatHttpError = formatHttpError;