better-effect 0.5.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 +60 -6
- package/dist/adapters/iti.d.mts +1 -1
- package/dist/adapters/iti.d.mts.map +1 -1
- package/dist/adapters/iti.mjs +4 -3
- package/dist/adapters/iti.mjs.map +1 -1
- package/dist/errors-GR3K_nRu.mjs.map +1 -1
- package/dist/index-DMfjhNR_.d.mts +500 -0
- package/dist/index-DMfjhNR_.d.mts.map +1 -0
- package/dist/index.d.mts +57 -61
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +87 -112
- package/dist/index.mjs.map +1 -1
- package/dist/{internal-identity-BnZC3Au-.mjs → internal-identity-C6Awrc33.mjs} +4 -3
- 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 +1 -1
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +3 -2
- package/dist/testing.mjs.map +1 -1
- package/package.json +13 -5
- package/dist/index-D77AvuBl.d.mts +0 -510
- package/dist/index-D77AvuBl.d.mts.map +0 -1
- package/dist/internal-identity-BnZC3Au-.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -44,9 +44,17 @@ literal is the Service's stable logical identity. Services with identical
|
|
|
44
44
|
methods but different tags are different dependencies; use a namespaced tag
|
|
45
45
|
such as `@acme/Database` when identities must be shared across packages.
|
|
46
46
|
|
|
47
|
-
`UserRepository` used `Database`, so `Database` became part of its environment requirements
|
|
47
|
+
`UserRepository` used `Database`, so `Database` became part of its environment requirements:
|
|
48
48
|
|
|
49
|
-
|
|
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.
|
|
50
58
|
|
|
51
59
|
Services can also describe a contract without requiring a class instance. Use the
|
|
52
60
|
static `of` helper to type-check a structural implementation; it returns the same
|
|
@@ -68,6 +76,15 @@ const AuthorizationLive = Layer.succeed(Authorization, authorization)
|
|
|
68
76
|
`instanceof Authorization`. For services with constructors, private fields or
|
|
69
77
|
other runtime invariants, use `new Authorization(...)` instead.
|
|
70
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.
|
|
87
|
+
|
|
71
88
|
Provide it and the environment becomes complete:
|
|
72
89
|
|
|
73
90
|
```ts
|
|
@@ -114,6 +131,40 @@ We call this **typechecked wiring**.
|
|
|
114
131
|
|
|
115
132
|
The Services your code uses, the implementations your Layers provide, and the programs your Runtime executes participate in the same type-level contract.
|
|
116
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
|
+
|
|
117
168
|
---
|
|
118
169
|
|
|
119
170
|
## Why better-effect?
|
|
@@ -193,9 +244,11 @@ Resources acquired during an individual execution belong to that execution inste
|
|
|
193
244
|
|
|
194
245
|
`better-effect` is not a replacement implementation of Effect.
|
|
195
246
|
|
|
196
|
-
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.
|
|
197
248
|
|
|
198
|
-
|
|
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.
|
|
199
252
|
|
|
200
253
|
Dependency resolution stays behind a pluggable backend.
|
|
201
254
|
|
|
@@ -270,8 +323,9 @@ Application resources live with the Runtime. Execution resources live with the e
|
|
|
270
323
|
Keep `better-result` as the source of truth for typed successes, failures, short-circuiting
|
|
271
324
|
and generator control flow. `Effect.gen` delegates to `Result.gen`; it adds only the
|
|
272
325
|
phantom Service requirements that TypeScript needs to check the application environment.
|
|
273
|
-
At runtime, an `
|
|
274
|
-
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.
|
|
275
329
|
|
|
276
330
|
For a linear workflow, `pipe` composes the same kind of program without introducing a
|
|
277
331
|
second Result model or a lazy Effect runtime:
|
package/dist/adapters/iti.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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
3
|
/**
|
|
4
4
|
* ITI-backed Layer backend.
|
|
@@ -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,5 +1,6 @@
|
|
|
1
1
|
import { a as ServiceTagCollisionError, o as ServiceNotFoundError, t as DuplicateServiceError } from "../errors-GR3K_nRu.mjs";
|
|
2
|
-
import { t as
|
|
2
|
+
import { t as isPromiseLike } from "../runtime-CDcCF5cb.mjs";
|
|
3
|
+
import { t as assertServiceCompatibility } from "../internal-identity-C6Awrc33.mjs";
|
|
3
4
|
import { createContainer } from "iti";
|
|
4
5
|
//#region src/adapters/iti.ts
|
|
5
6
|
/**
|
|
@@ -33,15 +34,15 @@ var ItiLayerBackend = class {
|
|
|
33
34
|
}
|
|
34
35
|
/** Resolve a registered Service through the ITI container. */
|
|
35
36
|
resolve(token) {
|
|
36
|
-
if (!this.registered.has(token.serviceTag)) throw new ServiceNotFoundError(token);
|
|
37
37
|
const registered = this.registered.get(token.serviceTag);
|
|
38
|
+
if (registered === void 0) throw new ServiceNotFoundError(token);
|
|
38
39
|
const key = this.keyFor(token);
|
|
39
40
|
const resolved = this.container.get(key);
|
|
40
41
|
const validate = (instance) => {
|
|
41
42
|
assertServiceCompatibility(token, registered, instance);
|
|
42
43
|
return instance;
|
|
43
44
|
};
|
|
44
|
-
if (resolved
|
|
45
|
+
if (isPromiseLike(resolved)) return Promise.resolve(resolved).then(validate);
|
|
45
46
|
return validate(resolved);
|
|
46
47
|
}
|
|
47
48
|
/** Dispose all ITI-managed provider instances. */
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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"}
|
|
@@ -1 +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:
|
|
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"}
|