better-effect 0.4.0 → 0.5.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 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,46 @@ class UserRepository extends Service<UserRepository>() {
32
32
  }
33
33
  }
34
34
 
35
- const UserRepositoryLive = Layer.make(UserRepository, () => new 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
+ 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.
46
+
42
47
  `UserRepository` used `Database`, so `Database` became part of its environment requirements.
43
48
 
44
49
  No dependency list was written manually.
45
50
 
51
+ Services can also describe a contract without requiring a class instance. Use the
52
+ static `of` helper to type-check a structural implementation; it returns the same
53
+ object unchanged at runtime:
54
+
55
+ ```ts
56
+ class Authorization extends Service<Authorization>()('Authorization') {
57
+ declare readonly authorize: (token: string) => Promise<boolean>
58
+ }
59
+
60
+ const authorization = Authorization.of({
61
+ authorize: async (token) => token.length > 0
62
+ })
63
+
64
+ const AuthorizationLive = Layer.succeed(Authorization, authorization)
65
+ ```
66
+
67
+ `Authorization.of(...)` does not call a constructor or make the result an
68
+ `instanceof Authorization`. For services with constructors, private fields or
69
+ other runtime invariants, use `new Authorization(...)` instead.
70
+
46
71
  Provide it and the environment becomes complete:
47
72
 
48
73
  ```ts
49
- const DatabaseLive = Layer.make(Database, () => new Database())
74
+ const DatabaseLive = Layer.make(Database)
50
75
 
51
76
  const AppLive = Layer.merge(DatabaseLive, UserRepositoryLive)
52
77
 
@@ -264,7 +289,9 @@ const program = pipe(
264
289
 
265
290
  The combinators keep the `better-result` semantics: `Effect.map` changes the success
266
291
  type, `Effect.mapError` changes the error type, and `Effect.andThen` only calls the next
267
- step after an `Ok`. The pipeline carries the requirements of every step, so Runtime
292
+ step after an `Ok`. Use `Effect.andThenAsync` when the next operation returns a
293
+ `Promise<Result>`; it always returns a Promise, including when the source is synchronous
294
+ or already an `Err`. The pipeline carries the requirements of every step, so Runtime
268
295
  still rejects it when its Layer does not provide every required Service.
269
296
 
270
297
  Use `Effect.gen` for larger workflows with several intermediate values, branches or
@@ -1,13 +1,21 @@
1
- import { V as AnyServiceToken, t as LayerBackend, v as LayerProvider } from "../index-BYQKfyeJ.mjs";
1
+ import { V as AnyServiceToken, t as LayerBackend, v as LayerRegistration } from "../index-D77AvuBl.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
- register(provider: LayerProvider): void;
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":";;cAMa,2BAA2B;UAC9B;mBAES;mBAEA;UAET;UAEA;EAgBR,SAAS,UAAU;EAgBnB,QAAQ,UAAU,iBAAiB,OAAO,IAAI,aAAa,KAAK,YAAY,aAAa;EAUnF,cAAc"}
1
+ {"version":3,"file":"iti.d.mts","names":[],"sources":["../../src/adapters/iti.ts"],"mappings":";;;;;;;;cAmBa,2BAA2B;UAC9B;mBAES;mBAEA;UAET;;EAgBR,SAAS,cAAc;;EAuBvB,QAAQ,UAAU,iBAAiB,OAAO,IAAI,aAAa,KAAK,YAAY,aAAa;;EAuBnF,cAAc"}
@@ -1,30 +1,50 @@
1
- import { n as DuplicateServiceError, o as ServiceNotFoundError } from "../errors-DlHCwICc.mjs";
1
+ import { a as ServiceTagCollisionError, o as ServiceNotFoundError, t as DuplicateServiceError } from "../errors-GR3K_nRu.mjs";
2
+ import { t as assertServiceCompatibility } from "../internal-identity-BnZC3Au-.mjs";
2
3
  import { createContainer } from "iti";
3
4
  //#region src/adapters/iti.ts
5
+ /**
6
+ * ITI-backed Layer backend.
7
+ *
8
+ * Install `iti` as the optional peer dependency and pass an instance to
9
+ * `Runtime.make` when using ITI's container implementation.
10
+ */
4
11
  var ItiLayerBackend = class {
5
12
  container = createContainer();
6
- keys = /* @__PURE__ */ new WeakMap();
7
- registered = /* @__PURE__ */ new WeakSet();
8
- nextId = 0;
13
+ keys = /* @__PURE__ */ new Map();
14
+ registered = /* @__PURE__ */ new Map();
9
15
  keyFor(token) {
10
- const existing = this.keys.get(token);
16
+ const tag = token.serviceTag;
17
+ const existing = this.keys.get(tag);
11
18
  if (existing) return existing;
12
- const key = `better-effect:${token.name || "Service"}:${this.nextId++}`;
13
- this.keys.set(token, key);
19
+ const key = `better-effect:${tag}`;
20
+ this.keys.set(tag, key);
14
21
  return key;
15
22
  }
16
- register(provider) {
17
- const token = provider.service;
18
- if (this.registered.has(token)) throw new DuplicateServiceError(token);
23
+ /** Register a Layer provider under its deterministic Service-tag key. */
24
+ register(registration) {
25
+ const token = registration.service;
26
+ const tag = token.serviceTag;
27
+ const existing = this.registered.get(tag);
28
+ if (existing === token) throw new DuplicateServiceError(token);
29
+ if (existing) throw new ServiceTagCollisionError(existing, token);
19
30
  const key = this.keyFor(token);
20
- this.container = this.container.add({ [key]: provider.acquire });
21
- this.registered.add(token);
31
+ this.container = this.container.add({ [key]: registration.acquire });
32
+ this.registered.set(tag, token);
22
33
  }
34
+ /** Resolve a registered Service through the ITI container. */
23
35
  resolve(token) {
24
- if (!this.registered.has(token)) throw new ServiceNotFoundError(token);
36
+ if (!this.registered.has(token.serviceTag)) throw new ServiceNotFoundError(token);
37
+ const registered = this.registered.get(token.serviceTag);
25
38
  const key = this.keyFor(token);
26
- return this.container.get(key);
39
+ const resolved = this.container.get(key);
40
+ const validate = (instance) => {
41
+ assertServiceCompatibility(token, registered, instance);
42
+ return instance;
43
+ };
44
+ if (resolved && typeof resolved.then === "function") return Promise.resolve(resolved).then(validate);
45
+ return validate(resolved);
27
46
  }
47
+ /** Dispose all ITI-managed provider instances. */
28
48
  async disposeAll() {
29
49
  await this.container.disposeAll();
30
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"iti.mjs","names":[],"sources":["../../src/adapters/iti.ts"],"sourcesContent":["import { createContainer } from 'iti'\n\nimport { DuplicateServiceError, type LayerBackend, type LayerProvider } from '../layer'\n\nimport { ServiceNotFoundError, type AnyServiceToken } from '../service'\n\nexport class ItiLayerBackend implements LayerBackend {\n private container: any = createContainer()\n\n private readonly keys = new WeakMap<AnyServiceToken, string>()\n\n private readonly registered = new WeakSet<AnyServiceToken>()\n\n private nextId = 0\n\n private keyFor(token: AnyServiceToken): string {\n const existing = this.keys.get(token)\n\n if (existing) {\n return existing\n }\n\n const name = token.name || 'Service'\n\n const key = `better-effect:${name}:${this.nextId++}`\n\n this.keys.set(token, key)\n\n return key\n }\n\n register(provider: LayerProvider): void {\n const token = provider.service\n\n if (this.registered.has(token)) {\n throw new DuplicateServiceError(token)\n }\n\n const key = this.keyFor(token)\n\n this.container = this.container.add({\n [key]: provider.acquire\n })\n\n this.registered.add(token)\n }\n\n resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>> {\n if (!this.registered.has(token)) {\n throw new ServiceNotFoundError(token)\n }\n\n const key = this.keyFor(token)\n\n return this.container.get(key) as InstanceType<T> | PromiseLike<InstanceType<T>>\n }\n\n async disposeAll(): Promise<void> {\n await this.container.disposeAll()\n }\n}\n"],"mappings":";;;AAMA,IAAa,kBAAb,MAAqD;CACnD,YAAyB,gBAAgB;CAEzC,uBAAwB,IAAI,QAAiC;CAE7D,6BAA8B,IAAI,QAAyB;CAE3D,SAAiB;CAEjB,OAAe,OAAgC;EAC7C,MAAM,WAAW,KAAK,KAAK,IAAI,KAAK;EAEpC,IAAI,UACF,OAAO;EAKT,MAAM,MAAM,iBAFC,MAAM,QAAQ,UAEO,GAAG,KAAK;EAE1C,KAAK,KAAK,IAAI,OAAO,GAAG;EAExB,OAAO;CACT;CAEA,SAAS,UAA+B;EACtC,MAAM,QAAQ,SAAS;EAEvB,IAAI,KAAK,WAAW,IAAI,KAAK,GAC3B,MAAM,IAAI,sBAAsB,KAAK;EAGvC,MAAM,MAAM,KAAK,OAAO,KAAK;EAE7B,KAAK,YAAY,KAAK,UAAU,IAAI,GACjC,MAAM,SAAS,QAClB,CAAC;EAED,KAAK,WAAW,IAAI,KAAK;CAC3B;CAEA,QAAmC,OAA0D;EAC3F,IAAI,CAAC,KAAK,WAAW,IAAI,KAAK,GAC5B,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,MAAM,KAAK,OAAO,KAAK;EAE7B,OAAO,KAAK,UAAU,IAAI,GAAG;CAC/B;CAEA,MAAM,aAA4B;EAChC,MAAM,KAAK,UAAU,WAAW;CAClC;AACF"}
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'\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 if (!this.registered.has(token.serviceTag)) {\n throw new ServiceNotFoundError(token)\n }\n\n const registered = this.registered.get(token.serviceTag)\n const key = this.keyFor(token)\n const resolved = this.container.get(key) as unknown\n\n const validate = (instance: unknown): InstanceType<T> => {\n assertServiceCompatibility(token, registered!, instance)\n\n return instance as InstanceType<T>\n }\n\n if (resolved && typeof (resolved as PromiseLike<unknown>).then === 'function') {\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":";;;;;;;;;;AAmBA,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,IAAI,CAAC,KAAK,WAAW,IAAI,MAAM,UAAU,GACvC,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,aAAa,KAAK,WAAW,IAAI,MAAM,UAAU;EACvD,MAAM,MAAM,KAAK,OAAO,KAAK;EAC7B,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,MAAM,YAAY,aAAuC;GACvD,2BAA2B,OAAO,YAAa,QAAQ;GAEvD,OAAO;EACT;EAEA,IAAI,YAAY,OAAQ,SAAkC,SAAS,YACjE,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'\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: unknown,\n readonly cleanupCause?: unknown\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;;;;ACfA,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"}