@antelopejs/interface-subscriptions 0.0.0-stage → 0.0.1

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.
@@ -0,0 +1,101 @@
1
+ import { RegisteringProxy } from "@antelopejs/interface-core";
2
+ import type { Subscription, SubscriptionEventHandler, SubscriptionRequest } from "./types";
3
+ /**
4
+ * Starts billing a saved payment method every period.
5
+ *
6
+ * Without a trial or a future billing anchor, the first period is charged
7
+ * before this resolves. A declined first charge creates nothing and rejects
8
+ * with {@link SubscriptionPaymentError}. A first charge that is still settling
9
+ * — a bank debit, say — creates the subscription as `active`; if it then
10
+ * fails, the subscription goes `past_due` like any other failed period.
11
+ *
12
+ * Every charge is an off-session payment-interface payment against
13
+ * `paymentMethod`, carrying {@link SUBSCRIPTION_METADATA_KEY} in its metadata.
14
+ *
15
+ * Implementations must document their replay window and resolve retained
16
+ * replays before checking whether the original trial or billing date has passed.
17
+ *
18
+ * @param request - Who, what, how often, and when to start
19
+ * @param idempotencyKey - Caller-generated key; within the provider-defined
20
+ * replay window, returns the saved outcome (including rejections where
21
+ * retained). After expiration, applications must reconcile uncertain payments
22
+ * and subscription creation before retrying; the same key may charge again.
23
+ * @param provider - Optional payment account selector, passed through to the
24
+ * payment interface. Later calls on the subscription must name the same one.
25
+ * @returns The subscription
26
+ * @throws InvalidSubscriptionRequestError if the request is outside the
27
+ * contract
28
+ * @throws SubscriptionPaymentError if the first period was charged and declined
29
+ */
30
+ export declare const CreateSubscription: (request: SubscriptionRequest, idempotencyKey: string, provider?: string | undefined) => Promise<Subscription>;
31
+ /**
32
+ * Reads a subscription's current state.
33
+ *
34
+ * @param id - Opaque subscription identifier
35
+ * @param provider - Optional payment account selector
36
+ * @returns The subscription
37
+ * @throws SubscriptionNotFoundError if no subscription has that identifier
38
+ */
39
+ export declare const GetSubscription: (id: string, provider?: string | undefined) => Promise<Subscription>;
40
+ /**
41
+ * Lists a customer's subscriptions, ended ones included.
42
+ *
43
+ * @param customer - Opaque payment-interface customer identifier
44
+ * @param provider - Optional payment account selector
45
+ * @returns The subscriptions, newest first. Empty when there are none.
46
+ */
47
+ export declare const ListSubscriptions: (customer: string, provider?: string | undefined) => Promise<Subscription[]>;
48
+ /**
49
+ * Cancels a subscription, now or when the period paid for runs out.
50
+ *
51
+ * Asking for `period_end` on a subscription already set to end then is not an
52
+ * error. Asking for `now` on one set to end at period end ends it now.
53
+ *
54
+ * @param id - Opaque subscription identifier
55
+ * @param idempotencyKey - Caller-generated key; replaying it within the
56
+ * provider-defined replay window returns the saved subscription
57
+ * @param timing - `now`, or `period_end`; see {@link CancellationTiming}
58
+ * @param provider - Optional payment account selector
59
+ * @returns The subscription after the change
60
+ * @throws SubscriptionNotFoundError if no subscription has that identifier
61
+ * @throws InvalidSubscriptionStateError if the subscription has already ended
62
+ */
63
+ export declare const CancelSubscription: (id: string, idempotencyKey: string, timing: "now" | "period_end", provider?: string | undefined) => Promise<Subscription>;
64
+ /**
65
+ * Charges a different saved method from the next attempt onwards.
66
+ *
67
+ * This is how a `past_due` subscription recovers when the old method will not:
68
+ * save a new one on-session, then switch to it. Nothing is charged by this
69
+ * call; the next scheduled attempt uses the new method.
70
+ *
71
+ * @param id - Opaque subscription identifier
72
+ * @param paymentMethod - Opaque payment-interface identifier of a method saved
73
+ * against the subscription's customer
74
+ * @param idempotencyKey - Caller-generated key; replay is safe within the
75
+ * provider-defined replay window
76
+ * @param provider - Optional payment account selector
77
+ * @returns The subscription after the change
78
+ * @throws SubscriptionNotFoundError if no subscription has that identifier
79
+ * @throws InvalidSubscriptionStateError if the subscription has ended
80
+ */
81
+ export declare const UpdateSubscriptionPaymentMethod: (id: string, paymentMethod: string, idempotencyKey: string, provider?: string | undefined) => Promise<Subscription>;
82
+ /**
83
+ * Where subscription events are delivered.
84
+ *
85
+ * Register a handler under an identifier unique within your module:
86
+ *
87
+ * ```ts
88
+ * SubscriptionEvents.register("billing", async (event) => { ... });
89
+ * ```
90
+ *
91
+ * Handlers are unregistered when the registering module unloads. Delivery is at
92
+ * least once: an event is delivered again if a handler throws, and may be
93
+ * delivered again after a crash. De-duplicate on
94
+ * {@link SubscriptionEvent.id}. In a cluster, each event is delivered by one
95
+ * instance, to the handlers registered in that instance.
96
+ *
97
+ * How an implementation learns of an event is its own business: the generic
98
+ * fallback raises them from its own clock, and a native provider from the
99
+ * provider's webhooks.
100
+ */
101
+ export declare const SubscriptionEvents: RegisteringProxy<(id: string, handler: SubscriptionEventHandler) => void>;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubscriptionEvents = exports.UpdateSubscriptionPaymentMethod = exports.CancelSubscription = exports.ListSubscriptions = exports.GetSubscription = exports.CreateSubscription = void 0;
4
+ const interface_core_1 = require("@antelopejs/interface-core");
5
+ /**
6
+ * Starts billing a saved payment method every period.
7
+ *
8
+ * Without a trial or a future billing anchor, the first period is charged
9
+ * before this resolves. A declined first charge creates nothing and rejects
10
+ * with {@link SubscriptionPaymentError}. A first charge that is still settling
11
+ * — a bank debit, say — creates the subscription as `active`; if it then
12
+ * fails, the subscription goes `past_due` like any other failed period.
13
+ *
14
+ * Every charge is an off-session payment-interface payment against
15
+ * `paymentMethod`, carrying {@link SUBSCRIPTION_METADATA_KEY} in its metadata.
16
+ *
17
+ * Implementations must document their replay window and resolve retained
18
+ * replays before checking whether the original trial or billing date has passed.
19
+ *
20
+ * @param request - Who, what, how often, and when to start
21
+ * @param idempotencyKey - Caller-generated key; within the provider-defined
22
+ * replay window, returns the saved outcome (including rejections where
23
+ * retained). After expiration, applications must reconcile uncertain payments
24
+ * and subscription creation before retrying; the same key may charge again.
25
+ * @param provider - Optional payment account selector, passed through to the
26
+ * payment interface. Later calls on the subscription must name the same one.
27
+ * @returns The subscription
28
+ * @throws InvalidSubscriptionRequestError if the request is outside the
29
+ * contract
30
+ * @throws SubscriptionPaymentError if the first period was charged and declined
31
+ */
32
+ exports.CreateSubscription = (0, interface_core_1.InterfaceFunction)();
33
+ /**
34
+ * Reads a subscription's current state.
35
+ *
36
+ * @param id - Opaque subscription identifier
37
+ * @param provider - Optional payment account selector
38
+ * @returns The subscription
39
+ * @throws SubscriptionNotFoundError if no subscription has that identifier
40
+ */
41
+ exports.GetSubscription = (0, interface_core_1.InterfaceFunction)();
42
+ /**
43
+ * Lists a customer's subscriptions, ended ones included.
44
+ *
45
+ * @param customer - Opaque payment-interface customer identifier
46
+ * @param provider - Optional payment account selector
47
+ * @returns The subscriptions, newest first. Empty when there are none.
48
+ */
49
+ exports.ListSubscriptions = (0, interface_core_1.InterfaceFunction)();
50
+ /**
51
+ * Cancels a subscription, now or when the period paid for runs out.
52
+ *
53
+ * Asking for `period_end` on a subscription already set to end then is not an
54
+ * error. Asking for `now` on one set to end at period end ends it now.
55
+ *
56
+ * @param id - Opaque subscription identifier
57
+ * @param idempotencyKey - Caller-generated key; replaying it within the
58
+ * provider-defined replay window returns the saved subscription
59
+ * @param timing - `now`, or `period_end`; see {@link CancellationTiming}
60
+ * @param provider - Optional payment account selector
61
+ * @returns The subscription after the change
62
+ * @throws SubscriptionNotFoundError if no subscription has that identifier
63
+ * @throws InvalidSubscriptionStateError if the subscription has already ended
64
+ */
65
+ exports.CancelSubscription = (0, interface_core_1.InterfaceFunction)();
66
+ /**
67
+ * Charges a different saved method from the next attempt onwards.
68
+ *
69
+ * This is how a `past_due` subscription recovers when the old method will not:
70
+ * save a new one on-session, then switch to it. Nothing is charged by this
71
+ * call; the next scheduled attempt uses the new method.
72
+ *
73
+ * @param id - Opaque subscription identifier
74
+ * @param paymentMethod - Opaque payment-interface identifier of a method saved
75
+ * against the subscription's customer
76
+ * @param idempotencyKey - Caller-generated key; replay is safe within the
77
+ * provider-defined replay window
78
+ * @param provider - Optional payment account selector
79
+ * @returns The subscription after the change
80
+ * @throws SubscriptionNotFoundError if no subscription has that identifier
81
+ * @throws InvalidSubscriptionStateError if the subscription has ended
82
+ */
83
+ exports.UpdateSubscriptionPaymentMethod = (0, interface_core_1.InterfaceFunction)();
84
+ /**
85
+ * Where subscription events are delivered.
86
+ *
87
+ * Register a handler under an identifier unique within your module:
88
+ *
89
+ * ```ts
90
+ * SubscriptionEvents.register("billing", async (event) => { ... });
91
+ * ```
92
+ *
93
+ * Handlers are unregistered when the registering module unloads. Delivery is at
94
+ * least once: an event is delivered again if a handler throws, and may be
95
+ * delivered again after a crash. De-duplicate on
96
+ * {@link SubscriptionEvent.id}. In a cluster, each event is delivered by one
97
+ * instance, to the handlers registered in that instance.
98
+ *
99
+ * How an implementation learns of an event is its own business: the generic
100
+ * fallback raises them from its own clock, and a native provider from the
101
+ * provider's webhooks.
102
+ */
103
+ exports.SubscriptionEvents = new interface_core_1.RegisteringProxy();
104
+ //# sourceMappingURL=functions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.js","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":";;;AAAA,+DAGoC;AASpC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACU,QAAA,kBAAkB,GAC7B,IAAA,kCAAiB,GAMd,CAAC;AAEN;;;;;;;GAOG;AACU,QAAA,eAAe,GAC1B,IAAA,kCAAiB,GAA4D,CAAC;AAEhF;;;;;;GAMG;AACU,QAAA,iBAAiB,GAC5B,IAAA,kCAAiB,GAEd,CAAC;AAEN;;;;;;;;;;;;;;GAcG;AACU,QAAA,kBAAkB,GAC7B,IAAA,kCAAiB,GAOd,CAAC;AAEN;;;;;;;;;;;;;;;;GAgBG;AACU,QAAA,+BAA+B,GAC1C,IAAA,kCAAiB,GAOd,CAAC;AAEN;;;;;;;;;;;;;;;;;;GAkBG;AACU,QAAA,kBAAkB,GAAG,IAAI,iCAAgB,EAEnD,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./errors";
2
+ export * from "./functions";
3
+ export * from "./types";
4
+ export * from "./validation";
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./errors"), exports);
18
+ __exportStar(require("./functions"), exports);
19
+ __exportStar(require("./types"), exports);
20
+ __exportStar(require("./validation"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,8CAA4B;AAC5B,0CAAwB;AACxB,+CAA6B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const promises_1 = require("node:timers/promises");
8
+ const support_1 = require("./support");
9
+ const index_1 = require("../index");
10
+ const EVENT_TIMEOUT = 20_000;
11
+ const ABSENT_CUSTOMER = `cus_antelope_absent_${"0".repeat(16)}`;
12
+ const ABSENT_METHOD = `pm_antelope_absent_${"0".repeat(16)}`;
13
+ const EVENT_POLL = 100;
14
+ describe(`cancelling (${support_1.CHARGEABLE})`, function () {
15
+ this.timeout(support_1.SUITE_TIMEOUT);
16
+ before(function () {
17
+ if (!support_1.TEST_METHOD)
18
+ this.skip();
19
+ });
20
+ it("ends a subscription now", async () => {
21
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
22
+ const canceled = await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "now");
23
+ strict_1.default.equal(canceled.status, "canceled");
24
+ strict_1.default.equal(canceled.endReason, "requested");
25
+ strict_1.default.ok(canceled.endedAt >= subscription.createdAt);
26
+ strict_1.default.equal((await (0, index_1.GetSubscription)(subscription.id)).status, "canceled");
27
+ });
28
+ it("lets a period run out instead of renewing it", async () => {
29
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
30
+ const scheduled = await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "period_end");
31
+ strict_1.default.equal(scheduled.status, "active", "the paid period keeps running");
32
+ strict_1.default.equal(scheduled.cancelAtPeriodEnd, true);
33
+ strict_1.default.equal(scheduled.endedAt, undefined);
34
+ strict_1.default.equal(scheduled.currentPeriodEnd, subscription.currentPeriodEnd);
35
+ strict_1.default.equal((await (0, index_1.GetSubscription)(subscription.id)).cancelAtPeriodEnd, true);
36
+ });
37
+ it("accepts a second request to end at period end", async () => {
38
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
39
+ await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "period_end");
40
+ const again = await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "period_end");
41
+ strict_1.default.equal(again.cancelAtPeriodEnd, true);
42
+ strict_1.default.equal(again.status, "active");
43
+ });
44
+ it("ends now a subscription already set to end at period end", async () => {
45
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
46
+ await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "period_end");
47
+ const canceled = await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "now");
48
+ strict_1.default.equal(canceled.status, "canceled");
49
+ });
50
+ it("ends a trial now without charging", async () => {
51
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)(), {
52
+ trialEnd: (0, support_1.inWholeSeconds)(support_1.TRIAL_DAYS * support_1.DAY_MS),
53
+ });
54
+ const canceled = await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "now");
55
+ strict_1.default.equal(canceled.status, "canceled");
56
+ strict_1.default.equal(canceled.latestPayment, undefined);
57
+ });
58
+ it("refuses to cancel what has already ended", async () => {
59
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
60
+ await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "now");
61
+ for (const timing of ["now", "period_end"]) {
62
+ const error = await (0, support_1.rejectsWith)((0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), timing), index_1.InvalidSubscriptionStateError, `cancel ${timing} after the end`);
63
+ strict_1.default.equal(error.status, "canceled");
64
+ }
65
+ });
66
+ it("replays a cancellation for a repeated idempotency key", async () => {
67
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
68
+ const idempotencyKey = (0, support_1.key)();
69
+ const first = await (0, index_1.CancelSubscription)(subscription.id, idempotencyKey, "now");
70
+ const replay = await (0, index_1.CancelSubscription)(subscription.id, idempotencyKey, "now");
71
+ strict_1.default.equal(replay.status, "canceled");
72
+ strict_1.default.equal(replay.endedAt, first.endedAt);
73
+ });
74
+ });
75
+ describe(`changing the payment method (${support_1.CHARGEABLE})`, function () {
76
+ this.timeout(support_1.SUITE_TIMEOUT);
77
+ before(function () {
78
+ if (!support_1.TEST_METHOD)
79
+ this.skip();
80
+ });
81
+ it("charges a newly saved method from now on", async () => {
82
+ const payer = await (0, support_1.newPayer)();
83
+ const subscription = await (0, support_1.subscribe)(payer);
84
+ const replacement = await (0, support_1.saveMethod)(payer.customer);
85
+ const updated = await (0, index_1.UpdateSubscriptionPaymentMethod)(subscription.id, replacement, (0, support_1.key)());
86
+ strict_1.default.equal(updated.paymentMethod, replacement);
87
+ strict_1.default.equal(updated.latestPayment, subscription.latestPayment, "switching charges nothing");
88
+ strict_1.default.equal((await (0, index_1.GetSubscription)(subscription.id)).paymentMethod, replacement);
89
+ });
90
+ it("refuses to change the method of a subscription that has ended", async () => {
91
+ const payer = await (0, support_1.newPayer)();
92
+ const subscription = await (0, support_1.subscribe)(payer);
93
+ await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "now");
94
+ await (0, support_1.rejectsWith)((0, index_1.UpdateSubscriptionPaymentMethod)(subscription.id, payer.paymentMethod, (0, support_1.key)()), index_1.InvalidSubscriptionStateError, "update after the end");
95
+ });
96
+ });
97
+ describe("unknown subscriptions", function () {
98
+ this.timeout(support_1.SUITE_TIMEOUT);
99
+ it("raises SubscriptionNotFoundError for every call on an unknown id", async () => {
100
+ await (0, support_1.rejectsWith)((0, index_1.GetSubscription)(support_1.ABSENT_ID), index_1.SubscriptionNotFoundError, "get");
101
+ await (0, support_1.rejectsWith)((0, index_1.CancelSubscription)(support_1.ABSENT_ID, (0, support_1.key)(), "now"), index_1.SubscriptionNotFoundError, "cancel");
102
+ await (0, support_1.rejectsWith)((0, index_1.UpdateSubscriptionPaymentMethod)(support_1.ABSENT_ID, "pm_absent", (0, support_1.key)()), index_1.SubscriptionNotFoundError, "update");
103
+ });
104
+ });
105
+ describe(`requests outside the contract (${support_1.CHARGEABLE})`, function () {
106
+ this.timeout(support_1.SUITE_TIMEOUT);
107
+ before(function () {
108
+ if (!support_1.TEST_METHOD)
109
+ this.skip();
110
+ });
111
+ const INVALID = {
112
+ "a zero amount": () => ({ amount: (0, support_1.amount)(0) }),
113
+ "a fractional amount": () => ({ amount: (0, support_1.amount)(10.5) }),
114
+ "an interval count of zero": () => ({ intervalCount: 0 }),
115
+ "a fractional interval count": () => ({ intervalCount: 1.5 }),
116
+ "an interval outside the vocabulary": () => ({
117
+ interval: "fortnight",
118
+ }),
119
+ "a trial that has already ended": (now) => ({ trialEnd: now - support_1.DAY_MS }),
120
+ "a billing anchor in the past": (now) => ({
121
+ billingAnchor: now - support_1.DAY_MS,
122
+ }),
123
+ "both a trial and a billing anchor": (now) => ({
124
+ trialEnd: now + support_1.DAY_MS,
125
+ billingAnchor: now + 2 * support_1.DAY_MS,
126
+ }),
127
+ };
128
+ for (const [label, overrides] of Object.entries(INVALID)) {
129
+ it(`refuses ${label}`, async () => {
130
+ const payer = await (0, support_1.newPayer)();
131
+ await (0, support_1.rejectsWith)((0, index_1.CreateSubscription)((0, support_1.monthly)(payer, overrides(Date.now())), (0, support_1.key)()), index_1.InvalidSubscriptionRequestError, label);
132
+ });
133
+ }
134
+ it("refuses a customer that does not exist, as a request, not a missing subscription", async () => {
135
+ const payer = await (0, support_1.newPayer)();
136
+ await (0, support_1.rejectsWith)((0, index_1.CreateSubscription)((0, support_1.monthly)(payer, { customer: ABSENT_CUSTOMER }), (0, support_1.key)()), index_1.InvalidSubscriptionRequestError, "unknown customer");
137
+ });
138
+ it("refuses a payment method that does not exist", async () => {
139
+ const payer = await (0, support_1.newPayer)();
140
+ await (0, support_1.rejectsWith)((0, index_1.CreateSubscription)((0, support_1.monthly)(payer, { paymentMethod: ABSENT_METHOD }), (0, support_1.key)()), index_1.InvalidSubscriptionRequestError, "unknown method");
141
+ });
142
+ it("refuses to switch to a method that does not exist, and the subscription stays", async () => {
143
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
144
+ await (0, support_1.rejectsWith)((0, index_1.UpdateSubscriptionPaymentMethod)(subscription.id, ABSENT_METHOD, (0, support_1.key)()), index_1.InvalidSubscriptionRequestError, "switch to an unknown method");
145
+ strict_1.default.equal((await (0, index_1.GetSubscription)(subscription.id)).paymentMethod, subscription.paymentMethod);
146
+ });
147
+ });
148
+ describe(`events (${support_1.OBSERVABLE})`, function () {
149
+ this.timeout(support_1.SUITE_TIMEOUT);
150
+ const received = [];
151
+ const HANDLER_ID = "conformance-suite";
152
+ before(function () {
153
+ if (!support_1.EVENTS_OBSERVABLE || !support_1.TEST_METHOD)
154
+ this.skip();
155
+ index_1.SubscriptionEvents.register(HANDLER_ID, (event) => {
156
+ received.push(event);
157
+ });
158
+ });
159
+ after(() => {
160
+ if (support_1.EVENTS_OBSERVABLE)
161
+ index_1.SubscriptionEvents.unregister(HANDLER_ID);
162
+ });
163
+ async function eventsFor(id, count) {
164
+ const deadline = Date.now() + EVENT_TIMEOUT;
165
+ const matching = () => received.filter((event) => event.subscription.id === id);
166
+ while (matching().length < count && Date.now() < deadline) {
167
+ await (0, promises_1.setTimeout)(EVENT_POLL);
168
+ }
169
+ return matching();
170
+ }
171
+ it("reports a new paid subscription as created, then paid", async () => {
172
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)());
173
+ const events = await eventsFor(subscription.id, 2);
174
+ strict_1.default.deepEqual(events.map((event) => event.type).sort(), [
175
+ "subscription.created",
176
+ "subscription.payment_succeeded",
177
+ ]);
178
+ const paid = events.find((event) => event.type === "subscription.payment_succeeded");
179
+ strict_1.default.equal(paid?.payment, subscription.latestPayment);
180
+ strict_1.default.equal(new Set(events.map((event) => event.id)).size, events.length);
181
+ });
182
+ it("reports a cancellation", async () => {
183
+ const subscription = await (0, support_1.subscribe)(await (0, support_1.newPayer)(), {
184
+ trialEnd: (0, support_1.inWholeSeconds)(support_1.TRIAL_DAYS * support_1.DAY_MS),
185
+ });
186
+ await (0, index_1.CancelSubscription)(subscription.id, (0, support_1.key)(), "now");
187
+ const events = await eventsFor(subscription.id, 2);
188
+ const canceled = events.find((event) => event.type === "subscription.canceled");
189
+ strict_1.default.ok(canceled, "a cancellation must be reported");
190
+ strict_1.default.equal(canceled.subscription.status, "canceled");
191
+ strict_1.default.equal(canceled.payment, undefined);
192
+ });
193
+ });
194
+ //# sourceMappingURL=subscriptions-changes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions-changes.test.js","sourceRoot":"","sources":["../../src/tests/subscriptions-changes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const promises_1 = require("node:timers/promises");
8
+ const interface_payment_1 = require("@antelopejs/interface-payment");
9
+ const index_1 = require("../index");
10
+ const support_1 = require("./support");
11
+ describe(`creating a subscription (${support_1.CHARGEABLE})`, function () {
12
+ this.timeout(support_1.SUITE_TIMEOUT);
13
+ before(function () {
14
+ if (!support_1.TEST_METHOD)
15
+ this.skip();
16
+ });
17
+ it("charges the first period at once and reports it active", async () => {
18
+ const payer = await (0, support_1.newPayer)();
19
+ const before = Date.now();
20
+ const subscription = await (0, support_1.subscribe)(payer);
21
+ strict_1.default.equal(subscription.status, "active");
22
+ strict_1.default.equal(subscription.cancelAtPeriodEnd, false);
23
+ strict_1.default.equal(subscription.paymentMethod, payer.paymentMethod);
24
+ strict_1.default.ok(subscription.latestPayment, "the first charge must be recorded");
25
+ strict_1.default.ok(subscription.currentPeriodStart <= Date.now());
26
+ strict_1.default.ok(subscription.currentPeriodStart >= before - support_1.DAY_MS);
27
+ const length = subscription.currentPeriodEnd - subscription.currentPeriodStart;
28
+ strict_1.default.ok(length >= support_1.SHORTEST_MONTH_MS && length <= support_1.LONGEST_MONTH_MS, `a one-month period lasted ${length / support_1.DAY_MS} days`);
29
+ });
30
+ it("charges the first period as an off-session payment it can be told by", async () => {
31
+ const payer = await (0, support_1.newPayer)();
32
+ const subscription = await (0, support_1.subscribe)(payer);
33
+ const payment = await (0, support_1.settledPayment)(subscription.latestPayment);
34
+ strict_1.default.equal(payment.status, "succeeded");
35
+ strict_1.default.deepEqual(payment.amount, subscription.amount);
36
+ strict_1.default.equal(payment.customer, payer.customer);
37
+ strict_1.default.equal(payment.metadata?.[index_1.SUBSCRIPTION_METADATA_KEY], subscription.id, "a subscription charge must be distinguishable from a one-off payment");
38
+ });
39
+ it("starts a trial without charging anything", async () => {
40
+ const payer = await (0, support_1.newPayer)();
41
+ const trialEnd = (0, support_1.inWholeSeconds)(support_1.TRIAL_DAYS * support_1.DAY_MS);
42
+ const subscription = await (0, support_1.subscribe)(payer, { trialEnd });
43
+ strict_1.default.equal(subscription.status, "trialing");
44
+ strict_1.default.equal(subscription.trialEnd, trialEnd);
45
+ strict_1.default.equal(subscription.currentPeriodEnd, trialEnd);
46
+ strict_1.default.equal(subscription.latestPayment, undefined, "a trial charges nothing");
47
+ });
48
+ it("defers the first charge to a billing anchor", async () => {
49
+ const payer = await (0, support_1.newPayer)();
50
+ const billingAnchor = (0, support_1.inWholeSeconds)(3 * support_1.DAY_MS);
51
+ const subscription = await (0, support_1.subscribe)(payer, { billingAnchor });
52
+ strict_1.default.equal(subscription.status, "active");
53
+ strict_1.default.equal(subscription.trialEnd, undefined);
54
+ strict_1.default.equal(subscription.currentPeriodEnd, billingAnchor);
55
+ strict_1.default.equal(subscription.latestPayment, undefined);
56
+ });
57
+ it("keeps the request's interval count and metadata", async () => {
58
+ const payer = await (0, support_1.newPayer)();
59
+ const metadata = { plan: "conformance-quarterly" };
60
+ const subscription = await (0, support_1.subscribe)(payer, { intervalCount: 3, metadata });
61
+ strict_1.default.equal(subscription.intervalCount, 3);
62
+ strict_1.default.deepEqual(subscription.metadata, metadata);
63
+ const length = subscription.currentPeriodEnd - subscription.currentPeriodStart;
64
+ strict_1.default.ok(length >= 3 * support_1.SHORTEST_MONTH_MS && length <= 3 * support_1.LONGEST_MONTH_MS, `a three-month period lasted ${length / support_1.DAY_MS} days`);
65
+ });
66
+ it("replays the original subscription for a repeated idempotency key", async () => {
67
+ const payer = await (0, support_1.newPayer)();
68
+ const request = (0, support_1.monthly)(payer);
69
+ const idempotencyKey = (0, support_1.key)();
70
+ const first = await (0, index_1.CreateSubscription)(request, idempotencyKey);
71
+ const replay = await (0, index_1.CreateSubscription)(request, idempotencyKey);
72
+ strict_1.default.equal(replay.id, first.id);
73
+ strict_1.default.equal(replay.latestPayment, first.latestPayment, "replaying must not charge again");
74
+ strict_1.default.equal((await (0, index_1.ListSubscriptions)(payer.customer)).length, 1);
75
+ });
76
+ });
77
+ describe(`reading subscriptions back (${support_1.CHARGEABLE})`, function () {
78
+ this.timeout(support_1.SUITE_TIMEOUT);
79
+ before(function () {
80
+ if (!support_1.TEST_METHOD)
81
+ this.skip();
82
+ });
83
+ it("reads a subscription back by its identifier", async () => {
84
+ const payer = await (0, support_1.newPayer)();
85
+ const created = await (0, support_1.subscribe)(payer);
86
+ const read = await (0, index_1.GetSubscription)(created.id);
87
+ strict_1.default.equal(read.id, created.id);
88
+ strict_1.default.equal(read.status, created.status);
89
+ strict_1.default.equal(read.currentPeriodStart, created.currentPeriodStart);
90
+ strict_1.default.equal(read.currentPeriodEnd, created.currentPeriodEnd);
91
+ strict_1.default.equal(read.latestPayment, created.latestPayment);
92
+ (0, support_1.assertSubscriptionShape)(read, (0, support_1.monthly)(payer, { reference: created.reference }));
93
+ });
94
+ it("lists a customer's subscriptions newest first, and no one else's", async () => {
95
+ const payer = await (0, support_1.newPayer)();
96
+ const stranger = await (0, support_1.newPayer)();
97
+ const older = await (0, support_1.subscribe)(payer);
98
+ await (0, promises_1.setTimeout)(support_1.PROVIDER_CLOCK_RESOLUTION_MS);
99
+ const newer = await (0, support_1.subscribe)(payer, {
100
+ trialEnd: (0, support_1.inWholeSeconds)(support_1.TRIAL_DAYS * support_1.DAY_MS),
101
+ });
102
+ await (0, support_1.subscribe)(stranger);
103
+ const listed = await (0, index_1.ListSubscriptions)(payer.customer);
104
+ strict_1.default.deepEqual(listed.map((subscription) => subscription.id), [newer.id, older.id]);
105
+ });
106
+ it("lists nothing for a customer without subscriptions", async () => {
107
+ const payer = await (0, support_1.newPayer)();
108
+ strict_1.default.deepEqual(await (0, index_1.ListSubscriptions)(payer.customer), []);
109
+ });
110
+ });
111
+ const REFUSED_PAYMENT_STATUSES = ["failed", "canceled"];
112
+ describe(`a declined first period (${support_1.DECLINES_LATER})`, function () {
113
+ this.timeout(support_1.SUITE_TIMEOUT);
114
+ before(function () {
115
+ if (!support_1.TEST_METHOD_DECLINES_LATER)
116
+ this.skip();
117
+ });
118
+ it("refuses the subscription and says which payment was declined", async () => {
119
+ const payer = await (0, support_1.newPayer)(support_1.TEST_METHOD_DECLINES_LATER);
120
+ const error = await (0, support_1.rejectsWith)((0, index_1.CreateSubscription)((0, support_1.monthly)(payer), (0, support_1.key)()), index_1.SubscriptionPaymentError, "a declined first period");
121
+ const payment = error.payment;
122
+ strict_1.default.ok(REFUSED_PAYMENT_STATUSES.includes(payment.status), `a declined first charge cannot be ${payment.status}`);
123
+ strict_1.default.equal(payment.failure !== undefined, payment.status === "failed", "a failed payment says why");
124
+ strict_1.default.equal((await (0, interface_payment_1.GetPayment)(payment.id)).status, payment.status);
125
+ strict_1.default.deepEqual(await (0, index_1.ListSubscriptions)(payer.customer), [], "a refused subscription must not exist");
126
+ });
127
+ it("refuses the same way when the idempotency key is replayed", async () => {
128
+ const payer = await (0, support_1.newPayer)(support_1.TEST_METHOD_DECLINES_LATER);
129
+ const request = (0, support_1.monthly)(payer);
130
+ const idempotencyKey = (0, support_1.key)();
131
+ const first = await (0, support_1.rejectsWith)((0, index_1.CreateSubscription)(request, idempotencyKey), index_1.SubscriptionPaymentError, "first attempt");
132
+ const replay = await (0, support_1.rejectsWith)((0, index_1.CreateSubscription)(request, idempotencyKey), index_1.SubscriptionPaymentError, "replay");
133
+ strict_1.default.equal(replay.payment.id, first.payment.id, "a replay must not charge again");
134
+ });
135
+ it("still starts a trial, since a trial charges nothing", async () => {
136
+ const payer = await (0, support_1.newPayer)(support_1.TEST_METHOD_DECLINES_LATER);
137
+ const subscription = await (0, support_1.subscribe)(payer, {
138
+ trialEnd: (0, support_1.inWholeSeconds)(support_1.TRIAL_DAYS * support_1.DAY_MS),
139
+ });
140
+ strict_1.default.equal(subscription.status, "trialing");
141
+ strict_1.default.equal(subscription.amount.value, support_1.PERIOD_VALUE);
142
+ });
143
+ });
144
+ //# sourceMappingURL=subscriptions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.test.js","sourceRoot":"","sources":["../../src/tests/subscriptions.test.ts"],"names":[],"mappings":";;;;;AAAA,gEAAwC;AACxC,mDAA2D;AAC3D,qEAA2D;AAE3D,oCAMkB;AAClB,uCAoBmB;AAEnB,QAAQ,CAAC,4BAA4B,oBAAU,GAAG,EAAE;IAClD,IAAI,CAAC,OAAO,CAAC,uBAAa,CAAC,CAAC;IAE5B,MAAM,CAAC;QACL,IAAI,CAAC,qBAAW;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,CAAC,CAAC;QAE5C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC5C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACpD,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9D,gBAAM,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,mCAAmC,CAAC,CAAC;QAC3E,gBAAM,CAAC,EAAE,CAAC,YAAY,CAAC,kBAAkB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACzD,gBAAM,CAAC,EAAE,CAAC,YAAY,CAAC,kBAAkB,IAAI,MAAM,GAAG,gBAAM,CAAC,CAAC;QAC9D,MAAM,MAAM,GACV,YAAY,CAAC,gBAAgB,GAAG,YAAY,CAAC,kBAAkB,CAAC;QAClE,gBAAM,CAAC,EAAE,CACP,MAAM,IAAI,2BAAiB,IAAI,MAAM,IAAI,0BAAgB,EACzD,6BAA6B,MAAM,GAAG,gBAAM,OAAO,CACpD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,MAAM,IAAA,wBAAc,EAAC,YAAY,CAAC,aAAc,CAAC,CAAC;QAClE,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC1C,gBAAM,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACtD,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/C,gBAAM,CAAC,KAAK,CACV,OAAO,CAAC,QAAQ,EAAE,CAAC,iCAAyB,CAAC,EAC7C,YAAY,CAAC,EAAE,EACf,sEAAsE,CACvE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAA,wBAAc,EAAC,oBAAU,GAAG,gBAAM,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE1D,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC9C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC9C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QACtD,gBAAM,CAAC,KAAK,CACV,YAAY,CAAC,aAAa,EAC1B,SAAS,EACT,yBAAyB,CAC1B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,IAAA,wBAAc,EAAC,CAAC,GAAG,gBAAM,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;QAE/D,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC5C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC/C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAC3D,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;QACnD,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE5E,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAC5C,gBAAM,CAAC,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,MAAM,GACV,YAAY,CAAC,gBAAgB,GAAG,YAAY,CAAC,kBAAkB,CAAC;QAClE,gBAAM,CAAC,EAAE,CACP,MAAM,IAAI,CAAC,GAAG,2BAAiB,IAAI,MAAM,IAAI,CAAC,GAAG,0BAAgB,EACjE,+BAA+B,MAAM,GAAG,gBAAM,OAAO,CACtD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,IAAA,iBAAO,EAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,cAAc,GAAG,IAAA,aAAG,GAAE,CAAC;QAE7B,MAAM,KAAK,GAAG,MAAM,IAAA,0BAAkB,EAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAkB,EAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAEjE,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAClC,gBAAM,CAAC,KAAK,CACV,MAAM,CAAC,aAAa,EACpB,KAAK,CAAC,aAAa,EACnB,iCAAiC,CAClC,CAAC;QACF,gBAAM,CAAC,KAAK,CAAC,CAAC,MAAM,IAAA,yBAAiB,EAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,oBAAU,GAAG,EAAE;IACrD,IAAI,CAAC,OAAO,CAAC,uBAAa,CAAC,CAAC;IAE5B,MAAM,CAAC;QACL,IAAI,CAAC,qBAAW;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,CAAC,CAAC;QAEvC,MAAM,IAAI,GAAG,MAAM,IAAA,uBAAe,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC/C,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAClC,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1C,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAClE,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9D,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;QACxD,IAAA,iCAAuB,EACrB,IAAI,EACJ,IAAA,iBAAO,EAAC,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,CAAC,CAAC;QACrC,MAAM,IAAA,qBAAK,EAAC,sCAA4B,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,EAAE;YACnC,QAAQ,EAAE,IAAA,wBAAc,EAAC,oBAAU,GAAG,gBAAM,CAAC;SAC9C,CAAC,CAAC;QACH,MAAM,IAAA,mBAAS,EAAC,QAAQ,CAAC,CAAC;QAE1B,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAiB,EAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvD,gBAAM,CAAC,SAAS,CACd,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,EAC7C,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CACrB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,GAAE,CAAC;QAC/B,gBAAM,CAAC,SAAS,CAAC,MAAM,IAAA,yBAAiB,EAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,MAAM,wBAAwB,GAAsB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AAE3E,QAAQ,CAAC,4BAA4B,wBAAc,GAAG,EAAE;IACtD,IAAI,CAAC,OAAO,CAAC,uBAAa,CAAC,CAAC;IAE5B,MAAM,CAAC;QACL,IAAI,CAAC,oCAA0B;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,EAAC,oCAA0B,CAAC,CAAC;QAEzD,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAW,EAC7B,IAAA,0BAAkB,EAAC,IAAA,iBAAO,EAAC,KAAK,CAAC,EAAE,IAAA,aAAG,GAAE,CAAC,EACzC,gCAAwB,EACxB,yBAAyB,CAC1B,CAAC;QAEF,MAAM,OAAO,GAAI,KAAkC,CAAC,OAAO,CAAC;QAC5D,gBAAM,CAAC,EAAE,CACP,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EACjD,qCAAqC,OAAO,CAAC,MAAM,EAAE,CACtD,CAAC;QACF,gBAAM,CAAC,KAAK,CACV,OAAO,CAAC,OAAO,KAAK,SAAS,EAC7B,OAAO,CAAC,MAAM,KAAK,QAAQ,EAC3B,2BAA2B,CAC5B,CAAC;QACF,gBAAM,CAAC,KAAK,CAAC,CAAC,MAAM,IAAA,8BAAU,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACpE,gBAAM,CAAC,SAAS,CACd,MAAM,IAAA,yBAAiB,EAAC,KAAK,CAAC,QAAQ,CAAC,EACvC,EAAE,EACF,uCAAuC,CACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,EAAC,oCAA0B,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,IAAA,iBAAO,EAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,cAAc,GAAG,IAAA,aAAG,GAAE,CAAC;QAE7B,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAW,EAC7B,IAAA,0BAAkB,EAAC,OAAO,EAAE,cAAc,CAAC,EAC3C,gCAAwB,EACxB,eAAe,CAChB,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAW,EAC9B,IAAA,0BAAkB,EAAC,OAAO,EAAE,cAAc,CAAC,EAC3C,gCAAwB,EACxB,QAAQ,CACT,CAAC;QAEF,gBAAM,CAAC,KAAK,CACT,MAAmC,CAAC,OAAO,CAAC,EAAE,EAC9C,KAAkC,CAAC,OAAO,CAAC,EAAE,EAC9C,gCAAgC,CACjC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAQ,EAAC,oCAA0B,CAAC,CAAC;QACzD,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAS,EAAC,KAAK,EAAE;YAC1C,QAAQ,EAAE,IAAA,wBAAc,EAAC,oBAAU,GAAG,gBAAM,CAAC;SAC9C,CAAC,CAAC;QACH,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC9C,gBAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,sBAAY,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}