@antelopejs/interface-dms-saas 0.4.1 → 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 +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/tenant-lifecycle.d.ts +27 -0
- package/dist/tenant-lifecycle.js +30 -0
- package/dist/tenant-lifecycle.js.map +1 -0
- package/docs/1.index.md +5 -5
- package/docs/3.lifecycle-and-usage.md +20 -18
- package/package.json +1 -1
- package/dist/workspace-lifecycle.d.ts +0 -27
- package/dist/workspace-lifecycle.js +0 -30
- package/dist/workspace-lifecycle.js.map +0 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ The AntelopeJS interface to extend the DMS SaaS module: billing, plans, registra
|
|
|
17
17
|
- Builds plan projections and catalogues, and normalizes prices.
|
|
18
18
|
- Extends registration and the provisioning of a new workspace.
|
|
19
19
|
- Adds workspace settings categories and blocks to the tenant billing page.
|
|
20
|
-
- Listens to
|
|
20
|
+
- Listens to tenant lifecycle events and operator actions, and exposes the canonical SaaS tables and models (`/db`).
|
|
21
21
|
|
|
22
22
|
A module that extends [`@antelopejs/dms-saas`](https://www.npmjs.com/package/@antelopejs/dms-saas) depends on this package, never on the runtime.
|
|
23
23
|
|
|
@@ -29,13 +29,13 @@ pnpm add @antelopejs/interface-dms-saas
|
|
|
29
29
|
|
|
30
30
|
## Quick start
|
|
31
31
|
|
|
32
|
-
The root entry holds every extension point except `db`, with `invoiceLineItems` and `
|
|
32
|
+
The root entry holds every extension point except `db`, with `invoiceLineItems` and `tenantLifecycle` as namespaces:
|
|
33
33
|
|
|
34
34
|
```ts docs-check
|
|
35
|
-
import { invoiceLineItems,
|
|
35
|
+
import { invoiceLineItems, tenantLifecycle } from "@antelopejs/interface-dms-saas";
|
|
36
36
|
|
|
37
37
|
export const usageKey = invoiceLineItems.buildInvoiceLineKey("example.compute", "minutes");
|
|
38
|
-
export const isProvisioningCommitted =
|
|
38
|
+
export const isProvisioningCommitted = tenantLifecycle.IsTenantProvisioningCommitted;
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Use the [entry-point reference](./docs/1.index.md#entry-points) for supported
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.tenantLifecycle = exports.invoiceLineItems = void 0;
|
|
40
40
|
__exportStar(require("./billing"), exports);
|
|
41
41
|
__exportStar(require("./data-api"), exports);
|
|
42
42
|
__exportStar(require("./pages"), exports);
|
|
@@ -44,5 +44,5 @@ __exportStar(require("./plans"), exports);
|
|
|
44
44
|
__exportStar(require("./provisioning"), exports);
|
|
45
45
|
__exportStar(require("./registration"), exports);
|
|
46
46
|
exports.invoiceLineItems = __importStar(require("./invoice-line-items"));
|
|
47
|
-
exports.
|
|
47
|
+
exports.tenantLifecycle = __importStar(require("./tenant-lifecycle"));
|
|
48
48
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,4CAA0B;AAC1B,6CAA2B;AAC3B,0CAAwB;AACxB,0CAAwB;AACxB,iDAA+B;AAC/B,iDAA+B;AAC/B,yEAAyD;AACzD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,4CAA0B;AAC1B,6CAA2B;AAC3B,0CAAwB;AACxB,0CAAwB;AACxB,iDAA+B;AAC/B,iDAA+B;AAC/B,yEAAyD;AACzD,sEAAsD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RegisteringProxy } from "@antelopejs/interface-core";
|
|
2
|
+
export declare const TENANT_LIFECYCLE_TRANSITIONS: readonly ["created", "suspended", "reactivation_requested"];
|
|
3
|
+
export type TenantLifecycleTransition = (typeof TENANT_LIFECYCLE_TRANSITIONS)[number];
|
|
4
|
+
export interface TenantLifecycleMessage {
|
|
5
|
+
tenantId: string;
|
|
6
|
+
operationId: string;
|
|
7
|
+
transition: TenantLifecycleTransition;
|
|
8
|
+
requestedAt: Date;
|
|
9
|
+
}
|
|
10
|
+
export interface TenantLifecycleReceipt {
|
|
11
|
+
receiptId: string;
|
|
12
|
+
effectiveAt?: Date;
|
|
13
|
+
}
|
|
14
|
+
export interface TenantLifecycleConsumer {
|
|
15
|
+
name: string;
|
|
16
|
+
transitions: readonly TenantLifecycleTransition[];
|
|
17
|
+
consume(message: TenantLifecycleMessage): Promise<TenantLifecycleReceipt>;
|
|
18
|
+
}
|
|
19
|
+
export interface TenantLifecycleConsumerRegistration {
|
|
20
|
+
unregister(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare const IsTenantProvisioningCommitted: (tenantId: string) => Promise<boolean>;
|
|
23
|
+
export declare namespace internal {
|
|
24
|
+
const RegisterTenantLifecycleConsumer: RegisteringProxy<(name: string, consumer: TenantLifecycleConsumer) => void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function UnregisterTenantLifecycleConsumer(name: string): void;
|
|
27
|
+
export declare function RegisterTenantLifecycleConsumer(consumer: TenantLifecycleConsumer): TenantLifecycleConsumerRegistration;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.internal = exports.IsTenantProvisioningCommitted = exports.TENANT_LIFECYCLE_TRANSITIONS = void 0;
|
|
4
|
+
exports.UnregisterTenantLifecycleConsumer = UnregisterTenantLifecycleConsumer;
|
|
5
|
+
exports.RegisterTenantLifecycleConsumer = RegisterTenantLifecycleConsumer;
|
|
6
|
+
const interface_core_1 = require("@antelopejs/interface-core");
|
|
7
|
+
const CONSUMER_NAME_PATTERN = /^[a-z][a-z0-9._-]{2,63}$/;
|
|
8
|
+
exports.TENANT_LIFECYCLE_TRANSITIONS = [
|
|
9
|
+
"created",
|
|
10
|
+
"suspended",
|
|
11
|
+
"reactivation_requested",
|
|
12
|
+
];
|
|
13
|
+
exports.IsTenantProvisioningCommitted = (0, interface_core_1.InterfaceFunction)();
|
|
14
|
+
var internal;
|
|
15
|
+
(function (internal) {
|
|
16
|
+
internal.RegisterTenantLifecycleConsumer = new interface_core_1.RegisteringProxy();
|
|
17
|
+
})(internal || (exports.internal = internal = {}));
|
|
18
|
+
function UnregisterTenantLifecycleConsumer(name) {
|
|
19
|
+
internal.RegisterTenantLifecycleConsumer.unregister(name);
|
|
20
|
+
}
|
|
21
|
+
function RegisterTenantLifecycleConsumer(consumer) {
|
|
22
|
+
if (!CONSUMER_NAME_PATTERN.test(consumer.name)) {
|
|
23
|
+
throw new Error("Invalid workspace lifecycle consumer name");
|
|
24
|
+
}
|
|
25
|
+
internal.RegisterTenantLifecycleConsumer.register(consumer.name, consumer);
|
|
26
|
+
return {
|
|
27
|
+
unregister: () => UnregisterTenantLifecycleConsumer(consumer.name),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=tenant-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-lifecycle.js","sourceRoot":"","sources":["../src/tenant-lifecycle.ts"],"names":[],"mappings":";;;AA+DA,8EAEC;AAWD,0EAUC;AAtFD,+DAGoC;AAEpC,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAG5C,QAAA,4BAA4B,GAAG;IAC1C,SAAS;IACT,WAAW;IACX,wBAAwB;CAChB,CAAC;AAwCE,QAAA,6BAA6B,GACxC,IAAA,kCAAiB,GAA0C,CAAC;AAG9D,IAAiB,QAAQ,CAIxB;AAJD,WAAiB,QAAQ;IACV,wCAA+B,GAAG,IAAI,iCAAgB,EAEhE,CAAC;AACN,CAAC,EAJgB,QAAQ,wBAAR,QAAQ,QAIxB;AAGD,SAAgB,iCAAiC,CAAC,IAAY;IAC5D,QAAQ,CAAC,+BAA+B,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAWD,SAAgB,+BAA+B,CAC7C,QAAiC;IAEjC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,QAAQ,CAAC,+BAA+B,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3E,OAAO;QACL,UAAU,EAAE,GAAG,EAAE,CAAC,iCAAiC,CAAC,QAAQ,CAAC,IAAI,CAAC;KACnE,CAAC;AACJ,CAAC"}
|
package/docs/1.index.md
CHANGED
|
@@ -11,26 +11,26 @@ Consumers depend on `@antelopejs/interface-dms-saas`, not the runtime's private
|
|
|
11
11
|
|
|
12
12
|
| Import after `@antelopejs/interface-dms-saas` | Contract |
|
|
13
13
|
| --- | --- |
|
|
14
|
-
| Root | Billing, data API, pages, plans, provisioning and registration exports; `invoiceLineItems` and `
|
|
14
|
+
| Root | Billing, data API, pages, plans, provisioning and registration exports; `invoiceLineItems` and `tenantLifecycle` namespaces |
|
|
15
15
|
| `/billing` | [Balances, previews and billing-state recomputation](./2.billing.md) |
|
|
16
16
|
| `/invoice-line-items` | [Usage providers, line types and key helpers](./3.lifecycle-and-usage.md#invoice-line-items) |
|
|
17
|
-
| `/
|
|
17
|
+
| `/tenant-lifecycle` | [Durable lifecycle consumers and provisioning gate](./3.lifecycle-and-usage.md#tenant-lifecycle) |
|
|
18
18
|
| `/provisioning`, `/registration` | [Provisioning payload and registration limits](./3.lifecycle-and-usage.md#registration-and-provisioning) |
|
|
19
19
|
| `/pages`, `/page-definitions` | [Page descriptors and extension registration](./4.pages-plans-data.md#page-extensions) |
|
|
20
20
|
| `/plans` | [Plan projections, localization and pricing helpers](./4.pages-plans-data.md#plan-helpers) |
|
|
21
21
|
| `/data-api`, `/hidden-filter` | [HiddenStringFilter](./4.pages-plans-data.md#hiddenstringfilter) |
|
|
22
22
|
| `/db`, `/db/models`, `/db/tables` | Canonical SaaS models and table classes; see the data boundary below |
|
|
23
23
|
|
|
24
|
-
`invoiceLineItems` and `
|
|
24
|
+
`invoiceLineItems` and `tenantLifecycle` are namespaces at the root, not flat exports. Use their direct subpaths for individual functions. Their `internal` proxy namespaces are implementation plumbing, not consumer APIs.
|
|
25
25
|
|
|
26
26
|
```ts docs-check
|
|
27
|
-
import { invoiceLineItems,
|
|
27
|
+
import { invoiceLineItems, tenantLifecycle } from "@antelopejs/interface-dms-saas";
|
|
28
28
|
|
|
29
29
|
export const usageKey = invoiceLineItems.buildInvoiceLineKey("example.compute", "minutes");
|
|
30
30
|
|
|
31
31
|
export async function mayProvision(tenantId: string): Promise<boolean> {
|
|
32
32
|
// Errors propagate: unavailable storage must not grant eligibility.
|
|
33
|
-
return
|
|
33
|
+
return tenantLifecycle.IsTenantProvisioningCommitted(tenantId);
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Lifecycle and usage
|
|
3
|
-
description: Registration extras, durable
|
|
3
|
+
description: Registration extras, durable tenant lifecycle consumers and idempotent invoice usage providers.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Lifecycle and usage
|
|
7
7
|
|
|
8
|
-
Use the direct subpaths below or the root's `invoiceLineItems` and `
|
|
8
|
+
Use the direct subpaths below or the root's `invoiceLineItems` and `tenantLifecycle` namespaces. Register consumers/providers from the owning module's lifecycle, not a request handler. Registrations replay when SaaS attaches or reloads and are released when their owner unloads.
|
|
9
9
|
|
|
10
10
|
## Invoice line items
|
|
11
11
|
|
|
@@ -49,42 +49,44 @@ Preview calls set `isPreview: true`, use a synthetic `upcoming_<subscription id>
|
|
|
49
49
|
|
|
50
50
|
`selectInvoiceLineItemsToCreate(providerId: string, items: readonly InvoiceLineItem[], alreadyInjectedKeys: ReadonlySet<string>): InvoiceLineItemSelection` is synchronous and has no Stripe side effects. It returns `accepted: PreparedInvoiceLineItem[]` (`{ lineKey, item }`, with trimmed item keys) and `skipped: SkippedInvoiceLineItem[]` (`{ lineKey, reason }`). `SkippedLineItemReason` is `already_invoiced`, `duplicate_key`, `zero_amount`, or `invalid`. The set must contain full provider-prefixed keys. This selection helper does not itself provide transactional idempotency.
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## Tenant lifecycle
|
|
53
53
|
|
|
54
|
-
Import from `/
|
|
54
|
+
Import from `/tenant-lifecycle`. `TENANT_LIFECYCLE_TRANSITIONS` contains `created`, `suspended` and `reactivation_requested`; `TenantLifecycleTransition` is their union.
|
|
55
|
+
|
|
56
|
+
**Breaking migration:** Update `@antelopejs/interface-dms-saas` and `@antelopejs/dms-saas` together. The old `RegisterWorkspaceLifecycleConsumer`, `UnregisterWorkspaceLifecycleConsumer`, `WorkspaceLifecycle*` types, `WORKSPACE_LIFECYCLE_TRANSITIONS`, `IsWorkspaceProvisioningCommitted`, `/workspace-lifecycle` subpath and root `workspaceLifecycle` namespace are removed, without compatibility aliases. Use the tenant-named API below and root `tenantLifecycle` namespace instead. Persisted consumer IDs, transition values and operation IDs remain unchanged; keep existing consumer names and deduplication keys.
|
|
55
57
|
|
|
56
58
|
```ts [Contract]
|
|
57
|
-
import type {
|
|
59
|
+
import type { TenantLifecycleTransition } from "@antelopejs/interface-dms-saas/tenant-lifecycle";
|
|
58
60
|
|
|
59
|
-
interface
|
|
61
|
+
interface TenantLifecycleMessage {
|
|
60
62
|
tenantId: string;
|
|
61
63
|
operationId: string;
|
|
62
|
-
transition:
|
|
64
|
+
transition: TenantLifecycleTransition;
|
|
63
65
|
requestedAt: Date;
|
|
64
66
|
}
|
|
65
|
-
interface
|
|
67
|
+
interface TenantLifecycleReceipt {
|
|
66
68
|
receiptId: string;
|
|
67
69
|
effectiveAt?: Date;
|
|
68
70
|
}
|
|
69
|
-
interface
|
|
71
|
+
interface TenantLifecycleConsumer {
|
|
70
72
|
name: string;
|
|
71
|
-
transitions: readonly
|
|
72
|
-
consume(message:
|
|
73
|
+
transitions: readonly TenantLifecycleTransition[];
|
|
74
|
+
consume(message: TenantLifecycleMessage): Promise<TenantLifecycleReceipt>;
|
|
73
75
|
}
|
|
74
|
-
interface
|
|
76
|
+
interface TenantLifecycleConsumerRegistration { unregister(): void; }
|
|
75
77
|
|
|
76
|
-
declare function
|
|
77
|
-
consumer:
|
|
78
|
-
):
|
|
79
|
-
declare function
|
|
80
|
-
declare function
|
|
78
|
+
declare function RegisterTenantLifecycleConsumer(
|
|
79
|
+
consumer: TenantLifecycleConsumer,
|
|
80
|
+
): TenantLifecycleConsumerRegistration;
|
|
81
|
+
declare function UnregisterTenantLifecycleConsumer(name: string): void;
|
|
82
|
+
declare function IsTenantProvisioningCommitted(tenantId: string): Promise<boolean>;
|
|
81
83
|
```
|
|
82
84
|
|
|
83
85
|
Names must match `/^[a-z][a-z0-9._-]{2,63}$/`; invalid names throw synchronously. Pick a stable unique name and explicitly select transitions. Unregister via the returned handle or by name when the module stops.
|
|
84
86
|
|
|
85
87
|
Delivery is **at least once**. Deduplicate by `operationId`, durably link provisioned resources, then return a durable receipt. A rejection is not an acknowledgement. Suspension closes SaaS access before delivery; reactivation keeps access closed until every registered required consumer returns a receipt. `created` arrives after ownership, billing and pre-provisioning hooks succeed and the first invoice is paid, or no payment is required.
|
|
86
88
|
|
|
87
|
-
`
|
|
89
|
+
`IsTenantProvisioningCommitted` returns false for preparing, unpaid or cancelled self-service workspaces; true for committed creations and legacy/bootstrap tenants without a marker. It is not an existence, membership or access check. Storage and missing-implementation errors propagate; fail closed instead of treating an unavailable check as eligibility.
|
|
88
90
|
|
|
89
91
|
## Registration and provisioning
|
|
90
92
|
|
package/package.json
CHANGED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { RegisteringProxy } from "@antelopejs/interface-core";
|
|
2
|
-
export declare const WORKSPACE_LIFECYCLE_TRANSITIONS: readonly ["created", "suspended", "reactivation_requested"];
|
|
3
|
-
export type WorkspaceLifecycleTransition = (typeof WORKSPACE_LIFECYCLE_TRANSITIONS)[number];
|
|
4
|
-
export interface WorkspaceLifecycleMessage {
|
|
5
|
-
tenantId: string;
|
|
6
|
-
operationId: string;
|
|
7
|
-
transition: WorkspaceLifecycleTransition;
|
|
8
|
-
requestedAt: Date;
|
|
9
|
-
}
|
|
10
|
-
export interface WorkspaceLifecycleReceipt {
|
|
11
|
-
receiptId: string;
|
|
12
|
-
effectiveAt?: Date;
|
|
13
|
-
}
|
|
14
|
-
export interface WorkspaceLifecycleConsumer {
|
|
15
|
-
name: string;
|
|
16
|
-
transitions: readonly WorkspaceLifecycleTransition[];
|
|
17
|
-
consume(message: WorkspaceLifecycleMessage): Promise<WorkspaceLifecycleReceipt>;
|
|
18
|
-
}
|
|
19
|
-
export interface WorkspaceLifecycleConsumerRegistration {
|
|
20
|
-
unregister(): void;
|
|
21
|
-
}
|
|
22
|
-
export declare const IsWorkspaceProvisioningCommitted: (tenantId: string) => Promise<boolean>;
|
|
23
|
-
export declare namespace internal {
|
|
24
|
-
const RegisterWorkspaceLifecycleConsumer: RegisteringProxy<(name: string, consumer: WorkspaceLifecycleConsumer) => void>;
|
|
25
|
-
}
|
|
26
|
-
export declare function UnregisterWorkspaceLifecycleConsumer(name: string): void;
|
|
27
|
-
export declare function RegisterWorkspaceLifecycleConsumer(consumer: WorkspaceLifecycleConsumer): WorkspaceLifecycleConsumerRegistration;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.internal = exports.IsWorkspaceProvisioningCommitted = exports.WORKSPACE_LIFECYCLE_TRANSITIONS = void 0;
|
|
4
|
-
exports.UnregisterWorkspaceLifecycleConsumer = UnregisterWorkspaceLifecycleConsumer;
|
|
5
|
-
exports.RegisterWorkspaceLifecycleConsumer = RegisterWorkspaceLifecycleConsumer;
|
|
6
|
-
const interface_core_1 = require("@antelopejs/interface-core");
|
|
7
|
-
const CONSUMER_NAME_PATTERN = /^[a-z][a-z0-9._-]{2,63}$/;
|
|
8
|
-
exports.WORKSPACE_LIFECYCLE_TRANSITIONS = [
|
|
9
|
-
"created",
|
|
10
|
-
"suspended",
|
|
11
|
-
"reactivation_requested",
|
|
12
|
-
];
|
|
13
|
-
exports.IsWorkspaceProvisioningCommitted = (0, interface_core_1.InterfaceFunction)();
|
|
14
|
-
var internal;
|
|
15
|
-
(function (internal) {
|
|
16
|
-
internal.RegisterWorkspaceLifecycleConsumer = new interface_core_1.RegisteringProxy();
|
|
17
|
-
})(internal || (exports.internal = internal = {}));
|
|
18
|
-
function UnregisterWorkspaceLifecycleConsumer(name) {
|
|
19
|
-
internal.RegisterWorkspaceLifecycleConsumer.unregister(name);
|
|
20
|
-
}
|
|
21
|
-
function RegisterWorkspaceLifecycleConsumer(consumer) {
|
|
22
|
-
if (!CONSUMER_NAME_PATTERN.test(consumer.name)) {
|
|
23
|
-
throw new Error("Invalid workspace lifecycle consumer name");
|
|
24
|
-
}
|
|
25
|
-
internal.RegisterWorkspaceLifecycleConsumer.register(consumer.name, consumer);
|
|
26
|
-
return {
|
|
27
|
-
unregister: () => UnregisterWorkspaceLifecycleConsumer(consumer.name),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=workspace-lifecycle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-lifecycle.js","sourceRoot":"","sources":["../src/workspace-lifecycle.ts"],"names":[],"mappings":";;;AAiEA,oFAEC;AAWD,gFAUC;AAxFD,+DAGoC;AAEpC,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAG5C,QAAA,+BAA+B,GAAG;IAC7C,SAAS;IACT,WAAW;IACX,wBAAwB;CAChB,CAAC;AA0CE,QAAA,gCAAgC,GAC3C,IAAA,kCAAiB,GAA0C,CAAC;AAG9D,IAAiB,QAAQ,CAIxB;AAJD,WAAiB,QAAQ;IACV,2CAAkC,GAAG,IAAI,iCAAgB,EAEnE,CAAC;AACN,CAAC,EAJgB,QAAQ,wBAAR,QAAQ,QAIxB;AAGD,SAAgB,oCAAoC,CAAC,IAAY;IAC/D,QAAQ,CAAC,kCAAkC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC;AAWD,SAAgB,kCAAkC,CAChD,QAAoC;IAEpC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,QAAQ,CAAC,kCAAkC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9E,OAAO;QACL,UAAU,EAAE,GAAG,EAAE,CAAC,oCAAoC,CAAC,QAAQ,CAAC,IAAI,CAAC;KACtE,CAAC;AACJ,CAAC"}
|