better-effect 0.4.0 → 0.6.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 +92 -11
- package/dist/adapters/iti.d.mts +11 -3
- package/dist/adapters/iti.d.mts.map +1 -1
- package/dist/adapters/iti.mjs +35 -14
- package/dist/adapters/iti.mjs.map +1 -1
- package/dist/errors-GR3K_nRu.mjs +74 -0
- package/dist/errors-GR3K_nRu.mjs.map +1 -0
- package/dist/index-DMfjhNR_.d.mts +500 -0
- package/dist/index-DMfjhNR_.d.mts.map +1 -0
- package/dist/index.d.mts +225 -32
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +419 -168
- package/dist/index.mjs.map +1 -1
- package/dist/internal-identity-C6Awrc33.mjs +27 -0
- package/dist/internal-identity-C6Awrc33.mjs.map +1 -0
- package/dist/runtime-CDcCF5cb.mjs +10 -0
- package/dist/runtime-CDcCF5cb.mjs.map +1 -0
- package/dist/testing.d.mts +11 -2
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +34 -12
- package/dist/testing.mjs.map +1 -1
- package/package.json +13 -5
- package/dist/errors-DlHCwICc.mjs +0 -67
- package/dist/errors-DlHCwICc.mjs.map +0 -1
- package/dist/index-BYQKfyeJ.d.mts +0 -235
- package/dist/index-BYQKfyeJ.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -16,13 +16,13 @@ bun add better-effect better-result
|
|
|
16
16
|
import { Result } from 'better-result'
|
|
17
17
|
import { Effect, Layer, Runtime, Service } from 'better-effect'
|
|
18
18
|
|
|
19
|
-
class Database extends Service<Database>() {
|
|
19
|
+
class Database extends Service<Database>()('Database') {
|
|
20
20
|
findUser(id: string) {
|
|
21
21
|
// ...
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
class UserRepository extends Service<UserRepository>() {
|
|
25
|
+
class UserRepository extends Service<UserRepository>()('UserRepository') {
|
|
26
26
|
findUser(id: string) {
|
|
27
27
|
return Effect.gen(async function* () {
|
|
28
28
|
const database = yield* Database
|
|
@@ -32,21 +32,63 @@ class UserRepository extends Service<UserRepository>() {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const UserRepositoryLive = Layer.make(UserRepository
|
|
35
|
+
const UserRepositoryLive = Layer.make(UserRepository)
|
|
36
36
|
|
|
37
37
|
await Runtime.make(UserRepositoryLive, backend)
|
|
38
38
|
// ^^^^^^^^^^^^^^^^^^
|
|
39
39
|
// Type error: Database is required but not provided
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
The explicit self type keeps `yield*` inference exact, while the non-empty
|
|
43
|
+
literal is the Service's stable logical identity. Services with identical
|
|
44
|
+
methods but different tags are different dependencies; use a namespaced tag
|
|
45
|
+
such as `@acme/Database` when identities must be shared across packages.
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
`UserRepository` used `Database`, so `Database` became part of its environment requirements:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
type FindUser = Awaited<ReturnType<UserRepository['findUser']>>
|
|
51
|
+
// Effect<User, never, Database>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`Effect<A, E, R>` is a type-only facade over a `better-result` Result, not an Effect TS
|
|
55
|
+
instruction tree. Constructors remain the handles used by `yield*`, Layers and resolver backends;
|
|
56
|
+
the public requirement `R` is a union of tagged Service instances. No dependency list was written
|
|
57
|
+
manually.
|
|
58
|
+
|
|
59
|
+
Services can also describe a contract without requiring a class instance. Use the
|
|
60
|
+
static `of` helper to type-check a structural implementation; it returns the same
|
|
61
|
+
object unchanged at runtime:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
class Authorization extends Service<Authorization>()('Authorization') {
|
|
65
|
+
declare readonly authorize: (token: string) => Promise<boolean>
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const authorization = Authorization.of({
|
|
69
|
+
authorize: async (token) => token.length > 0
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const AuthorizationLive = Layer.succeed(Authorization, authorization)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`Authorization.of(...)` does not call a constructor or make the result an
|
|
76
|
+
`instanceof Authorization`. For services with constructors, private fields or
|
|
77
|
+
other runtime invariants, use `new Authorization(...)` instead.
|
|
78
|
+
|
|
79
|
+
Service tokens themselves are always declared through `Service<Self>()(tag)`.
|
|
80
|
+
Every instance carries a required, declaration-only `ServiceIdentity<Tag>`; no
|
|
81
|
+
identity property exists at runtime. `Service.Contract<Authorization>` projects
|
|
82
|
+
the marker-free implementation shape accepted by `Service.of` and all Layer
|
|
83
|
+
provider APIs. Those boundaries return or provide the branded Service type
|
|
84
|
+
without modifying the implementation object. `Service.of(...)` does not create
|
|
85
|
+
an alternate token, so the instance contract stays tied to the constructor used
|
|
86
|
+
by Layers and resolver backends.
|
|
45
87
|
|
|
46
88
|
Provide it and the environment becomes complete:
|
|
47
89
|
|
|
48
90
|
```ts
|
|
49
|
-
const DatabaseLive = Layer.make(Database
|
|
91
|
+
const DatabaseLive = Layer.make(Database)
|
|
50
92
|
|
|
51
93
|
const AppLive = Layer.merge(DatabaseLive, UserRepositoryLive)
|
|
52
94
|
|
|
@@ -89,6 +131,40 @@ We call this **typechecked wiring**.
|
|
|
89
131
|
|
|
90
132
|
The Services your code uses, the implementations your Layers provide, and the programs your Runtime executes participate in the same type-level contract.
|
|
91
133
|
|
|
134
|
+
A Layer's public type is `Layer<Provided, Required>`. `Provided` is the Service
|
|
135
|
+
instance union produced by the Layer and `Required` is only the external
|
|
136
|
+
requirement union left after composition. Preserve inferred Layers when possible;
|
|
137
|
+
use `satisfies Layer<Provided, Required>` when checking an application boundary
|
|
138
|
+
without erasing provider provenance.
|
|
139
|
+
|
|
140
|
+
Generic infrastructure that intentionally erases this metadata can use the
|
|
141
|
+
explicit `Layer.Any` sentinel, including for an empty Layer. Bare Layers,
|
|
142
|
+
partial-`any` shapes and concrete unions such as `Layer<A> | Layer<B>` are not
|
|
143
|
+
implicit unchecked boundaries.
|
|
144
|
+
|
|
145
|
+
### Discover type helpers from their API
|
|
146
|
+
|
|
147
|
+
Public type helpers are also grouped under the runtime API they describe:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import type { Effect, Layer, Runtime, Scope, Service } from 'better-effect'
|
|
151
|
+
|
|
152
|
+
type Program = ReturnType<UserRepository['findUser']>
|
|
153
|
+
type Success = Effect.Success<Program>
|
|
154
|
+
type Failure = Effect.Error<Program>
|
|
155
|
+
type Dependencies = Effect.Requirements<Program>
|
|
156
|
+
type Services = Layer.Provided<typeof AppLive>
|
|
157
|
+
type AppRuntime = Runtime.For<typeof AppLive>
|
|
158
|
+
type DatabaseTag = Service.Tag<Database> // 'Database'
|
|
159
|
+
type DatabaseToken = Service.TokenOf<Database> // Service.Token<'Database', Database>
|
|
160
|
+
type Outcome = Scope.Outcome
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
These are declaration-only aliases and add nothing to the JavaScript bundle.
|
|
164
|
+
The associated `Layer` helpers are intentionally namespaced; use
|
|
165
|
+
`Layer.Provided`, `Layer.Required`, `Layer.Complete` and `Layer.Any` rather than
|
|
166
|
+
low-level provider metadata names.
|
|
167
|
+
|
|
92
168
|
---
|
|
93
169
|
|
|
94
170
|
## Why better-effect?
|
|
@@ -168,9 +244,11 @@ Resources acquired during an individual execution belong to that execution inste
|
|
|
168
244
|
|
|
169
245
|
`better-effect` is not a replacement implementation of Effect.
|
|
170
246
|
|
|
171
|
-
It does not introduce a fiber runtime, scheduler, streams, queues or a
|
|
247
|
+
It does not introduce a fiber runtime, scheduler, streams, queues or a lazy runtime instruction tree.
|
|
172
248
|
|
|
173
|
-
|
|
249
|
+
Its public `Effect<A, E, R>` is only a type-level Result facade. `Effect.gen` builds on
|
|
250
|
+
`better-result` generator composition while carrying Service instance requirements through the
|
|
251
|
+
TypeScript type system.
|
|
174
252
|
|
|
175
253
|
Dependency resolution stays behind a pluggable backend.
|
|
176
254
|
|
|
@@ -245,8 +323,9 @@ Application resources live with the Runtime. Execution resources live with the e
|
|
|
245
323
|
Keep `better-result` as the source of truth for typed successes, failures, short-circuiting
|
|
246
324
|
and generator control flow. `Effect.gen` delegates to `Result.gen`; it adds only the
|
|
247
325
|
phantom Service requirements that TypeScript needs to check the application environment.
|
|
248
|
-
At runtime, an `
|
|
249
|
-
only in the type.
|
|
326
|
+
At runtime, an `Effect<A, E, R>` is still a `better-result` Result; the requirements exist
|
|
327
|
+
only in the type. `Effect.Requirements`, `Layer.Provided`, `Layer.Required` and
|
|
328
|
+
`Runtime.For` expose tagged Service instance unions.
|
|
250
329
|
|
|
251
330
|
For a linear workflow, `pipe` composes the same kind of program without introducing a
|
|
252
331
|
second Result model or a lazy Effect runtime:
|
|
@@ -264,7 +343,9 @@ const program = pipe(
|
|
|
264
343
|
|
|
265
344
|
The combinators keep the `better-result` semantics: `Effect.map` changes the success
|
|
266
345
|
type, `Effect.mapError` changes the error type, and `Effect.andThen` only calls the next
|
|
267
|
-
step after an `Ok`.
|
|
346
|
+
step after an `Ok`. Use `Effect.andThenAsync` when the next operation returns a
|
|
347
|
+
`Promise<Result>`; it always returns a Promise, including when the source is synchronous
|
|
348
|
+
or already an `Err`. The pipeline carries the requirements of every step, so Runtime
|
|
268
349
|
still rejects it when its Layer does not provide every required Service.
|
|
269
350
|
|
|
270
351
|
Use `Effect.gen` for larger workflows with several intermediate values, branches or
|
package/dist/adapters/iti.d.mts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as LayerRegistration, t as LayerBackend, z as AnyServiceToken } from "../index-DMfjhNR_.mjs";
|
|
2
2
|
//#region src/adapters/iti.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* ITI-backed Layer backend.
|
|
5
|
+
*
|
|
6
|
+
* Install `iti` as the optional peer dependency and pass an instance to
|
|
7
|
+
* `Runtime.make` when using ITI's container implementation.
|
|
8
|
+
*/
|
|
3
9
|
declare class ItiLayerBackend implements LayerBackend {
|
|
4
10
|
private container;
|
|
5
11
|
private readonly keys;
|
|
6
12
|
private readonly registered;
|
|
7
|
-
private nextId;
|
|
8
13
|
private keyFor;
|
|
9
|
-
|
|
14
|
+
/** Register a Layer provider under its deterministic Service-tag key. */
|
|
15
|
+
register(registration: LayerRegistration): void;
|
|
16
|
+
/** Resolve a registered Service through the ITI container. */
|
|
10
17
|
resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>>;
|
|
18
|
+
/** Dispose all ITI-managed provider instances. */
|
|
11
19
|
disposeAll(): Promise<void>;
|
|
12
20
|
}
|
|
13
21
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iti.d.mts","names":[],"sources":["../../src/adapters/iti.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"iti.d.mts","names":[],"sources":["../../src/adapters/iti.ts"],"mappings":";;;;;;;;cAsBa,2BAA2B;UAC9B;mBAES;mBAEA;UAET;;EAgBR,SAAS,cAAc;;EAuBvB,QAAQ,UAAU,iBAAiB,OAAO,IAAI,aAAa,KAAK,YAAY,aAAa;;EAyBnF,cAAc"}
|
package/dist/adapters/iti.mjs
CHANGED
|
@@ -1,30 +1,51 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ServiceTagCollisionError, o as ServiceNotFoundError, t as DuplicateServiceError } from "../errors-GR3K_nRu.mjs";
|
|
2
|
+
import { t as isPromiseLike } from "../runtime-CDcCF5cb.mjs";
|
|
3
|
+
import { t as assertServiceCompatibility } from "../internal-identity-C6Awrc33.mjs";
|
|
2
4
|
import { createContainer } from "iti";
|
|
3
5
|
//#region src/adapters/iti.ts
|
|
6
|
+
/**
|
|
7
|
+
* ITI-backed Layer backend.
|
|
8
|
+
*
|
|
9
|
+
* Install `iti` as the optional peer dependency and pass an instance to
|
|
10
|
+
* `Runtime.make` when using ITI's container implementation.
|
|
11
|
+
*/
|
|
4
12
|
var ItiLayerBackend = class {
|
|
5
13
|
container = createContainer();
|
|
6
|
-
keys = /* @__PURE__ */ new
|
|
7
|
-
registered = /* @__PURE__ */ new
|
|
8
|
-
nextId = 0;
|
|
14
|
+
keys = /* @__PURE__ */ new Map();
|
|
15
|
+
registered = /* @__PURE__ */ new Map();
|
|
9
16
|
keyFor(token) {
|
|
10
|
-
const
|
|
17
|
+
const tag = token.serviceTag;
|
|
18
|
+
const existing = this.keys.get(tag);
|
|
11
19
|
if (existing) return existing;
|
|
12
|
-
const key = `better-effect:${
|
|
13
|
-
this.keys.set(
|
|
20
|
+
const key = `better-effect:${tag}`;
|
|
21
|
+
this.keys.set(tag, key);
|
|
14
22
|
return key;
|
|
15
23
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
/** Register a Layer provider under its deterministic Service-tag key. */
|
|
25
|
+
register(registration) {
|
|
26
|
+
const token = registration.service;
|
|
27
|
+
const tag = token.serviceTag;
|
|
28
|
+
const existing = this.registered.get(tag);
|
|
29
|
+
if (existing === token) throw new DuplicateServiceError(token);
|
|
30
|
+
if (existing) throw new ServiceTagCollisionError(existing, token);
|
|
19
31
|
const key = this.keyFor(token);
|
|
20
|
-
this.container = this.container.add({ [key]:
|
|
21
|
-
this.registered.
|
|
32
|
+
this.container = this.container.add({ [key]: registration.acquire });
|
|
33
|
+
this.registered.set(tag, token);
|
|
22
34
|
}
|
|
35
|
+
/** Resolve a registered Service through the ITI container. */
|
|
23
36
|
resolve(token) {
|
|
24
|
-
|
|
37
|
+
const registered = this.registered.get(token.serviceTag);
|
|
38
|
+
if (registered === void 0) throw new ServiceNotFoundError(token);
|
|
25
39
|
const key = this.keyFor(token);
|
|
26
|
-
|
|
40
|
+
const resolved = this.container.get(key);
|
|
41
|
+
const validate = (instance) => {
|
|
42
|
+
assertServiceCompatibility(token, registered, instance);
|
|
43
|
+
return instance;
|
|
44
|
+
};
|
|
45
|
+
if (isPromiseLike(resolved)) return Promise.resolve(resolved).then(validate);
|
|
46
|
+
return validate(resolved);
|
|
27
47
|
}
|
|
48
|
+
/** Dispose all ITI-managed provider instances. */
|
|
28
49
|
async disposeAll() {
|
|
29
50
|
await this.container.disposeAll();
|
|
30
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iti.mjs","names":[],"sources":["../../src/adapters/iti.ts"],"sourcesContent":["import { createContainer } from 'iti'\n\nimport {
|
|
1
|
+
{"version":3,"file":"iti.mjs","names":[],"sources":["../../src/adapters/iti.ts"],"sourcesContent":["import { createContainer } from 'iti'\n\nimport {\n DuplicateServiceError,\n ServiceTagCollisionError,\n type LayerBackend,\n type LayerRegistration\n} from '../layer'\n\nimport { ServiceNotFoundError, type AnyServiceToken } from '../service'\n\nimport { assertServiceCompatibility } from '../layer/internal-identity'\nimport { isPromiseLike } from '../utils/runtime'\n\ntype LayerAcquiredValue = Awaited<ReturnType<LayerRegistration['acquire']>>\n\n/**\n * ITI-backed Layer backend.\n *\n * Install `iti` as the optional peer dependency and pass an instance to\n * `Runtime.make` when using ITI's container implementation.\n */\nexport class ItiLayerBackend implements LayerBackend {\n private container: any = createContainer()\n\n private readonly keys = new Map<string, string>()\n\n private readonly registered = new Map<string, AnyServiceToken>()\n\n private keyFor(token: AnyServiceToken): string {\n const tag = token.serviceTag\n const existing = this.keys.get(tag)\n\n if (existing) {\n return existing\n }\n\n const key = `better-effect:${tag}`\n\n this.keys.set(tag, key)\n\n return key\n }\n\n /** Register a Layer provider under its deterministic Service-tag key. */\n register(registration: LayerRegistration): void {\n const token = registration.service\n const tag = token.serviceTag\n const existing = this.registered.get(tag)\n\n if (existing === token) {\n throw new DuplicateServiceError(token)\n }\n\n if (existing) {\n throw new ServiceTagCollisionError(existing, token)\n }\n\n const key = this.keyFor(token)\n\n this.container = this.container.add({\n [key]: registration.acquire\n })\n\n this.registered.set(tag, token)\n }\n\n /** Resolve a registered Service through the ITI container. */\n resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>> {\n const registered = this.registered.get(token.serviceTag)\n\n if (registered === undefined) {\n throw new ServiceNotFoundError(token)\n }\n\n const key = this.keyFor(token)\n const resolved = this.container.get(key)\n\n const validate = (instance: LayerAcquiredValue): InstanceType<T> => {\n assertServiceCompatibility(token, registered, instance)\n\n // SAFETY: The registered tag and compatibility check establish the constructor-to-instance relationship after ITI erases it.\n return instance as InstanceType<T>\n }\n\n if (isPromiseLike(resolved)) {\n return Promise.resolve(resolved).then(validate)\n }\n\n return validate(resolved)\n }\n\n /** Dispose all ITI-managed provider instances. */\n async disposeAll(): Promise<void> {\n await this.container.disposeAll()\n }\n}\n"],"mappings":";;;;;;;;;;;AAsBA,IAAa,kBAAb,MAAqD;CACnD,YAAyB,gBAAgB;CAEzC,uBAAwB,IAAI,IAAoB;CAEhD,6BAA8B,IAAI,IAA6B;CAE/D,OAAe,OAAgC;EAC7C,MAAM,MAAM,MAAM;EAClB,MAAM,WAAW,KAAK,KAAK,IAAI,GAAG;EAElC,IAAI,UACF,OAAO;EAGT,MAAM,MAAM,iBAAiB;EAE7B,KAAK,KAAK,IAAI,KAAK,GAAG;EAEtB,OAAO;CACT;;CAGA,SAAS,cAAuC;EAC9C,MAAM,QAAQ,aAAa;EAC3B,MAAM,MAAM,MAAM;EAClB,MAAM,WAAW,KAAK,WAAW,IAAI,GAAG;EAExC,IAAI,aAAa,OACf,MAAM,IAAI,sBAAsB,KAAK;EAGvC,IAAI,UACF,MAAM,IAAI,yBAAyB,UAAU,KAAK;EAGpD,MAAM,MAAM,KAAK,OAAO,KAAK;EAE7B,KAAK,YAAY,KAAK,UAAU,IAAI,GACjC,MAAM,aAAa,QACtB,CAAC;EAED,KAAK,WAAW,IAAI,KAAK,KAAK;CAChC;;CAGA,QAAmC,OAA0D;EAC3F,MAAM,aAAa,KAAK,WAAW,IAAI,MAAM,UAAU;EAEvD,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,MAAM,KAAK,OAAO,KAAK;EAC7B,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,MAAM,YAAY,aAAkD;GAClE,2BAA2B,OAAO,YAAY,QAAQ;GAGtD,OAAO;EACT;EAEA,IAAI,cAAc,QAAQ,GACxB,OAAO,QAAQ,QAAQ,QAAQ,CAAC,CAAC,KAAK,QAAQ;EAGhD,OAAO,SAAS,QAAQ;CAC1B;;CAGA,MAAM,aAA4B;EAChC,MAAM,KAAK,UAAU,WAAW;CAClC;AACF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
//#region src/service/errors.ts
|
|
2
|
+
/** Thrown when a Service is accessed without an active runtime resolver. */
|
|
3
|
+
var ServiceRuntimeNotConfiguredError = class extends Error {
|
|
4
|
+
constructor() {
|
|
5
|
+
super("No ServiceResolver is available in the current runtime context");
|
|
6
|
+
this.name = "ServiceRuntimeNotConfiguredError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
/** Thrown when a runtime has no provider for the requested Service tag. */
|
|
10
|
+
var ServiceNotFoundError = class extends Error {
|
|
11
|
+
service;
|
|
12
|
+
constructor(service) {
|
|
13
|
+
super(`Service "${service.serviceTag}" was not provided`);
|
|
14
|
+
this.service = service;
|
|
15
|
+
this.name = "ServiceNotFoundError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/layer/errors.ts
|
|
20
|
+
/** Thrown when a Layer registers the same Service tag more than once. */
|
|
21
|
+
var DuplicateServiceError = class extends Error {
|
|
22
|
+
service;
|
|
23
|
+
constructor(service) {
|
|
24
|
+
super(`Duplicate service tag "${service.serviceTag}"`);
|
|
25
|
+
this.service = service;
|
|
26
|
+
this.name = "DuplicateServiceError";
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/** Thrown when one Service tag is associated with incompatible constructors. */
|
|
30
|
+
var ServiceTagCollisionError = class extends Error {
|
|
31
|
+
existing;
|
|
32
|
+
incoming;
|
|
33
|
+
constructor(existing, incoming) {
|
|
34
|
+
super(`Service tag "${incoming.serviceTag}" is already associated with "${existing.name}" and cannot be associated with "${incoming.name}"`);
|
|
35
|
+
this.existing = existing;
|
|
36
|
+
this.incoming = incoming;
|
|
37
|
+
this.name = "ServiceTagCollisionError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
/** Thrown when a backend fails while registering a Layer provider. */
|
|
41
|
+
var LayerRegistrationError = class extends Error {
|
|
42
|
+
service;
|
|
43
|
+
registrationCause;
|
|
44
|
+
cleanupCause;
|
|
45
|
+
constructor(service, registrationCause, cleanupCause) {
|
|
46
|
+
super(service ? `Failed to register service "${service.serviceTag}"` : "Failed to build Layer", { cause: registrationCause });
|
|
47
|
+
this.service = service;
|
|
48
|
+
this.registrationCause = registrationCause;
|
|
49
|
+
this.cleanupCause = cleanupCause;
|
|
50
|
+
this.name = "LayerRegistrationError";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/** Thrown when one or more Layer-owned resources fail during disposal. */
|
|
54
|
+
var LayerDisposeError = class extends Error {
|
|
55
|
+
causes;
|
|
56
|
+
constructor(causes) {
|
|
57
|
+
super(`Failed to dispose Layer (${causes.length} error${causes.length === 1 ? "" : "s"})`);
|
|
58
|
+
this.causes = causes;
|
|
59
|
+
this.name = "LayerDisposeError";
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/** Thrown when a Layer generator yields a value other than a Service requirement. */
|
|
63
|
+
var LayerGeneratorYieldError = class extends Error {
|
|
64
|
+
service;
|
|
65
|
+
constructor(service) {
|
|
66
|
+
super(`Layer.gen("${service.serviceTag}") yielded an unsupported value`);
|
|
67
|
+
this.service = service;
|
|
68
|
+
this.name = "LayerGeneratorYieldError";
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { ServiceTagCollisionError as a, LayerRegistrationError as i, LayerDisposeError as n, ServiceNotFoundError as o, LayerGeneratorYieldError as r, ServiceRuntimeNotConfiguredError as s, DuplicateServiceError as t };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=errors-GR3K_nRu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-GR3K_nRu.mjs","names":[],"sources":["../src/service/errors.ts","../src/layer/errors.ts"],"sourcesContent":["import type { AnyServiceToken } from './types'\n\n/** Thrown when a Service is accessed without an active runtime resolver. */\nexport class ServiceRuntimeNotConfiguredError extends Error {\n constructor() {\n super('No ServiceResolver is available in the current runtime context')\n\n this.name = 'ServiceRuntimeNotConfiguredError'\n }\n}\n\n/** Thrown when a runtime has no provider for the requested Service tag. */\nexport class ServiceNotFoundError extends Error {\n constructor(readonly service: AnyServiceToken) {\n super(`Service \"${service.serviceTag}\" was not provided`)\n\n this.name = 'ServiceNotFoundError'\n }\n}\n","import type { AnyServiceToken, ServiceClass } from '../service'\nimport type { ScopeOutcome } from '../scope'\n\ntype LayerCause = Extract<ScopeOutcome, { readonly status: 'failure' }>['cause']\n\n/** Thrown when a Layer registers the same Service tag more than once. */\nexport class DuplicateServiceError extends Error {\n constructor(readonly service: ServiceClass<any>) {\n super(`Duplicate service tag \"${service.serviceTag}\"`)\n\n this.name = 'DuplicateServiceError'\n }\n}\n\n/** Thrown when one Service tag is associated with incompatible constructors. */\nexport class ServiceTagCollisionError extends Error {\n constructor(\n readonly existing: AnyServiceToken,\n readonly incoming: AnyServiceToken\n ) {\n super(\n `Service tag \"${incoming.serviceTag}\" is already associated with \"${existing.name}\" ` +\n `and cannot be associated with \"${incoming.name}\"`\n )\n\n this.name = 'ServiceTagCollisionError'\n }\n}\n\n/** Thrown when a backend fails while registering a Layer provider. */\nexport class LayerRegistrationError extends Error {\n constructor(\n readonly service: ServiceClass<any> | undefined,\n readonly registrationCause: LayerCause,\n readonly cleanupCause?: LayerCause\n ) {\n super(\n service ? `Failed to register service \"${service.serviceTag}\"` : 'Failed to build Layer',\n {\n cause: registrationCause\n }\n )\n\n this.name = 'LayerRegistrationError'\n }\n}\n\n/** Thrown when one or more Layer-owned resources fail during disposal. */\nexport class LayerDisposeError extends Error {\n constructor(readonly causes: readonly unknown[]) {\n super(`Failed to dispose Layer (${causes.length} error${causes.length === 1 ? '' : 's'})`)\n\n this.name = 'LayerDisposeError'\n }\n}\n\n/** Thrown when a Layer generator yields a value other than a Service requirement. */\nexport class LayerGeneratorYieldError extends Error {\n constructor(readonly service: ServiceClass<any>) {\n super(`Layer.gen(\"${service.serviceTag}\") yielded an unsupported value`)\n\n this.name = 'LayerGeneratorYieldError'\n }\n}\n"],"mappings":";;AAGA,IAAa,mCAAb,cAAsD,MAAM;CAC1D,cAAc;EACZ,MAAM,gEAAgE;EAEtE,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,uBAAb,cAA0C,MAAM;CACzB;CAArB,YAAY,SAAmC;EAC7C,MAAM,YAAY,QAAQ,WAAW,mBAAmB;EADrC,KAAA,UAAA;EAGnB,KAAK,OAAO;CACd;AACF;;;;ACZA,IAAa,wBAAb,cAA2C,MAAM;CAC1B;CAArB,YAAY,SAAqC;EAC/C,MAAM,0BAA0B,QAAQ,WAAW,EAAE;EADlC,KAAA,UAAA;EAGnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,2BAAb,cAA8C,MAAM;CAEvC;CACA;CAFX,YACE,UACA,UACA;EACA,MACE,gBAAgB,SAAS,WAAW,gCAAgC,SAAS,KAAK,mCAC9C,SAAS,KAAK,EACpD;EANS,KAAA,WAAA;EACA,KAAA,WAAA;EAOT,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,yBAAb,cAA4C,MAAM;CAErC;CACA;CACA;CAHX,YACE,SACA,mBACA,cACA;EACA,MACE,UAAU,+BAA+B,QAAQ,WAAW,KAAK,yBACjE,EACE,OAAO,kBACT,CACF;EATS,KAAA,UAAA;EACA,KAAA,oBAAA;EACA,KAAA,eAAA;EAST,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,oBAAb,cAAuC,MAAM;CACtB;CAArB,YAAY,QAAqC;EAC/C,MAAM,4BAA4B,OAAO,OAAO,QAAQ,OAAO,WAAW,IAAI,KAAK,IAAI,EAAE;EADtE,KAAA,SAAA;EAGnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,2BAAb,cAA8C,MAAM;CAC7B;CAArB,YAAY,SAAqC;EAC/C,MAAM,cAAc,QAAQ,WAAW,gCAAgC;EADpD,KAAA,UAAA;EAGnB,KAAK,OAAO;CACd;AACF"}
|