brass-runtime 1.17.0 → 1.18.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 +36 -3
- package/dist/agent/cli/main.cjs +31 -32
- package/dist/agent/cli/main.js +3 -4
- package/dist/agent/cli/main.mjs +3 -4
- package/dist/agent/index.cjs +4 -5
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +3 -4
- package/dist/agent/index.mjs +3 -4
- package/dist/{chunk-GYM3LLGS.mjs → chunk-2QNREG6K.mjs} +188 -5
- package/dist/{chunk-4ROBZFL6.cjs → chunk-2SLT3X6G.cjs} +6 -8
- package/dist/{chunk-KZJQ723N.cjs → chunk-3PFZGP23.cjs} +13 -15
- package/dist/{chunk-VWIPB6I5.js → chunk-3PHU7FWS.js} +528 -23
- package/dist/{chunk-BKK77SBA.js → chunk-4YQHPIWJ.js} +32 -11
- package/dist/chunk-5XADBMSU.cjs +33 -0
- package/dist/{chunk-DNFJLJMW.mjs → chunk-6MLAZPBL.mjs} +48 -24
- package/dist/chunk-7TKI527D.cjs +123 -0
- package/dist/{chunk-AGR5B2BC.cjs → chunk-7TXQJFZX.cjs} +564 -12
- package/dist/{chunk-RKGKFN2A.js → chunk-AADFFVYS.js} +1 -1
- package/dist/{chunk-52PPNNI4.cjs → chunk-AJMKZXRB.cjs} +2 -2
- package/dist/{chunk-3AYM6WPJ.js → chunk-BG5RNEA2.js} +20 -299
- package/dist/{chunk-2HQTDLHF.mjs → chunk-ELLF55ER.mjs} +555 -3
- package/dist/{chunk-EOC4UHBS.mjs → chunk-G5JTCFMI.mjs} +2 -2
- package/dist/chunk-H5GYX7RZ.js +6126 -0
- package/dist/{chunk-C3MDXTRZ.js → chunk-HCJ4S3YB.js} +48 -24
- package/dist/{chunk-6IXXWIUM.js → chunk-IBRHSH5H.js} +555 -3
- package/dist/{chunk-Q2I37RP3.cjs → chunk-IFRBVMWJ.cjs} +44 -323
- package/dist/{chunk-52OB2ROS.js → chunk-ITG6I7ZS.js} +2 -4
- package/dist/chunk-ITZQ526U.mjs +33 -0
- package/dist/{chunk-7JIJOVCT.js → chunk-JH4GI3DW.js} +2 -4
- package/dist/{chunk-F6XWZQY4.cjs → chunk-KHACHFBQ.cjs} +583 -78
- package/dist/{chunk-4P2HHGAX.mjs → chunk-KRYP6CAE.mjs} +32 -11
- package/dist/chunk-KTGDLBLD.mjs +123 -0
- package/dist/{chunk-WBGRHGBP.cjs → chunk-LXBU5E77.cjs} +114 -93
- package/dist/{chunk-PD4EJTQC.cjs → chunk-N6QNSTWD.cjs} +5 -5
- package/dist/{chunk-6RY2FFN4.mjs → chunk-OI4ESUMC.mjs} +9 -11
- package/dist/{chunk-EJ6BPYVR.mjs → chunk-OT2TESZU.mjs} +1 -1
- package/dist/{chunk-7X3K5RMS.js → chunk-PSEU65ND.js} +9 -11
- package/dist/{chunk-SK7UZRNI.mjs → chunk-QCOLAHU3.mjs} +528 -23
- package/dist/{chunk-KH4SYAOS.mjs → chunk-QZ6QFJNM.mjs} +20 -299
- package/dist/{chunk-MBEJI5HF.mjs → chunk-R6WDSZA6.mjs} +2 -4
- package/dist/{chunk-FHQGHPMO.mjs → chunk-RREBJX2S.mjs} +2 -4
- package/dist/{chunk-5QC7LRZ3.js → chunk-S4HHFUYP.js} +2 -2
- package/dist/{chunk-GLE2WY7Z.cjs → chunk-SSQJKDN3.cjs} +194 -11
- package/dist/{chunk-CZIVE6NT.cjs → chunk-UUMKZJRJ.cjs} +48 -24
- package/dist/chunk-VIFA4DPN.cjs +6126 -0
- package/dist/chunk-W6WR37HN.js +33 -0
- package/dist/{chunk-FH2X7BVP.js → chunk-XSAHV5HQ.js} +188 -5
- package/dist/chunk-YM3EDNYD.js +123 -0
- package/dist/{chunk-7ZPEZ57L.cjs → chunk-YTX2JYYP.cjs} +18 -20
- package/dist/chunk-Z3PSSXP3.mjs +6126 -0
- package/dist/core/index.cjs +31 -9
- package/dist/core/index.d.ts +19 -152
- package/dist/core/index.js +80 -58
- package/dist/core/index.mjs +80 -58
- package/dist/defaultClient-DhpCQW9m.d.ts +1623 -0
- package/dist/{effect-DIUHZ9IN.d.ts → effect-CtUDl5M5.d.ts} +1 -1
- package/dist/http/index.cjs +202 -59
- package/dist/http/index.d.ts +55 -819
- package/dist/http/index.js +216 -73
- package/dist/http/index.mjs +216 -73
- package/dist/http/testing.cjs +31 -10
- package/dist/http/testing.d.ts +16 -5
- package/dist/http/testing.js +29 -8
- package/dist/http/testing.mjs +29 -8
- package/dist/index.cjs +110 -88
- package/dist/index.d.ts +9 -8
- package/dist/index.js +81 -59
- package/dist/index.mjs +81 -59
- package/dist/{schedule-CK3Ml_7p.d.ts → layer-BalPI6cN.d.ts} +176 -2
- package/dist/observability/index.cjs +20 -7
- package/dist/observability/index.d.ts +32 -8
- package/dist/observability/index.js +19 -6
- package/dist/observability/index.mjs +19 -6
- package/dist/perf/cli.cjs +26 -28
- package/dist/perf/cli.js +11 -13
- package/dist/perf/cli.mjs +11 -13
- package/dist/perf/index.cjs +13 -15
- package/dist/perf/index.js +11 -13
- package/dist/perf/index.mjs +11 -13
- package/dist/schema/index.cjs +2 -2
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.mjs +1 -1
- package/dist/{server-D6JZ15_e.d.ts → server-C1zVmqE6.d.ts} +5 -5
- package/dist/{stream-B4oK9JFP.d.ts → stream-Bb4FTejt.d.ts} +1 -1
- package/dist/{tracer-Hwt1cl7h.d.ts → tracer-DzfuE6um.d.ts} +2 -2
- package/dist/{tracing-DqbTKGcf.d.ts → tracing-BABA5arE.d.ts} +1 -1
- package/docs/README.md +2 -0
- package/docs/ai/PUBLIC_API.md +28 -7
- package/docs/articles/brass-runtime-http-observability.md +467 -0
- package/docs/frameworks/angular.md +51 -0
- package/docs/frameworks/express.md +58 -0
- package/docs/frameworks/fastify.md +49 -0
- package/docs/frameworks/nestjs.md +53 -0
- package/docs/frameworks/nextjs.md +55 -0
- package/docs/frameworks/react.md +44 -0
- package/docs/frameworks/vanilla.md +56 -0
- package/docs/guides/layers.md +130 -0
- package/docs/http-recipes.md +31 -1
- package/docs/http.md +50 -1
- package/docs/observability.md +132 -0
- package/docs/performance-profiler.md +6 -2
- package/docs/recipes/layers.md +46 -2
- package/docs/recipes/testing.md +25 -0
- package/package.json +4 -1
- package/dist/chunk-3LOYJFRR.cjs +0 -300
- package/dist/chunk-3Y2RIUMM.js +0 -300
- package/dist/chunk-5EC274J5.cjs +0 -2874
- package/dist/chunk-5VRJNBLZ.mjs +0 -2874
- package/dist/chunk-62AZW6UT.cjs +0 -313
- package/dist/chunk-74ZTY6CP.js +0 -2871
- package/dist/chunk-7CMJS3QE.mjs +0 -2871
- package/dist/chunk-A2OM6NEH.mjs +0 -194
- package/dist/chunk-B33ICAKP.js +0 -313
- package/dist/chunk-JF5WGYJJ.cjs +0 -194
- package/dist/chunk-KN32XNTH.mjs +0 -313
- package/dist/chunk-KQLYONSE.cjs +0 -2871
- package/dist/chunk-L2SYFEBS.js +0 -194
- package/dist/chunk-MIIYDLGM.js +0 -2874
- package/dist/chunk-PWC3RBQE.mjs +0 -300
- package/dist/client-CZHU674n.d.ts +0 -820
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Scope,
|
|
2
3
|
liveClock,
|
|
3
4
|
runtimeClockFromEnv,
|
|
4
5
|
unsafeGetCurrentRuntime
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-XSAHV5HQ.js";
|
|
6
7
|
import {
|
|
7
8
|
Async,
|
|
9
|
+
Cause,
|
|
10
|
+
Exit,
|
|
8
11
|
asyncEffect,
|
|
9
12
|
asyncFail,
|
|
10
13
|
asyncFlatMap,
|
|
11
14
|
asyncFold,
|
|
12
|
-
asyncSucceed
|
|
15
|
+
asyncSucceed,
|
|
16
|
+
asyncSync,
|
|
17
|
+
unit
|
|
13
18
|
} from "./chunk-UB4B6OFY.js";
|
|
14
19
|
|
|
15
20
|
// src/core/runtime/combinators.ts
|
|
@@ -102,6 +107,174 @@ function retryWithBackoff(effect, opts = {}) {
|
|
|
102
107
|
});
|
|
103
108
|
}
|
|
104
109
|
|
|
110
|
+
// src/core/runtime/resource.ts
|
|
111
|
+
function bracket(acquire, use, release) {
|
|
112
|
+
return asyncEffect((env, cb) => {
|
|
113
|
+
const runtime = unsafeGetCurrentRuntime();
|
|
114
|
+
const scope = new Scope(runtime);
|
|
115
|
+
const acquireFiber = scope.fork(acquire);
|
|
116
|
+
acquireFiber.join((acquireExit) => {
|
|
117
|
+
if (acquireExit._tag === "Failure") {
|
|
118
|
+
scope.close(acquireExit);
|
|
119
|
+
cb(acquireExit);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const resource2 = acquireExit.value;
|
|
123
|
+
const useFiber = scope.fork(use(resource2));
|
|
124
|
+
useFiber.join((useExit) => {
|
|
125
|
+
const releaseEffect = safeRelease(release, resource2, useExit);
|
|
126
|
+
const releaseFiber = runtime.fork(releaseEffect);
|
|
127
|
+
releaseFiber.join(() => {
|
|
128
|
+
scope.close(useExit);
|
|
129
|
+
cb(useExit);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
return () => {
|
|
134
|
+
scope.close(Exit.failCause(Cause.interrupt()));
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function safeRelease(release, resource2, exit) {
|
|
139
|
+
return asyncFold(
|
|
140
|
+
(() => {
|
|
141
|
+
try {
|
|
142
|
+
return release(resource2, exit);
|
|
143
|
+
} catch {
|
|
144
|
+
return unit();
|
|
145
|
+
}
|
|
146
|
+
})(),
|
|
147
|
+
() => unit(),
|
|
148
|
+
() => unit()
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
function ensuring(effect, finalizer) {
|
|
152
|
+
return asyncEffect((env, cb) => {
|
|
153
|
+
const runtime = unsafeGetCurrentRuntime();
|
|
154
|
+
const fiber = runtime.fork(effect);
|
|
155
|
+
fiber.join((exit) => {
|
|
156
|
+
const fin = asyncFold(
|
|
157
|
+
(() => {
|
|
158
|
+
try {
|
|
159
|
+
return finalizer(exit);
|
|
160
|
+
} catch {
|
|
161
|
+
return unit();
|
|
162
|
+
}
|
|
163
|
+
})(),
|
|
164
|
+
() => unit(),
|
|
165
|
+
() => unit()
|
|
166
|
+
);
|
|
167
|
+
runtime.fork(fin).join(() => {
|
|
168
|
+
cb(exit);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
return () => {
|
|
172
|
+
fiber.interrupt();
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function resource(acquire, release) {
|
|
177
|
+
return makeResourceFromUse((body) => bracket(acquire, body, release));
|
|
178
|
+
}
|
|
179
|
+
var makeResource = resource;
|
|
180
|
+
function resourceSucceed(value) {
|
|
181
|
+
return makeResourceFromUse((body) => body(value));
|
|
182
|
+
}
|
|
183
|
+
function resourceFromManaged(m) {
|
|
184
|
+
return makeResourceFromUse((body) => useManaged(m, body));
|
|
185
|
+
}
|
|
186
|
+
function useResource(res, body) {
|
|
187
|
+
return res.use(body);
|
|
188
|
+
}
|
|
189
|
+
function resourceAll(resources) {
|
|
190
|
+
const build = (index) => {
|
|
191
|
+
if (index >= resources.length) return resourceSucceed([]);
|
|
192
|
+
return resources[index].flatMap(
|
|
193
|
+
(head) => build(index + 1).map((tail) => [head, ...tail])
|
|
194
|
+
);
|
|
195
|
+
};
|
|
196
|
+
return build(0).map((values) => values);
|
|
197
|
+
}
|
|
198
|
+
var Resource = Object.freeze({
|
|
199
|
+
make: resource,
|
|
200
|
+
succeed: resourceSucceed,
|
|
201
|
+
fromManaged: resourceFromManaged,
|
|
202
|
+
all: resourceAll,
|
|
203
|
+
use: useResource
|
|
204
|
+
});
|
|
205
|
+
function makeResourceFromUse(use) {
|
|
206
|
+
const self = {
|
|
207
|
+
_tag: "Resource",
|
|
208
|
+
use,
|
|
209
|
+
map: (f) => makeResourceFromUse((body) => self.use((a) => body(f(a)))),
|
|
210
|
+
flatMap: (f) => makeResourceFromUse((body) => self.use((a) => f(a).use(body))),
|
|
211
|
+
zip: (that) => self.flatMap((a) => that.map((b) => [a, b]))
|
|
212
|
+
};
|
|
213
|
+
return self;
|
|
214
|
+
}
|
|
215
|
+
function managed(acquire, release) {
|
|
216
|
+
return {
|
|
217
|
+
_tag: "Managed",
|
|
218
|
+
acquire,
|
|
219
|
+
release: (resource2, exit) => release(resource2, exit)
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function useManaged(m, body) {
|
|
223
|
+
return bracket(m.acquire, body, m.release);
|
|
224
|
+
}
|
|
225
|
+
function managedAll(manageds) {
|
|
226
|
+
const acquire = asyncEffect((env, cb) => {
|
|
227
|
+
const runtime = unsafeGetCurrentRuntime();
|
|
228
|
+
const resources = [];
|
|
229
|
+
let i = 0;
|
|
230
|
+
const acquireNext = () => {
|
|
231
|
+
if (i >= manageds.length) {
|
|
232
|
+
cb({ _tag: "Success", value: resources });
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const m = manageds[i];
|
|
236
|
+
const fiber = runtime.fork(m.acquire);
|
|
237
|
+
fiber.join((exit) => {
|
|
238
|
+
if (exit._tag === "Failure") {
|
|
239
|
+
releaseAcquired(runtime, manageds, resources, exit).then(() => {
|
|
240
|
+
cb(exit);
|
|
241
|
+
});
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
resources.push(exit.value);
|
|
245
|
+
i++;
|
|
246
|
+
acquireNext();
|
|
247
|
+
});
|
|
248
|
+
};
|
|
249
|
+
acquireNext();
|
|
250
|
+
});
|
|
251
|
+
const release = (resources, exit) => {
|
|
252
|
+
return asyncEffect((_env, cb) => {
|
|
253
|
+
const runtime = unsafeGetCurrentRuntime();
|
|
254
|
+
releaseAcquired(runtime, manageds, resources, exit).then(() => {
|
|
255
|
+
cb({ _tag: "Success", value: void 0 });
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
return { _tag: "Managed", acquire, release };
|
|
260
|
+
}
|
|
261
|
+
async function releaseAcquired(runtime, manageds, resources, exit) {
|
|
262
|
+
for (let i = resources.length - 1; i >= 0; i--) {
|
|
263
|
+
try {
|
|
264
|
+
const m = manageds[i];
|
|
265
|
+
await new Promise((resolve) => {
|
|
266
|
+
const releaseEff = asyncFold(
|
|
267
|
+
m.release(resources[i], exit),
|
|
268
|
+
() => unit(),
|
|
269
|
+
() => unit()
|
|
270
|
+
);
|
|
271
|
+
runtime.fork(releaseEff).join(() => resolve());
|
|
272
|
+
});
|
|
273
|
+
} catch {
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
105
278
|
// src/core/runtime/schedule.ts
|
|
106
279
|
function recurs(n) {
|
|
107
280
|
return {
|
|
@@ -636,12 +809,359 @@ var Schedule = Object.freeze({
|
|
|
636
809
|
poll: repeatWithSchedule
|
|
637
810
|
});
|
|
638
811
|
|
|
812
|
+
// src/core/runtime/layer.ts
|
|
813
|
+
var MissingLayerServiceError = class extends Error {
|
|
814
|
+
_tag = "MissingLayerService";
|
|
815
|
+
serviceName;
|
|
816
|
+
constructor(serviceName) {
|
|
817
|
+
super(`Missing layer service '${serviceName}'. Add a layer that provides this ServiceTag or pass a LayerContext containing it.`);
|
|
818
|
+
this.name = "MissingLayerServiceError";
|
|
819
|
+
this.serviceName = serviceName;
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
function formatLayerError(error) {
|
|
823
|
+
if (error instanceof MissingLayerServiceError) return error.message;
|
|
824
|
+
if (isObjectRecord(error) && error._tag === "MissingLayerService" && typeof error.serviceName === "string") {
|
|
825
|
+
return `Missing layer service '${error.serviceName}'. Add the provider layer before using the service.`;
|
|
826
|
+
}
|
|
827
|
+
return error instanceof Error ? error.message : String(error);
|
|
828
|
+
}
|
|
829
|
+
function makeServiceTag(name) {
|
|
830
|
+
return {
|
|
831
|
+
_tag: "ServiceTag",
|
|
832
|
+
key: Symbol(name),
|
|
833
|
+
name
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
var serviceTag = makeServiceTag;
|
|
837
|
+
var defineService = makeServiceTag;
|
|
838
|
+
var LayerContext = class _LayerContext {
|
|
839
|
+
services;
|
|
840
|
+
constructor(entries) {
|
|
841
|
+
if (entries instanceof Map) {
|
|
842
|
+
this.services = new Map(entries);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
this.services = /* @__PURE__ */ new Map();
|
|
846
|
+
if (!entries) return;
|
|
847
|
+
for (const [tag, service] of entries) this.services.set(tag.key, service);
|
|
848
|
+
}
|
|
849
|
+
static empty() {
|
|
850
|
+
return new _LayerContext();
|
|
851
|
+
}
|
|
852
|
+
get(tag) {
|
|
853
|
+
return this.services.get(tag.key);
|
|
854
|
+
}
|
|
855
|
+
unsafeGet(tag) {
|
|
856
|
+
if (!this.services.has(tag.key)) {
|
|
857
|
+
throw new MissingLayerServiceError(tag.name);
|
|
858
|
+
}
|
|
859
|
+
return this.services.get(tag.key);
|
|
860
|
+
}
|
|
861
|
+
has(tag) {
|
|
862
|
+
return this.services.has(tag.key);
|
|
863
|
+
}
|
|
864
|
+
add(tag, service) {
|
|
865
|
+
const next = new Map(this.services);
|
|
866
|
+
next.set(tag.key, service);
|
|
867
|
+
return new _LayerContext(next);
|
|
868
|
+
}
|
|
869
|
+
merge(other) {
|
|
870
|
+
const next = new Map(this.services);
|
|
871
|
+
for (const [key, service] of other.services) next.set(key, service);
|
|
872
|
+
return new _LayerContext(next);
|
|
873
|
+
}
|
|
874
|
+
size() {
|
|
875
|
+
return this.services.size;
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
function makeLayerScope() {
|
|
879
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
880
|
+
const finalizers = [];
|
|
881
|
+
let closed = false;
|
|
882
|
+
const scope = {
|
|
883
|
+
get: (l, deps) => {
|
|
884
|
+
if (closed) return asyncFail(new Error("LayerScope is closed"));
|
|
885
|
+
if (cache.has(l)) return asyncSucceed(cache.get(l));
|
|
886
|
+
const built = l.buildScoped ? l.buildScoped(deps, scope) : asyncFlatMap(
|
|
887
|
+
l.build(deps),
|
|
888
|
+
({ service, release }) => asyncFlatMap(scope.addFinalizer(release), () => asyncSucceed(service))
|
|
889
|
+
);
|
|
890
|
+
return asyncFlatMap(
|
|
891
|
+
built,
|
|
892
|
+
(service) => asyncSync(() => {
|
|
893
|
+
cache.set(l, service);
|
|
894
|
+
return service;
|
|
895
|
+
})
|
|
896
|
+
);
|
|
897
|
+
},
|
|
898
|
+
close: () => {
|
|
899
|
+
if (closed) return unit();
|
|
900
|
+
closed = true;
|
|
901
|
+
return releaseAll(finalizers);
|
|
902
|
+
},
|
|
903
|
+
size: () => finalizers.length,
|
|
904
|
+
addFinalizer: (release) => asyncSync(() => {
|
|
905
|
+
if (!closed) finalizers.push(release);
|
|
906
|
+
})
|
|
907
|
+
};
|
|
908
|
+
return scope;
|
|
909
|
+
}
|
|
910
|
+
function releaseAll(finalizers) {
|
|
911
|
+
const next = finalizers.pop();
|
|
912
|
+
if (!next) return unit();
|
|
913
|
+
return asyncFold(
|
|
914
|
+
next(),
|
|
915
|
+
() => releaseAll(finalizers),
|
|
916
|
+
() => releaseAll(finalizers)
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
function mergeServices(a, b) {
|
|
920
|
+
if (a instanceof LayerContext && b instanceof LayerContext) {
|
|
921
|
+
return a.merge(b);
|
|
922
|
+
}
|
|
923
|
+
if (isObjectRecord(a) && isObjectRecord(b)) {
|
|
924
|
+
return { ...a, ...b };
|
|
925
|
+
}
|
|
926
|
+
return Object.assign({}, a, b);
|
|
927
|
+
}
|
|
928
|
+
function isObjectRecord(value) {
|
|
929
|
+
return typeof value === "object" && value !== null;
|
|
930
|
+
}
|
|
931
|
+
function layer(acquire, release) {
|
|
932
|
+
return {
|
|
933
|
+
_tag: "Layer",
|
|
934
|
+
build: (_deps) => asyncFlatMap(acquire(), (service) => asyncSucceed({
|
|
935
|
+
service,
|
|
936
|
+
release: release ? () => release(service) : () => unit()
|
|
937
|
+
}))
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
function layerValue(tag, value) {
|
|
941
|
+
return layerEffect(tag, () => asyncSucceed(value));
|
|
942
|
+
}
|
|
943
|
+
var makeTestLayer = layerValue;
|
|
944
|
+
function makeTestLayers(...providers) {
|
|
945
|
+
return {
|
|
946
|
+
_tag: "Layer",
|
|
947
|
+
build: (deps = LayerContext.empty()) => asyncSucceed({
|
|
948
|
+
service: providers.reduce(
|
|
949
|
+
(context, [tag, service]) => context.add(tag, service),
|
|
950
|
+
deps
|
|
951
|
+
),
|
|
952
|
+
release: () => unit()
|
|
953
|
+
})
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
function layerEffect(tag, acquire, release) {
|
|
957
|
+
return {
|
|
958
|
+
_tag: "Layer",
|
|
959
|
+
build: (deps = LayerContext.empty()) => asyncFlatMap(acquire(deps), (service) => asyncSucceed({
|
|
960
|
+
service: deps.add(tag, service),
|
|
961
|
+
release: release ? () => release(service) : () => unit()
|
|
962
|
+
}))
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
var layerFromContext = layerEffect;
|
|
966
|
+
var defineLayer = layerEffect;
|
|
967
|
+
function getService(tag) {
|
|
968
|
+
return asyncSync((context) => context.unsafeGet(tag));
|
|
969
|
+
}
|
|
970
|
+
function getServices(tags) {
|
|
971
|
+
return asyncSync((context) => readServices(context, tags));
|
|
972
|
+
}
|
|
973
|
+
function useService(tag, use) {
|
|
974
|
+
return (context) => {
|
|
975
|
+
let service;
|
|
976
|
+
try {
|
|
977
|
+
service = context.unsafeGet(tag);
|
|
978
|
+
} catch (error) {
|
|
979
|
+
return asyncFail(error);
|
|
980
|
+
}
|
|
981
|
+
return use(service);
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
function useServices(tags, use) {
|
|
985
|
+
return (context) => {
|
|
986
|
+
let services;
|
|
987
|
+
try {
|
|
988
|
+
services = readServices(context, tags);
|
|
989
|
+
} catch (error) {
|
|
990
|
+
return asyncFail(error);
|
|
991
|
+
}
|
|
992
|
+
return use(services);
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
function readServices(context, tags) {
|
|
996
|
+
const services = {};
|
|
997
|
+
for (const key of Object.keys(tags)) {
|
|
998
|
+
services[key] = context.unsafeGet(tags[key]);
|
|
999
|
+
}
|
|
1000
|
+
return services;
|
|
1001
|
+
}
|
|
1002
|
+
function layerFrom() {
|
|
1003
|
+
return (acquire, release) => ({
|
|
1004
|
+
_tag: "Layer",
|
|
1005
|
+
build: (deps) => asyncFlatMap(acquire(deps), (service) => asyncSucceed({
|
|
1006
|
+
service,
|
|
1007
|
+
release: release ? () => release(service) : () => unit()
|
|
1008
|
+
}))
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
function layerSucceed(value) {
|
|
1012
|
+
return {
|
|
1013
|
+
_tag: "Layer",
|
|
1014
|
+
build: () => asyncSucceed({ service: value, release: () => unit() })
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
function layerFail(error) {
|
|
1018
|
+
return {
|
|
1019
|
+
_tag: "Layer",
|
|
1020
|
+
build: () => asyncFail(error)
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
function compose(from, to) {
|
|
1024
|
+
return {
|
|
1025
|
+
_tag: "Layer",
|
|
1026
|
+
buildScoped: (deps, scope) => asyncFlatMap(
|
|
1027
|
+
scope.get(from, deps),
|
|
1028
|
+
(mid) => scope.get(to, mid)
|
|
1029
|
+
),
|
|
1030
|
+
build: (deps) => asyncFlatMap(
|
|
1031
|
+
from.build(deps),
|
|
1032
|
+
({ service: mid, release: releaseMid }) => asyncFold(
|
|
1033
|
+
to.build(mid),
|
|
1034
|
+
(error) => asyncFlatMap(releaseMid(), () => asyncFail(error)),
|
|
1035
|
+
({ service: out, release: releaseOut }) => asyncSucceed({
|
|
1036
|
+
service: out,
|
|
1037
|
+
release: () => asyncFlatMap(releaseOut(), () => releaseMid())
|
|
1038
|
+
})
|
|
1039
|
+
)
|
|
1040
|
+
)
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
function composeAll(...layers) {
|
|
1044
|
+
return layers.slice(1).reduce(
|
|
1045
|
+
(acc, next) => compose(acc, next),
|
|
1046
|
+
layers[0]
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
function merge(left, right) {
|
|
1050
|
+
return {
|
|
1051
|
+
_tag: "Layer",
|
|
1052
|
+
buildScoped: (deps, scope) => asyncFlatMap(
|
|
1053
|
+
scope.get(left, deps),
|
|
1054
|
+
(a) => asyncFlatMap(
|
|
1055
|
+
scope.get(right, deps),
|
|
1056
|
+
(b) => asyncSucceed(mergeServices(a, b))
|
|
1057
|
+
)
|
|
1058
|
+
),
|
|
1059
|
+
build: (deps) => asyncFlatMap(
|
|
1060
|
+
left.build(deps),
|
|
1061
|
+
({ service: a, release: releaseA }) => asyncFold(
|
|
1062
|
+
right.build(deps),
|
|
1063
|
+
(error) => asyncFlatMap(releaseA(), () => asyncFail(error)),
|
|
1064
|
+
({ service: b, release: releaseB }) => asyncSucceed({
|
|
1065
|
+
service: mergeServices(a, b),
|
|
1066
|
+
release: () => asyncFlatMap(releaseB(), () => releaseA())
|
|
1067
|
+
})
|
|
1068
|
+
)
|
|
1069
|
+
)
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
function mergeAll(...layers) {
|
|
1073
|
+
return layers.slice(1).reduce(
|
|
1074
|
+
(acc, next) => merge(acc, next),
|
|
1075
|
+
layers[0]
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
function mapLayer(l, f) {
|
|
1079
|
+
return {
|
|
1080
|
+
_tag: "Layer",
|
|
1081
|
+
buildScoped: (deps, scope) => asyncFlatMap(
|
|
1082
|
+
scope.get(l, deps),
|
|
1083
|
+
(service) => asyncSucceed(f(service))
|
|
1084
|
+
),
|
|
1085
|
+
build: (deps) => asyncFlatMap(
|
|
1086
|
+
l.build(deps),
|
|
1087
|
+
({ service, release }) => asyncSucceed({ service: f(service), release })
|
|
1088
|
+
)
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
function buildLayer(l, deps) {
|
|
1092
|
+
const scope = makeLayerScope();
|
|
1093
|
+
return asyncFold(
|
|
1094
|
+
scope.get(l, deps),
|
|
1095
|
+
(error) => asyncFlatMap(scope.close(), () => asyncFail(error)),
|
|
1096
|
+
(service) => asyncSucceed({
|
|
1097
|
+
service,
|
|
1098
|
+
scope,
|
|
1099
|
+
close: scope.close,
|
|
1100
|
+
use: (body) => body(service)
|
|
1101
|
+
})
|
|
1102
|
+
);
|
|
1103
|
+
}
|
|
1104
|
+
function provideLayer(l, use, deps) {
|
|
1105
|
+
return asyncFlatMap(
|
|
1106
|
+
buildLayer(l, deps ?? {}),
|
|
1107
|
+
({ service, close }) => ensuring(
|
|
1108
|
+
use(service),
|
|
1109
|
+
() => close()
|
|
1110
|
+
)
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
function provideLayerContext(l, use, deps = LayerContext.empty()) {
|
|
1114
|
+
return provideLayer(l, use, deps);
|
|
1115
|
+
}
|
|
1116
|
+
var provide = provideLayer;
|
|
1117
|
+
var provideContext = provideLayerContext;
|
|
1118
|
+
var Layer = Object.freeze({
|
|
1119
|
+
make: layer,
|
|
1120
|
+
from: layerFrom,
|
|
1121
|
+
succeed: layerSucceed,
|
|
1122
|
+
fail: layerFail,
|
|
1123
|
+
value: layerValue,
|
|
1124
|
+
test: makeTestLayer,
|
|
1125
|
+
tests: makeTestLayers,
|
|
1126
|
+
effect: layerEffect,
|
|
1127
|
+
define: defineLayer,
|
|
1128
|
+
fromContext: layerFromContext,
|
|
1129
|
+
compose,
|
|
1130
|
+
composeAll,
|
|
1131
|
+
merge,
|
|
1132
|
+
all: mergeAll,
|
|
1133
|
+
mergeAll,
|
|
1134
|
+
map: mapLayer,
|
|
1135
|
+
provide: provideLayer,
|
|
1136
|
+
provideContext: provideLayerContext,
|
|
1137
|
+
build: buildLayer,
|
|
1138
|
+
scope: makeLayerScope,
|
|
1139
|
+
context: LayerContext.empty,
|
|
1140
|
+
tag: makeServiceTag,
|
|
1141
|
+
service: getService,
|
|
1142
|
+
services: getServices,
|
|
1143
|
+
use: useService,
|
|
1144
|
+
useAll: useServices
|
|
1145
|
+
});
|
|
1146
|
+
|
|
639
1147
|
export {
|
|
640
1148
|
sleep,
|
|
641
1149
|
timeout,
|
|
642
1150
|
retry,
|
|
643
1151
|
retryN,
|
|
644
1152
|
retryWithBackoff,
|
|
1153
|
+
bracket,
|
|
1154
|
+
ensuring,
|
|
1155
|
+
resource,
|
|
1156
|
+
makeResource,
|
|
1157
|
+
resourceSucceed,
|
|
1158
|
+
resourceFromManaged,
|
|
1159
|
+
useResource,
|
|
1160
|
+
resourceAll,
|
|
1161
|
+
Resource,
|
|
1162
|
+
managed,
|
|
1163
|
+
useManaged,
|
|
1164
|
+
managedAll,
|
|
645
1165
|
recurs,
|
|
646
1166
|
forever,
|
|
647
1167
|
never,
|
|
@@ -679,5 +1199,37 @@ export {
|
|
|
679
1199
|
repeatWithSchedule,
|
|
680
1200
|
repeat,
|
|
681
1201
|
poll,
|
|
682
|
-
Schedule
|
|
1202
|
+
Schedule,
|
|
1203
|
+
MissingLayerServiceError,
|
|
1204
|
+
formatLayerError,
|
|
1205
|
+
makeServiceTag,
|
|
1206
|
+
serviceTag,
|
|
1207
|
+
defineService,
|
|
1208
|
+
LayerContext,
|
|
1209
|
+
makeLayerScope,
|
|
1210
|
+
layer,
|
|
1211
|
+
layerValue,
|
|
1212
|
+
makeTestLayer,
|
|
1213
|
+
makeTestLayers,
|
|
1214
|
+
layerEffect,
|
|
1215
|
+
layerFromContext,
|
|
1216
|
+
defineLayer,
|
|
1217
|
+
getService,
|
|
1218
|
+
getServices,
|
|
1219
|
+
useService,
|
|
1220
|
+
useServices,
|
|
1221
|
+
layerFrom,
|
|
1222
|
+
layerSucceed,
|
|
1223
|
+
layerFail,
|
|
1224
|
+
compose,
|
|
1225
|
+
composeAll,
|
|
1226
|
+
merge,
|
|
1227
|
+
mergeAll,
|
|
1228
|
+
mapLayer,
|
|
1229
|
+
buildLayer,
|
|
1230
|
+
provideLayer,
|
|
1231
|
+
provideLayerContext,
|
|
1232
|
+
provide,
|
|
1233
|
+
provideContext,
|
|
1234
|
+
Layer
|
|
683
1235
|
};
|