@mesub/node 0.0.0-stage → 0.1.2

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.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +840 -2
  3. package/dist/chunk-43Q4PNF7.cjs +480 -0
  4. package/dist/chunk-43Q4PNF7.cjs.map +1 -0
  5. package/dist/chunk-4AAPR37Y.js +120 -0
  6. package/dist/chunk-4AAPR37Y.js.map +1 -0
  7. package/dist/chunk-4JSJOX35.cjs +2040 -0
  8. package/dist/chunk-4JSJOX35.cjs.map +1 -0
  9. package/dist/chunk-66VVEXMU.cjs +340 -0
  10. package/dist/chunk-66VVEXMU.cjs.map +1 -0
  11. package/dist/chunk-J2CE4QWV.js +340 -0
  12. package/dist/chunk-J2CE4QWV.js.map +1 -0
  13. package/dist/chunk-JJWHMB2X.js +480 -0
  14. package/dist/chunk-JJWHMB2X.js.map +1 -0
  15. package/dist/chunk-NOS4FWWQ.js +2040 -0
  16. package/dist/chunk-NOS4FWWQ.js.map +1 -0
  17. package/dist/chunk-SJRQDWTI.cjs +120 -0
  18. package/dist/chunk-SJRQDWTI.cjs.map +1 -0
  19. package/dist/client-BEuDegEY.d.cts +765 -0
  20. package/dist/client-CXQLkSAJ.d.ts +765 -0
  21. package/dist/errors-BN4ZWUfM.d.ts +112 -0
  22. package/dist/errors-DcLfunS-.d.cts +112 -0
  23. package/dist/express.cjs +129 -0
  24. package/dist/express.cjs.map +1 -0
  25. package/dist/express.d.cts +57 -0
  26. package/dist/express.d.ts +57 -0
  27. package/dist/express.js +129 -0
  28. package/dist/express.js.map +1 -0
  29. package/dist/guard-CaXiHMVF.d.ts +51 -0
  30. package/dist/guard-D4AB5HtN.d.cts +51 -0
  31. package/dist/index.cjs +39 -0
  32. package/dist/index.cjs.map +1 -0
  33. package/dist/index.d.cts +44 -0
  34. package/dist/index.d.ts +44 -0
  35. package/dist/index.js +39 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/nest.cjs +62 -0
  38. package/dist/nest.cjs.map +1 -0
  39. package/dist/nest.d.cts +57 -0
  40. package/dist/nest.d.ts +57 -0
  41. package/dist/nest.js +62 -0
  42. package/dist/nest.js.map +1 -0
  43. package/dist/next.cjs +113 -0
  44. package/dist/next.cjs.map +1 -0
  45. package/dist/next.d.cts +63 -0
  46. package/dist/next.d.ts +63 -0
  47. package/dist/next.js +113 -0
  48. package/dist/next.js.map +1 -0
  49. package/dist/routes-B7wN4sby.d.ts +130 -0
  50. package/dist/routes-CMzB52P6.d.cts +130 -0
  51. package/dist/situations.cjs +15 -0
  52. package/dist/situations.cjs.map +1 -0
  53. package/dist/situations.d.cts +607 -0
  54. package/dist/situations.d.ts +607 -0
  55. package/dist/situations.js +15 -0
  56. package/dist/situations.js.map +1 -0
  57. package/dist/subscriptions-B6Lin6i_.d.cts +775 -0
  58. package/dist/subscriptions-B6Lin6i_.d.ts +775 -0
  59. package/dist/testing.cjs +1488 -0
  60. package/dist/testing.cjs.map +1 -0
  61. package/dist/testing.d.cts +331 -0
  62. package/dist/testing.d.ts +331 -0
  63. package/dist/testing.js +1488 -0
  64. package/dist/testing.js.map +1 -0
  65. package/package.json +158 -4
@@ -0,0 +1,51 @@
1
+ import { C as Customer, A as AccessAnswer } from './subscriptions-B6Lin6i_.js';
2
+
3
+ /** Who a call is about, normalised as Mesub reads it. */
4
+ interface Asked {
5
+ kind: 'wallet' | 'external_id' | 'email';
6
+ value: string;
7
+ }
8
+
9
+ /** Why a request was turned away, and what it answers by default. */
10
+ type DenialReason = 'unauthenticated' | 'no_access' | 'unavailable';
11
+ /** Who is asking and what Mesub answered, as a guarded route receives it. */
12
+ interface MesubAccess {
13
+ /**
14
+ * The wallet that pays. Asked by external id or email, the one Mesub
15
+ * answered with; null when the answer is the outage fallback's and holds none.
16
+ */
17
+ wallet: string | null;
18
+ /** Who Mesub was asked about: a wallet, your own id for them, or their email. */
19
+ customer: Asked;
20
+ /** The plan that let the request through: the first of the list that did. */
21
+ plan: string;
22
+ /** Mesub's answer for that plan. */
23
+ answer: AccessAnswer | null;
24
+ /** The answer came from the outage fallback. */
25
+ stale: boolean;
26
+ }
27
+ /** A refusal, as `onDenied` receives it. */
28
+ interface Denial {
29
+ reason: DenialReason;
30
+ /** 401, 402 or 503: what would be answered without `onDenied`. */
31
+ status: number;
32
+ /** Mesub's answer, for the first plan asked when there are several. */
33
+ answer: AccessAnswer | null;
34
+ }
35
+ /**
36
+ * The plan a guard asks about: one, any one of several (the first that grants
37
+ * lets the request through), or either of those worked out per request.
38
+ */
39
+ type PlanOption<Req> = string | readonly string[] | ((request: Req) => string | readonly string[]);
40
+ /**
41
+ * Who is asking, from your own auth: `(req) => ({ external_id: req.user.id })`,
42
+ * a wallet, or an email. Null or undefined when nobody is signed in, a 401.
43
+ * May be async.
44
+ *
45
+ * It must come from a session you verified, never from the request itself (a
46
+ * query, a body, a header the caller writes): whoever names a subscriber
47
+ * would get their access.
48
+ */
49
+ type CustomerOption<Req> = (request: Req) => Customer | string | null | undefined | Promise<Customer | string | null | undefined>;
50
+
51
+ export type { Asked as A, CustomerOption as C, Denial as D, MesubAccess as M, PlanOption as P, DenialReason as a };
@@ -0,0 +1,51 @@
1
+ import { C as Customer, A as AccessAnswer } from './subscriptions-B6Lin6i_.cjs';
2
+
3
+ /** Who a call is about, normalised as Mesub reads it. */
4
+ interface Asked {
5
+ kind: 'wallet' | 'external_id' | 'email';
6
+ value: string;
7
+ }
8
+
9
+ /** Why a request was turned away, and what it answers by default. */
10
+ type DenialReason = 'unauthenticated' | 'no_access' | 'unavailable';
11
+ /** Who is asking and what Mesub answered, as a guarded route receives it. */
12
+ interface MesubAccess {
13
+ /**
14
+ * The wallet that pays. Asked by external id or email, the one Mesub
15
+ * answered with; null when the answer is the outage fallback's and holds none.
16
+ */
17
+ wallet: string | null;
18
+ /** Who Mesub was asked about: a wallet, your own id for them, or their email. */
19
+ customer: Asked;
20
+ /** The plan that let the request through: the first of the list that did. */
21
+ plan: string;
22
+ /** Mesub's answer for that plan. */
23
+ answer: AccessAnswer | null;
24
+ /** The answer came from the outage fallback. */
25
+ stale: boolean;
26
+ }
27
+ /** A refusal, as `onDenied` receives it. */
28
+ interface Denial {
29
+ reason: DenialReason;
30
+ /** 401, 402 or 503: what would be answered without `onDenied`. */
31
+ status: number;
32
+ /** Mesub's answer, for the first plan asked when there are several. */
33
+ answer: AccessAnswer | null;
34
+ }
35
+ /**
36
+ * The plan a guard asks about: one, any one of several (the first that grants
37
+ * lets the request through), or either of those worked out per request.
38
+ */
39
+ type PlanOption<Req> = string | readonly string[] | ((request: Req) => string | readonly string[]);
40
+ /**
41
+ * Who is asking, from your own auth: `(req) => ({ external_id: req.user.id })`,
42
+ * a wallet, or an email. Null or undefined when nobody is signed in, a 401.
43
+ * May be async.
44
+ *
45
+ * It must come from a session you verified, never from the request itself (a
46
+ * query, a body, a header the caller writes): whoever names a subscriber
47
+ * would get their access.
48
+ */
49
+ type CustomerOption<Req> = (request: Req) => Customer | string | null | undefined | Promise<Customer | string | null | undefined>;
50
+
51
+ export type { Asked as A, CustomerOption as C, Denial as D, MesubAccess as M, PlanOption as P, DenialReason as a };
package/dist/index.cjs ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ var _chunk4JSJOX35cjs = require('./chunk-4JSJOX35.cjs');
14
+
15
+
16
+
17
+
18
+
19
+
20
+ var _chunk43Q4PNF7cjs = require('./chunk-43Q4PNF7.cjs');
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+ exports.ACCESS_LINE = _chunk43Q4PNF7cjs.ACCESS_LINE; exports.API_VERSION = _chunk4JSJOX35cjs.API_VERSION; exports.API_VERSION_HEADER = _chunk4JSJOX35cjs.API_VERSION_HEADER; exports.AccessCache = _chunk4JSJOX35cjs.AccessCache; exports.CONFIRMATIONS = _chunk43Q4PNF7cjs.CONFIRMATIONS; exports.DEFAULT_MAX_ENTRIES = _chunk4JSJOX35cjs.DEFAULT_MAX_ENTRIES; exports.DEFAULT_MAX_STALE_MS = _chunk4JSJOX35cjs.DEFAULT_MAX_STALE_MS; exports.MemoryStore = _chunk4JSJOX35cjs.MemoryStore; exports.Mesub = _chunk4JSJOX35cjs.Mesub; exports.MesubError = _chunk4JSJOX35cjs.MesubError; exports.MesubSubmitError = _chunk4JSJOX35cjs.MesubSubmitError; exports.SITUATIONS = _chunk43Q4PNF7cjs.SITUATIONS; exports.VERSION = _chunk4JSJOX35cjs.VERSION; exports.explain = _chunk43Q4PNF7cjs.explain; exports.situationOf = _chunk43Q4PNF7cjs.situationOf; exports.verifyWebhook = _chunk4JSJOX35cjs.verifyWebhook;
39
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/node-sdk/node-sdk/dist/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,i3BAAC","file":"/home/runner/work/node-sdk/node-sdk/dist/index.cjs"}
@@ -0,0 +1,44 @@
1
+ import { C as CacheStore, a as CacheEntry } from './client-BEuDegEY.cjs';
2
+ export { A as AccessCache, b as AccessCacheOptions, c as AccessChangedDetail, d as CachedAnswer, e as CreatedDetail, D as DEFAULT_MAX_STALE_MS, f as Decision, E as EndedDetail, g as EventList, h as EventListParams, i as EventNetwork, j as EventType, k as Events, F as FirstPayment, H as HeaderSource, M as Mesub, l as MesubEvent, m as MesubOptions, N as NoDetail, P as PaymentFailedDetail, n as Plan, o as PlanStatus, p as PlanToken, q as Plans, R as RenewalIssue, r as RenewalUpcomingDetail, s as RenewedDetail, t as Revalidating, S as StoppedDetail, u as SubscriptionAccessGrantedEvent, v as SubscriptionAccessRevokedEvent, w as SubscriptionCancelledEvent, x as SubscriptionCreatedEvent, y as SubscriptionEndedEvent, z as SubscriptionExpiredEvent, B as SubscriptionPausedEvent, G as SubscriptionPaymentFailedEvent, I as SubscriptionRenewalUpcomingEvent, J as SubscriptionRenewedEvent, K as SubscriptionResumedEvent, L as SubscriptionStoppedEvent, O as SubscriptionUnpausedEvent, T as TestEvent, V as VerifyWebhookOptions, W as WebhookBody, Q as WebhookEvent, U as WebhookEventType, X as Webhooks, Y as verifyWebhook } from './client-BEuDegEY.cjs';
3
+ export { M as MesubError, a as MesubErrorCode, b as MesubErrorOptions, c as MesubSubmitError, d as MesubSubmitErrorOptions } from './errors-DcLfunS-.cjs';
4
+ export { A as AccessAnswer, a as AccessList, b as AccessOptions, c as AttemptsParams, B as BlockedReason, d as ConfirmOptions, e as ConfirmParams, f as ConfirmReasonCode, g as ConfirmResult, C as Customer, E as EndReason, L as LateReason, h as ListParams, P as PaymentStatus, i as PullOutcome, R as RequestOptions, S as ServedAttempt, j as ServerSubscription, k as ServerSubscriptionList, l as ServerSubscriptionStatus, m as StopReason, n as SubmitOptions, o as SubmitParams, p as SubmitResult, q as SubscribeCosts, r as SubscribeParams, s as SubscribeTransaction, t as SubscriptionAttempt, u as SubscriptionAttemptList, v as SubscriptionStatus, w as Subscriptions, W as WalletTransaction } from './subscriptions-B6Lin6i_.cjs';
5
+ export { ACCESS_LINE, CONFIRMATIONS, ConfirmationKey, ExplainOptions, Explainable, ExplainedAction, Explanation, SITUATIONS, Situation, SituationActionId, SituationActionTemplate, SituationActor, SituationKey, SituationText, explain, situationOf } from './situations.cjs';
6
+
7
+ /** Kept in step with package.json by `test/version.spec.ts`. */
8
+ declare const VERSION = "0.1.2";
9
+ /**
10
+ * The version of the Mesub API this release was written against, sent in
11
+ * the `Mesub-Version` header of every call, so the API can change its
12
+ * answers for newer releases without breaking this one. Moved only with a
13
+ * release, never by a merchant.
14
+ */
15
+ declare const API_VERSION = "2026-10-02";
16
+ /** The header `API_VERSION` is sent in. */
17
+ declare const API_VERSION_HEADER = "Mesub-Version";
18
+
19
+ /** How many answers the memory store keeps before dropping the least recently used. */
20
+ declare const DEFAULT_MAX_ENTRIES = 10000;
21
+ interface MemoryStoreOptions {
22
+ /** A whole number above 0: 10 000 by default. */
23
+ maxEntries?: number;
24
+ /** The clock, replaced in tests. */
25
+ now?: () => number;
26
+ }
27
+ /**
28
+ * The default store: an LRU in a `Map`, which keeps insertion order. Reading
29
+ * an entry moves it to the end, so the first key is always the least recently
30
+ * used one. It lives in this process only: a restart empties it.
31
+ */
32
+ declare class MemoryStore<T = unknown> implements CacheStore<T> {
33
+ private readonly entries;
34
+ private readonly maxEntries;
35
+ private readonly now;
36
+ constructor(options?: MemoryStoreOptions);
37
+ /** How many entries are held, expired ones included until they are read. */
38
+ get size(): number;
39
+ get(key: string): CacheEntry<T> | undefined;
40
+ set(key: string, entry: CacheEntry<T>, _ttlMs: number): void;
41
+ delete(key: string): void;
42
+ }
43
+
44
+ export { API_VERSION, API_VERSION_HEADER, CacheEntry, CacheStore, DEFAULT_MAX_ENTRIES, MemoryStore, type MemoryStoreOptions, VERSION };
@@ -0,0 +1,44 @@
1
+ import { C as CacheStore, a as CacheEntry } from './client-CXQLkSAJ.js';
2
+ export { A as AccessCache, b as AccessCacheOptions, c as AccessChangedDetail, d as CachedAnswer, e as CreatedDetail, D as DEFAULT_MAX_STALE_MS, f as Decision, E as EndedDetail, g as EventList, h as EventListParams, i as EventNetwork, j as EventType, k as Events, F as FirstPayment, H as HeaderSource, M as Mesub, l as MesubEvent, m as MesubOptions, N as NoDetail, P as PaymentFailedDetail, n as Plan, o as PlanStatus, p as PlanToken, q as Plans, R as RenewalIssue, r as RenewalUpcomingDetail, s as RenewedDetail, t as Revalidating, S as StoppedDetail, u as SubscriptionAccessGrantedEvent, v as SubscriptionAccessRevokedEvent, w as SubscriptionCancelledEvent, x as SubscriptionCreatedEvent, y as SubscriptionEndedEvent, z as SubscriptionExpiredEvent, B as SubscriptionPausedEvent, G as SubscriptionPaymentFailedEvent, I as SubscriptionRenewalUpcomingEvent, J as SubscriptionRenewedEvent, K as SubscriptionResumedEvent, L as SubscriptionStoppedEvent, O as SubscriptionUnpausedEvent, T as TestEvent, V as VerifyWebhookOptions, W as WebhookBody, Q as WebhookEvent, U as WebhookEventType, X as Webhooks, Y as verifyWebhook } from './client-CXQLkSAJ.js';
3
+ export { M as MesubError, a as MesubErrorCode, b as MesubErrorOptions, c as MesubSubmitError, d as MesubSubmitErrorOptions } from './errors-BN4ZWUfM.js';
4
+ export { A as AccessAnswer, a as AccessList, b as AccessOptions, c as AttemptsParams, B as BlockedReason, d as ConfirmOptions, e as ConfirmParams, f as ConfirmReasonCode, g as ConfirmResult, C as Customer, E as EndReason, L as LateReason, h as ListParams, P as PaymentStatus, i as PullOutcome, R as RequestOptions, S as ServedAttempt, j as ServerSubscription, k as ServerSubscriptionList, l as ServerSubscriptionStatus, m as StopReason, n as SubmitOptions, o as SubmitParams, p as SubmitResult, q as SubscribeCosts, r as SubscribeParams, s as SubscribeTransaction, t as SubscriptionAttempt, u as SubscriptionAttemptList, v as SubscriptionStatus, w as Subscriptions, W as WalletTransaction } from './subscriptions-B6Lin6i_.js';
5
+ export { ACCESS_LINE, CONFIRMATIONS, ConfirmationKey, ExplainOptions, Explainable, ExplainedAction, Explanation, SITUATIONS, Situation, SituationActionId, SituationActionTemplate, SituationActor, SituationKey, SituationText, explain, situationOf } from './situations.js';
6
+
7
+ /** Kept in step with package.json by `test/version.spec.ts`. */
8
+ declare const VERSION = "0.1.2";
9
+ /**
10
+ * The version of the Mesub API this release was written against, sent in
11
+ * the `Mesub-Version` header of every call, so the API can change its
12
+ * answers for newer releases without breaking this one. Moved only with a
13
+ * release, never by a merchant.
14
+ */
15
+ declare const API_VERSION = "2026-10-02";
16
+ /** The header `API_VERSION` is sent in. */
17
+ declare const API_VERSION_HEADER = "Mesub-Version";
18
+
19
+ /** How many answers the memory store keeps before dropping the least recently used. */
20
+ declare const DEFAULT_MAX_ENTRIES = 10000;
21
+ interface MemoryStoreOptions {
22
+ /** A whole number above 0: 10 000 by default. */
23
+ maxEntries?: number;
24
+ /** The clock, replaced in tests. */
25
+ now?: () => number;
26
+ }
27
+ /**
28
+ * The default store: an LRU in a `Map`, which keeps insertion order. Reading
29
+ * an entry moves it to the end, so the first key is always the least recently
30
+ * used one. It lives in this process only: a restart empties it.
31
+ */
32
+ declare class MemoryStore<T = unknown> implements CacheStore<T> {
33
+ private readonly entries;
34
+ private readonly maxEntries;
35
+ private readonly now;
36
+ constructor(options?: MemoryStoreOptions);
37
+ /** How many entries are held, expired ones included until they are read. */
38
+ get size(): number;
39
+ get(key: string): CacheEntry<T> | undefined;
40
+ set(key: string, entry: CacheEntry<T>, _ttlMs: number): void;
41
+ delete(key: string): void;
42
+ }
43
+
44
+ export { API_VERSION, API_VERSION_HEADER, CacheEntry, CacheStore, DEFAULT_MAX_ENTRIES, MemoryStore, type MemoryStoreOptions, VERSION };
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ import {
2
+ API_VERSION,
3
+ API_VERSION_HEADER,
4
+ AccessCache,
5
+ DEFAULT_MAX_ENTRIES,
6
+ DEFAULT_MAX_STALE_MS,
7
+ MemoryStore,
8
+ Mesub,
9
+ MesubError,
10
+ MesubSubmitError,
11
+ VERSION,
12
+ verifyWebhook
13
+ } from "./chunk-NOS4FWWQ.js";
14
+ import {
15
+ ACCESS_LINE,
16
+ CONFIRMATIONS,
17
+ SITUATIONS,
18
+ explain,
19
+ situationOf
20
+ } from "./chunk-JJWHMB2X.js";
21
+ export {
22
+ ACCESS_LINE,
23
+ API_VERSION,
24
+ API_VERSION_HEADER,
25
+ AccessCache,
26
+ CONFIRMATIONS,
27
+ DEFAULT_MAX_ENTRIES,
28
+ DEFAULT_MAX_STALE_MS,
29
+ MemoryStore,
30
+ Mesub,
31
+ MesubError,
32
+ MesubSubmitError,
33
+ SITUATIONS,
34
+ VERSION,
35
+ explain,
36
+ situationOf,
37
+ verifyWebhook
38
+ };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/nest.cjs ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+ var _chunkSJRQDWTIcjs = require('./chunk-SJRQDWTI.cjs');
13
+
14
+
15
+ var _chunk4JSJOX35cjs = require('./chunk-4JSJOX35.cjs');
16
+
17
+ // src/nest.ts
18
+
19
+
20
+
21
+
22
+ var _common = require('@nestjs/common');
23
+ function setHeader(response, name, value) {
24
+ if (typeof response.setHeader === "function") response.setHeader(name, value);
25
+ else if (typeof response.header === "function") response.header(name, value);
26
+ }
27
+ function RequirePlan(plan, options) {
28
+ _chunkSJRQDWTIcjs.checkPlan.call(void 0, plan);
29
+ _chunkSJRQDWTIcjs.checkCustomer.call(void 0, options);
30
+ class MesubPlanGuard {
31
+ async canActivate(context) {
32
+ const http = context.switchToHttp();
33
+ const request = http.getRequest();
34
+ const client = _nullishCoalesce(options.client, () => ( _chunkSJRQDWTIcjs.defaultClient.call(void 0, )));
35
+ const outcome = await _chunkSJRQDWTIcjs.guard.call(void 0,
36
+ client,
37
+ await _chunkSJRQDWTIcjs.askerOf.call(void 0, request, options.customer),
38
+ () => _chunkSJRQDWTIcjs.plansOf.call(void 0, plan, request)
39
+ );
40
+ if (outcome.allowed) {
41
+ request.mesub = _chunkSJRQDWTIcjs.accessOf.call(void 0, outcome);
42
+ return true;
43
+ }
44
+ const denial = _chunkSJRQDWTIcjs.denialOf.call(void 0, outcome);
45
+ await _optionalChain([options, 'access', _ => _.onDenied, 'optionalCall', _2 => _2(denial, request)]);
46
+ if (outcome.reason === "unavailable") {
47
+ setHeader(http.getResponse(), "Retry-After", _chunkSJRQDWTIcjs.retryAfterOf.call(void 0, outcome));
48
+ }
49
+ throw new (0, _common.HttpException)(_chunkSJRQDWTIcjs.denialBody.call(void 0, outcome), denial.status);
50
+ }
51
+ }
52
+ return _common.mixin.call(void 0, MesubPlanGuard);
53
+ }
54
+ var MesubAccess = _common.createParamDecorator.call(void 0,
55
+ (_data, context) => context.switchToHttp().getRequest().mesub
56
+ );
57
+
58
+
59
+
60
+
61
+ exports.MesubAccess = MesubAccess; exports.MesubError = _chunk4JSJOX35cjs.MesubError; exports.RequirePlan = RequirePlan;
62
+ //# sourceMappingURL=nest.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/node-sdk/node-sdk/dist/nest.cjs","../src/nest.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACfA;AAEI;AAEA;AACA;AAAA,wCAEG;AAkEP,SAAS,SAAA,CAAU,QAAA,EAAsB,IAAA,EAAc,KAAA,EAAe;AAClE,EAAA,GAAA,CAAI,OAAO,QAAA,CAAS,UAAA,IAAc,UAAA,EAAY,QAAA,CAAS,SAAA,CAAU,IAAA,EAAM,KAAK,CAAA;AAAA,EAAA,KAAA,GAAA,CACnE,OAAO,QAAA,CAAS,OAAA,IAAW,UAAA,EAAY,QAAA,CAAS,MAAA,CAAO,IAAA,EAAM,KAAK,CAAA;AAC/E;AAcO,SAAS,WAAA,CACZ,IAAA,EACA,OAAA,EACiB;AACjB,EAAA,yCAAA,IAAc,CAAA;AACd,EAAA,6CAAA,OAAqB,CAAA;AAAA,EAErB,MAAM,eAAsC;AAAA,IACxC,MAAM,WAAA,CAAY,OAAA,EAA6C;AAC3D,MAAA,MAAM,KAAA,EAAO,OAAA,CAAQ,YAAA,CAAa,CAAA;AAClC,MAAA,MAAM,QAAA,EAAU,IAAA,CAAK,UAAA,CAAgB,CAAA;AACrC,MAAA,MAAM,OAAA,mBAAS,OAAA,CAAQ,MAAA,UAAU,6CAAA,GAAc;AAC/C,MAAA,MAAM,QAAA,EAAU,MAAM,qCAAA;AAAA,QAAM,MAAA;AAAA,QAAQ,MAAM,uCAAA,OAAQ,EAAS,OAAA,CAAQ,QAAQ,CAAA;AAAA,QAAG,CAAA,EAAA,GAC1E,uCAAA,IAAQ,EAAM,OAAO;AAAA,MACzB,CAAA;AAEA,MAAA,GAAA,CAAI,OAAA,CAAQ,OAAA,EAAS;AACjB,QAAA,OAAA,CAAQ,MAAA,EAAQ,wCAAA,OAAgB,CAAA;AAEhC,QAAA,OAAO,IAAA;AAAA,MACX;AAEA,MAAA,MAAM,OAAA,EAAS,wCAAA,OAAgB,CAAA;AAE/B,MAAA,sBAAM,OAAA,mBAAQ,QAAA,0BAAA,CAAW,MAAA,EAAQ,OAAO,GAAA;AAExC,MAAA,GAAA,CAAI,OAAA,CAAQ,OAAA,IAAW,aAAA,EAAe;AAClC,QAAA,SAAA,CAAU,IAAA,CAAK,WAAA,CAAwB,CAAA,EAAG,aAAA,EAAe,4CAAA,OAAoB,CAAC,CAAA;AAAA,MAClF;AAEA,MAAA,MAAM,IAAI,0BAAA,CAAc,0CAAA,OAAkB,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA;AAAA,IAC9D;AAAA,EACJ;AAEA,EAAA,OAAO,2BAAA,cAAoB,CAAA;AAC/B;AAGO,IAAM,YAAA,EAAc,0CAAA;AAAA,EACvB,CAAC,KAAA,EAAgB,OAAA,EAAA,GACb,OAAA,CAAQ,YAAA,CAAa,CAAA,CAAE,UAAA,CAAyB,CAAA,CAAE;AAC1D,CAAA;AD5EA;AACE;AACA;AACA;AACF,wHAAC","file":"/home/runner/work/node-sdk/node-sdk/dist/nest.cjs","sourcesContent":[null,"/** `@mesub/node/nest`: `RequirePlan()` and `@MesubAccess()`. */\nimport {\n type CanActivate,\n createParamDecorator,\n type ExecutionContext,\n HttpException,\n mixin,\n type Type,\n} from '@nestjs/common';\n\nimport type { Mesub } from './client.js';\nimport {\n accessOf,\n askerOf,\n checkCustomer,\n checkPlan,\n type CustomerOption,\n type Denial,\n defaultClient,\n denialBody,\n denialOf,\n guard,\n type MesubAccess as Access,\n type PlanOption,\n plansOf,\n retryAfterOf,\n} from './guard.js';\nimport type { HeaderSource } from './webhooks.js';\n\nexport { MesubError } from './errors.js';\nexport type { CustomerOption, Denial, DenialReason, PlanOption } from './guard.js';\nexport type { Asked } from './customer.js';\nexport type { Customer } from './answer.js';\n\n/** Who is asking and what Mesub answered, as `@MesubAccess()` gives it. */\nexport type MesubAccess = Access;\n\n/** An Express or Fastify request, as far as the guard reads and writes it. */\nexport interface MesubRequest {\n headers: HeaderSource;\n /** Set by `RequirePlan` when the request is let through. */\n mesub?: MesubAccess;\n}\n\n/**\n * `Req` is your request as your own auth guard leaves it: name it to read\n * `req.user` in `customer` without a cast,\n * `RequirePlan<AuthedRequest>('pro', { customer: (req) => ... })`.\n */\nexport interface RequirePlanOptions<Req extends MesubRequest = MesubRequest> {\n /** Defaults to one client built from MESUB_API_KEY. */\n client?: Mesub;\n /**\n * Who is asking, from your own auth:\n * `(req) => ({ external_id: req.user.id })`, a wallet or an email. Null when\n * nobody is signed in. It must come from a session you verified, never\n * from the request itself.\n */\n customer: CustomerOption<Req>;\n /**\n * Answer a refusal yourself by throwing your own exception, with your own\n * status and body. It may be async: what it returns is awaited, and a\n * rejection is thrown like a throw. If it returns, the default refusal\n * is thrown.\n */\n onDenied?: (denial: Denial, request: Req) => unknown;\n}\n\n/** Express has `setHeader`, a Fastify reply has `header`. */\ninterface HeaderSink {\n setHeader?: (name: string, value: string) => unknown;\n header?: (name: string, value: string) => unknown;\n}\n\nfunction setHeader(response: HeaderSink, name: string, value: string) {\n if (typeof response.setHeader === 'function') response.setHeader(name, value);\n else if (typeof response.header === 'function') response.header(name, value);\n}\n\n/**\n * A guard letting a request through only for a subscriber with access to that\n * plan: `@UseGuards(RequirePlan('pro', { customer }))` on a controller or a\n * route. The plan is a slug, a list of which any one will do\n * (`['pro', 'team']`), or either worked out per request. `@MesubAccess()` says\n * which one let it through.\n *\n * Who is asking is who `customer` says, from your own auth. Refusals throw an\n * `HttpException` of 401 (nobody signed in), 402 (Mesub said no) or 503 with\n * Retry-After (Mesub unreachable, with no answer known for that subscriber).\n * Integration errors are thrown as they are, for Nest to log and answer 500.\n */\nexport function RequirePlan<Req extends MesubRequest = MesubRequest>(\n plan: PlanOption<Req>,\n options: RequirePlanOptions<Req>,\n): Type<CanActivate> {\n checkPlan(plan);\n checkCustomer(options);\n\n class MesubPlanGuard implements CanActivate {\n async canActivate(context: ExecutionContext): Promise<boolean> {\n const http = context.switchToHttp();\n const request = http.getRequest<Req>();\n const client = options.client ?? defaultClient();\n const outcome = await guard(client, await askerOf(request, options.customer), () =>\n plansOf(plan, request),\n );\n\n if (outcome.allowed) {\n request.mesub = accessOf(outcome);\n\n return true;\n }\n\n const denial = denialOf(outcome);\n\n await options.onDenied?.(denial, request);\n\n if (outcome.reason === 'unavailable') {\n setHeader(http.getResponse<HeaderSink>(), 'Retry-After', retryAfterOf(outcome));\n }\n\n throw new HttpException(denialBody(outcome), denial.status);\n }\n }\n\n return mixin(MesubPlanGuard);\n}\n\n/** The `MesubAccess` that `RequirePlan` left on the request, as a handler parameter. */\nexport const MesubAccess = createParamDecorator(\n (_data: unknown, context: ExecutionContext): MesubAccess | undefined =>\n context.switchToHttp().getRequest<MesubRequest>().mesub,\n);\n"]}
@@ -0,0 +1,57 @@
1
+ import { Type, CanActivate } from '@nestjs/common';
2
+ import { H as HeaderSource, M as Mesub } from './client-BEuDegEY.cjs';
3
+ import { M as MesubAccess$1, P as PlanOption, C as CustomerOption, D as Denial } from './guard-D4AB5HtN.cjs';
4
+ export { A as Asked, a as DenialReason } from './guard-D4AB5HtN.cjs';
5
+ export { M as MesubError } from './errors-DcLfunS-.cjs';
6
+ export { C as Customer } from './subscriptions-B6Lin6i_.cjs';
7
+
8
+ /** `@mesub/node/nest`: `RequirePlan()` and `@MesubAccess()`. */
9
+
10
+ /** An Express or Fastify request, as far as the guard reads and writes it. */
11
+ interface MesubRequest {
12
+ headers: HeaderSource;
13
+ /** Set by `RequirePlan` when the request is let through. */
14
+ mesub?: MesubAccess;
15
+ }
16
+ /**
17
+ * `Req` is your request as your own auth guard leaves it: name it to read
18
+ * `req.user` in `customer` without a cast,
19
+ * `RequirePlan<AuthedRequest>('pro', { customer: (req) => ... })`.
20
+ */
21
+ interface RequirePlanOptions<Req extends MesubRequest = MesubRequest> {
22
+ /** Defaults to one client built from MESUB_API_KEY. */
23
+ client?: Mesub;
24
+ /**
25
+ * Who is asking, from your own auth:
26
+ * `(req) => ({ external_id: req.user.id })`, a wallet or an email. Null when
27
+ * nobody is signed in. It must come from a session you verified, never
28
+ * from the request itself.
29
+ */
30
+ customer: CustomerOption<Req>;
31
+ /**
32
+ * Answer a refusal yourself by throwing your own exception, with your own
33
+ * status and body. It may be async: what it returns is awaited, and a
34
+ * rejection is thrown like a throw. If it returns, the default refusal
35
+ * is thrown.
36
+ */
37
+ onDenied?: (denial: Denial, request: Req) => unknown;
38
+ }
39
+ /**
40
+ * A guard letting a request through only for a subscriber with access to that
41
+ * plan: `@UseGuards(RequirePlan('pro', { customer }))` on a controller or a
42
+ * route. The plan is a slug, a list of which any one will do
43
+ * (`['pro', 'team']`), or either worked out per request. `@MesubAccess()` says
44
+ * which one let it through.
45
+ *
46
+ * Who is asking is who `customer` says, from your own auth. Refusals throw an
47
+ * `HttpException` of 401 (nobody signed in), 402 (Mesub said no) or 503 with
48
+ * Retry-After (Mesub unreachable, with no answer known for that subscriber).
49
+ * Integration errors are thrown as they are, for Nest to log and answer 500.
50
+ */
51
+ declare function RequirePlan<Req extends MesubRequest = MesubRequest>(plan: PlanOption<Req>, options: RequirePlanOptions<Req>): Type<CanActivate>;
52
+ /** Who is asking and what Mesub answered, as `@MesubAccess()` gives it. */
53
+ type MesubAccess = MesubAccess$1;
54
+ /** The `MesubAccess` that `RequirePlan` left on the request, as a handler parameter. */
55
+ declare const MesubAccess: (...dataOrPipes: unknown[]) => ParameterDecorator;
56
+
57
+ export { CustomerOption, Denial, MesubAccess, type MesubRequest, PlanOption, RequirePlan, type RequirePlanOptions };
package/dist/nest.d.ts ADDED
@@ -0,0 +1,57 @@
1
+ import { Type, CanActivate } from '@nestjs/common';
2
+ import { H as HeaderSource, M as Mesub } from './client-CXQLkSAJ.js';
3
+ import { M as MesubAccess$1, P as PlanOption, C as CustomerOption, D as Denial } from './guard-CaXiHMVF.js';
4
+ export { A as Asked, a as DenialReason } from './guard-CaXiHMVF.js';
5
+ export { M as MesubError } from './errors-BN4ZWUfM.js';
6
+ export { C as Customer } from './subscriptions-B6Lin6i_.js';
7
+
8
+ /** `@mesub/node/nest`: `RequirePlan()` and `@MesubAccess()`. */
9
+
10
+ /** An Express or Fastify request, as far as the guard reads and writes it. */
11
+ interface MesubRequest {
12
+ headers: HeaderSource;
13
+ /** Set by `RequirePlan` when the request is let through. */
14
+ mesub?: MesubAccess;
15
+ }
16
+ /**
17
+ * `Req` is your request as your own auth guard leaves it: name it to read
18
+ * `req.user` in `customer` without a cast,
19
+ * `RequirePlan<AuthedRequest>('pro', { customer: (req) => ... })`.
20
+ */
21
+ interface RequirePlanOptions<Req extends MesubRequest = MesubRequest> {
22
+ /** Defaults to one client built from MESUB_API_KEY. */
23
+ client?: Mesub;
24
+ /**
25
+ * Who is asking, from your own auth:
26
+ * `(req) => ({ external_id: req.user.id })`, a wallet or an email. Null when
27
+ * nobody is signed in. It must come from a session you verified, never
28
+ * from the request itself.
29
+ */
30
+ customer: CustomerOption<Req>;
31
+ /**
32
+ * Answer a refusal yourself by throwing your own exception, with your own
33
+ * status and body. It may be async: what it returns is awaited, and a
34
+ * rejection is thrown like a throw. If it returns, the default refusal
35
+ * is thrown.
36
+ */
37
+ onDenied?: (denial: Denial, request: Req) => unknown;
38
+ }
39
+ /**
40
+ * A guard letting a request through only for a subscriber with access to that
41
+ * plan: `@UseGuards(RequirePlan('pro', { customer }))` on a controller or a
42
+ * route. The plan is a slug, a list of which any one will do
43
+ * (`['pro', 'team']`), or either worked out per request. `@MesubAccess()` says
44
+ * which one let it through.
45
+ *
46
+ * Who is asking is who `customer` says, from your own auth. Refusals throw an
47
+ * `HttpException` of 401 (nobody signed in), 402 (Mesub said no) or 503 with
48
+ * Retry-After (Mesub unreachable, with no answer known for that subscriber).
49
+ * Integration errors are thrown as they are, for Nest to log and answer 500.
50
+ */
51
+ declare function RequirePlan<Req extends MesubRequest = MesubRequest>(plan: PlanOption<Req>, options: RequirePlanOptions<Req>): Type<CanActivate>;
52
+ /** Who is asking and what Mesub answered, as `@MesubAccess()` gives it. */
53
+ type MesubAccess = MesubAccess$1;
54
+ /** The `MesubAccess` that `RequirePlan` left on the request, as a handler parameter. */
55
+ declare const MesubAccess: (...dataOrPipes: unknown[]) => ParameterDecorator;
56
+
57
+ export { CustomerOption, Denial, MesubAccess, type MesubRequest, PlanOption, RequirePlan, type RequirePlanOptions };
package/dist/nest.js ADDED
@@ -0,0 +1,62 @@
1
+ import {
2
+ accessOf,
3
+ askerOf,
4
+ checkCustomer,
5
+ checkPlan,
6
+ defaultClient,
7
+ denialBody,
8
+ denialOf,
9
+ guard,
10
+ plansOf,
11
+ retryAfterOf
12
+ } from "./chunk-4AAPR37Y.js";
13
+ import {
14
+ MesubError
15
+ } from "./chunk-NOS4FWWQ.js";
16
+
17
+ // src/nest.ts
18
+ import {
19
+ createParamDecorator,
20
+ HttpException,
21
+ mixin
22
+ } from "@nestjs/common";
23
+ function setHeader(response, name, value) {
24
+ if (typeof response.setHeader === "function") response.setHeader(name, value);
25
+ else if (typeof response.header === "function") response.header(name, value);
26
+ }
27
+ function RequirePlan(plan, options) {
28
+ checkPlan(plan);
29
+ checkCustomer(options);
30
+ class MesubPlanGuard {
31
+ async canActivate(context) {
32
+ const http = context.switchToHttp();
33
+ const request = http.getRequest();
34
+ const client = options.client ?? defaultClient();
35
+ const outcome = await guard(
36
+ client,
37
+ await askerOf(request, options.customer),
38
+ () => plansOf(plan, request)
39
+ );
40
+ if (outcome.allowed) {
41
+ request.mesub = accessOf(outcome);
42
+ return true;
43
+ }
44
+ const denial = denialOf(outcome);
45
+ await options.onDenied?.(denial, request);
46
+ if (outcome.reason === "unavailable") {
47
+ setHeader(http.getResponse(), "Retry-After", retryAfterOf(outcome));
48
+ }
49
+ throw new HttpException(denialBody(outcome), denial.status);
50
+ }
51
+ }
52
+ return mixin(MesubPlanGuard);
53
+ }
54
+ var MesubAccess = createParamDecorator(
55
+ (_data, context) => context.switchToHttp().getRequest().mesub
56
+ );
57
+ export {
58
+ MesubAccess,
59
+ MesubError,
60
+ RequirePlan
61
+ };
62
+ //# sourceMappingURL=nest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nest.ts"],"sourcesContent":["/** `@mesub/node/nest`: `RequirePlan()` and `@MesubAccess()`. */\nimport {\n type CanActivate,\n createParamDecorator,\n type ExecutionContext,\n HttpException,\n mixin,\n type Type,\n} from '@nestjs/common';\n\nimport type { Mesub } from './client.js';\nimport {\n accessOf,\n askerOf,\n checkCustomer,\n checkPlan,\n type CustomerOption,\n type Denial,\n defaultClient,\n denialBody,\n denialOf,\n guard,\n type MesubAccess as Access,\n type PlanOption,\n plansOf,\n retryAfterOf,\n} from './guard.js';\nimport type { HeaderSource } from './webhooks.js';\n\nexport { MesubError } from './errors.js';\nexport type { CustomerOption, Denial, DenialReason, PlanOption } from './guard.js';\nexport type { Asked } from './customer.js';\nexport type { Customer } from './answer.js';\n\n/** Who is asking and what Mesub answered, as `@MesubAccess()` gives it. */\nexport type MesubAccess = Access;\n\n/** An Express or Fastify request, as far as the guard reads and writes it. */\nexport interface MesubRequest {\n headers: HeaderSource;\n /** Set by `RequirePlan` when the request is let through. */\n mesub?: MesubAccess;\n}\n\n/**\n * `Req` is your request as your own auth guard leaves it: name it to read\n * `req.user` in `customer` without a cast,\n * `RequirePlan<AuthedRequest>('pro', { customer: (req) => ... })`.\n */\nexport interface RequirePlanOptions<Req extends MesubRequest = MesubRequest> {\n /** Defaults to one client built from MESUB_API_KEY. */\n client?: Mesub;\n /**\n * Who is asking, from your own auth:\n * `(req) => ({ external_id: req.user.id })`, a wallet or an email. Null when\n * nobody is signed in. It must come from a session you verified, never\n * from the request itself.\n */\n customer: CustomerOption<Req>;\n /**\n * Answer a refusal yourself by throwing your own exception, with your own\n * status and body. It may be async: what it returns is awaited, and a\n * rejection is thrown like a throw. If it returns, the default refusal\n * is thrown.\n */\n onDenied?: (denial: Denial, request: Req) => unknown;\n}\n\n/** Express has `setHeader`, a Fastify reply has `header`. */\ninterface HeaderSink {\n setHeader?: (name: string, value: string) => unknown;\n header?: (name: string, value: string) => unknown;\n}\n\nfunction setHeader(response: HeaderSink, name: string, value: string) {\n if (typeof response.setHeader === 'function') response.setHeader(name, value);\n else if (typeof response.header === 'function') response.header(name, value);\n}\n\n/**\n * A guard letting a request through only for a subscriber with access to that\n * plan: `@UseGuards(RequirePlan('pro', { customer }))` on a controller or a\n * route. The plan is a slug, a list of which any one will do\n * (`['pro', 'team']`), or either worked out per request. `@MesubAccess()` says\n * which one let it through.\n *\n * Who is asking is who `customer` says, from your own auth. Refusals throw an\n * `HttpException` of 401 (nobody signed in), 402 (Mesub said no) or 503 with\n * Retry-After (Mesub unreachable, with no answer known for that subscriber).\n * Integration errors are thrown as they are, for Nest to log and answer 500.\n */\nexport function RequirePlan<Req extends MesubRequest = MesubRequest>(\n plan: PlanOption<Req>,\n options: RequirePlanOptions<Req>,\n): Type<CanActivate> {\n checkPlan(plan);\n checkCustomer(options);\n\n class MesubPlanGuard implements CanActivate {\n async canActivate(context: ExecutionContext): Promise<boolean> {\n const http = context.switchToHttp();\n const request = http.getRequest<Req>();\n const client = options.client ?? defaultClient();\n const outcome = await guard(client, await askerOf(request, options.customer), () =>\n plansOf(plan, request),\n );\n\n if (outcome.allowed) {\n request.mesub = accessOf(outcome);\n\n return true;\n }\n\n const denial = denialOf(outcome);\n\n await options.onDenied?.(denial, request);\n\n if (outcome.reason === 'unavailable') {\n setHeader(http.getResponse<HeaderSink>(), 'Retry-After', retryAfterOf(outcome));\n }\n\n throw new HttpException(denialBody(outcome), denial.status);\n }\n }\n\n return mixin(MesubPlanGuard);\n}\n\n/** The `MesubAccess` that `RequirePlan` left on the request, as a handler parameter. */\nexport const MesubAccess = createParamDecorator(\n (_data: unknown, context: ExecutionContext): MesubAccess | undefined =>\n context.switchToHttp().getRequest<MesubRequest>().mesub,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;AACA;AAAA,EAEI;AAAA,EAEA;AAAA,EACA;AAAA,OAEG;AAkEP,SAAS,UAAU,UAAsB,MAAc,OAAe;AAClE,MAAI,OAAO,SAAS,cAAc,WAAY,UAAS,UAAU,MAAM,KAAK;AAAA,WACnE,OAAO,SAAS,WAAW,WAAY,UAAS,OAAO,MAAM,KAAK;AAC/E;AAcO,SAAS,YACZ,MACA,SACiB;AACjB,YAAU,IAAI;AACd,gBAAc,OAAO;AAAA,EAErB,MAAM,eAAsC;AAAA,IACxC,MAAM,YAAY,SAA6C;AAC3D,YAAM,OAAO,QAAQ,aAAa;AAClC,YAAM,UAAU,KAAK,WAAgB;AACrC,YAAM,SAAS,QAAQ,UAAU,cAAc;AAC/C,YAAM,UAAU,MAAM;AAAA,QAAM;AAAA,QAAQ,MAAM,QAAQ,SAAS,QAAQ,QAAQ;AAAA,QAAG,MAC1E,QAAQ,MAAM,OAAO;AAAA,MACzB;AAEA,UAAI,QAAQ,SAAS;AACjB,gBAAQ,QAAQ,SAAS,OAAO;AAEhC,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,SAAS,OAAO;AAE/B,YAAM,QAAQ,WAAW,QAAQ,OAAO;AAExC,UAAI,QAAQ,WAAW,eAAe;AAClC,kBAAU,KAAK,YAAwB,GAAG,eAAe,aAAa,OAAO,CAAC;AAAA,MAClF;AAEA,YAAM,IAAI,cAAc,WAAW,OAAO,GAAG,OAAO,MAAM;AAAA,IAC9D;AAAA,EACJ;AAEA,SAAO,MAAM,cAAc;AAC/B;AAGO,IAAM,cAAc;AAAA,EACvB,CAAC,OAAgB,YACb,QAAQ,aAAa,EAAE,WAAyB,EAAE;AAC1D;","names":[]}