@owlmeans/payment 0.1.18-rc.2 → 0.1.18-rc.20

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 (72) hide show
  1. package/README.md +18 -26
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/payment/SKILL.md +137 -26
  4. package/build/advertise.d.ts +2 -0
  5. package/build/advertise.d.ts.map +1 -0
  6. package/build/advertise.js +11 -0
  7. package/build/advertise.js.map +1 -0
  8. package/build/consts.d.ts +5 -23
  9. package/build/consts.d.ts.map +1 -1
  10. package/build/consts.js +9 -23
  11. package/build/consts.js.map +1 -1
  12. package/build/entitlement.d.ts +61 -0
  13. package/build/entitlement.d.ts.map +1 -0
  14. package/build/entitlement.js +98 -0
  15. package/build/entitlement.js.map +1 -0
  16. package/build/entrypoints.d.ts +25 -0
  17. package/build/entrypoints.d.ts.map +1 -0
  18. package/build/entrypoints.js +43 -0
  19. package/build/entrypoints.js.map +1 -0
  20. package/build/index.d.ts +4 -1
  21. package/build/index.d.ts.map +1 -1
  22. package/build/index.js +4 -1
  23. package/build/index.js.map +1 -1
  24. package/build/model/checkout.d.ts +2 -3
  25. package/build/model/checkout.d.ts.map +1 -1
  26. package/build/model/checkout.js +8 -6
  27. package/build/model/checkout.js.map +1 -1
  28. package/build/model/index.d.ts +1 -0
  29. package/build/model/index.d.ts.map +1 -1
  30. package/build/model/index.js +1 -0
  31. package/build/model/index.js.map +1 -1
  32. package/build/model/plan.d.ts.map +1 -1
  33. package/build/model/plan.js +5 -1
  34. package/build/model/plan.js.map +1 -1
  35. package/build/model/pricing.d.ts +4 -0
  36. package/build/model/pricing.d.ts.map +1 -0
  37. package/build/model/pricing.js +31 -0
  38. package/build/model/pricing.js.map +1 -0
  39. package/build/model/subscription.d.ts +2 -2
  40. package/build/model/subscription.d.ts.map +1 -1
  41. package/build/model/subscription.js +9 -14
  42. package/build/model/subscription.js.map +1 -1
  43. package/build/pricing.d.ts +7 -0
  44. package/build/pricing.d.ts.map +1 -0
  45. package/build/pricing.js +63 -0
  46. package/build/pricing.js.map +1 -0
  47. package/build/types.d.ts +25 -3
  48. package/build/types.d.ts.map +1 -1
  49. package/package.json +13 -11
  50. package/src/advertise.ts +15 -0
  51. package/src/consts.ts +10 -24
  52. package/src/entitlement.ts +125 -0
  53. package/src/entrypoints.ts +57 -0
  54. package/src/index.ts +4 -1
  55. package/src/model/checkout.ts +8 -6
  56. package/src/model/index.ts +1 -0
  57. package/src/model/plan.ts +5 -1
  58. package/src/model/pricing.ts +34 -0
  59. package/src/model/subscription.ts +11 -14
  60. package/src/pricing.ts +87 -0
  61. package/src/types.ts +29 -3
  62. package/tests/entitlement.spec.ts +90 -0
  63. package/tests/pricing.spec.ts +33 -0
  64. package/tests/protocol.spec.ts +51 -0
  65. package/tests/tsconfig.json +11 -0
  66. package/tsconfig.json +6 -1
  67. package/build/.gitkeep +0 -0
  68. package/build/modules.d.ts +0 -3
  69. package/build/modules.d.ts.map +0 -1
  70. package/build/modules.js +0 -18
  71. package/build/modules.js.map +0 -1
  72. package/src/modules.ts +0 -43
package/README.md CHANGED
@@ -1,18 +1,21 @@
1
1
  # @owlmeans/payment
2
2
 
3
- Payment service abstraction — product catalog, subscription management, and Stripe checkout integration.
3
+ Payment contracts and service abstractions for product catalogs, subscriptions, and amount- or
4
+ quantity-priced checkout.
4
5
 
5
6
  ## Overview
6
7
 
7
8
  - `makePaymentService(alias?)` — creates a payment service for context registration
8
9
  - `appendPaymentService(context, alias?)` — registers the payment service in the context
9
10
  - `PaymentService` — interface for products, plans, subscriptions, and checkout session creation
10
- - `CreateCheckoutBody` / `CreateCheckoutResponse` — request/response types for checkout
11
+ - `paymentApi` — immutable protocol declarations for subscription propagation and checkout
12
+ - `CheckoutPricingMode` plus amount/quantity checkout policy schemas and validators
13
+ - `chargeAmountMinor()` — integer-minor-unit processing adjustment calculation
11
14
 
12
15
  ## Installation
13
16
 
14
17
  ```bash
15
- bun add @owlmeans/payment
18
+ bun add @owlmeans/payment@^0.1.18-rc.13
16
19
  ```
17
20
 
18
21
  ## Usage
@@ -20,34 +23,20 @@ bun add @owlmeans/payment
20
23
  Create a checkout session:
21
24
 
22
25
  ```typescript
23
- import type { CreateCheckoutBody, CreateCheckoutResponse } from '@owlmeans/payment'
26
+ import { paymentApi } from '@owlmeans/payment'
24
27
 
25
- const [result] = await ctx.module<ClientModule<CreateCheckoutResponse>>(
26
- paymentApi.service.checkout.session.external.create
28
+ const result = await ctx.entrypoint(
29
+ paymentApi.service.checkout.session.external.create,
27
30
  ).call({
28
31
  body: {
29
32
  productSku: 'vib-tokens',
30
- entityId,
33
+ entitySlug,
31
34
  service: VIB_ALIAS,
35
+ amountMinor: 1_000,
32
36
  successUrl: helper.makeUrl(service)
33
- } satisfies CreateCheckoutBody
34
- })
35
- window.open(result.url, '_blank')
36
- ```
37
-
38
- Handle subscription propagation:
39
-
40
- ```typescript
41
- import { SubscriptionPropagateBody, PlanDuration, SubscriptionStatus } from '@owlmeans/payment'
42
-
43
- const handler = handleBody<SubscriptionPropagateBody>(async (body, context) => {
44
- if (body.status === SubscriptionStatus.Consumable) {
45
- const tokens = body.capabilities?.find(
46
- c => c.scope === PlanDuration.Consumable
47
- )?.permissions.units ?? 0
48
- await ctx.agentToken().topUpTokens(entityId, tokens * 1000)
49
37
  }
50
38
  })
39
+ window.location.assign(result.url)
51
40
  ```
52
41
 
53
42
  ## API
@@ -67,9 +56,11 @@ Creates the payment service.
67
56
 
68
57
  ### Types
69
58
 
70
- - `CreateCheckoutBody` — `{ productSku, entityId, service, successUrl?, cancelUrl? }`
59
+ - `CreateCheckoutBody` — `{ productSku, entitySlug, service, amountMinor?, successUrl?, cancelUrl? }`
71
60
  - `CreateCheckoutResponse` — `{ url: string }`
72
- - `SubscriptionPropagateBody` — extends `PlanSubscription`
61
+ - `AmountCheckoutPolicy` — integer minor-unit bounds, presets, currency, fixed and basis-point adjustments
62
+ - `QuantityCheckoutPolicy` — integer quantity bounds and default
63
+ - `SubscriptionPropagateBody` — propagation wire shape with `entitySlug`, never the stored `entityId`
73
64
  - `PlanSubscription` — `{ sku, entityId, createdAt, status, capabilities? }`
74
65
 
75
66
  ### Enums
@@ -78,6 +69,7 @@ Creates the payment service.
78
69
  - `SubscriptionStatus` — `Active`, `Consumable`, `Canceled`, etc.
79
70
  - `ProductType` — product category enum
80
71
  - `PaymentEntityType` — entity classification enum
72
+ - `CheckoutPricingMode` — `Amount` or `Quantity`
81
73
 
82
74
  ## Related Packages
83
75
 
@@ -91,7 +83,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
91
83
  your project's skill store (`.agents/skills/`):
92
84
 
93
85
  ```sh
94
- npx @owlmeans/agent-skills
86
+ npx @owlmeans/agent-skills@^0.1.18-rc.19
95
87
  ```
96
88
 
97
89
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/payment",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.514Z",
4
+ "version": "0.1.18-rc.20",
5
+ "generatedAt": "2026-09-12T13:51:53.541Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: payment
3
- description: How to use @owlmeans/payment — payment processing types, models, errors, paymentApi service alias for cross-service checkout calls. Auto-invoked when importing payment types or invoking checkout flows.
3
+ description: "How to use @owlmeans/payment — provider-agnostic payment contracts, immutable payment protocols, amount/quantity checkout policies and pricing, catalogue records, and entitlement gates. Auto-invoked when importing payment types or errors, declaring paid routes, or creating checkout."
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,44 +8,155 @@ user-invocable: false
8
8
  # @owlmeans/payment
9
9
 
10
10
  **Layer:** Core
11
- **Install:** `"@owlmeans/payment": "^0.1.18-rc.0"` in `dependencies`
11
+ **Install:** `"@owlmeans/payment": "^0.1.18-rc.20"` in `dependencies`
12
12
 
13
- ## Key Exports
13
+ The contracts half of payments: the catalogue (products, plans, localizations), the subscription
14
+ record, the entitlement grammar, and the entrypoint declarations both sides of a checkout share. It
15
+ talks to no paygate — a server-side integration implements against these, and
16
+ `@owlmeans/client-payment` adapts the same service for a browser.
17
+
18
+ ## Key exports
14
19
 
15
20
  | Export | Description |
16
- |--------|-------------|
17
- | `paymentApi` | Service alias tree for payment endpoints (e.g. `paymentApi.service.checkout.session.external.create`) |
18
- | `Payment`, `Checkout` types | Domain model shapes |
19
- | `paymentModules` | Entrypoint declarations to spread into `appModules` |
20
- | Errors | Typed payment errors |
21
- | Constants | Payment service aliases |
22
- | `model` submodule | Reusable payment models |
23
- | i18n | Translatable error messages |
21
+ |---|---|
22
+ | `makePaymentService(alias?)` · `appendPaymentService(ctx, alias?)` | The catalogue reader, registered under `DEFAULT_ALIAS` / `PAYMENT_SERVICE` (`'payment'`). |
23
+ | `PaymentService` | `product(sku)` · `products()` · `plans(productSku, duration)` · `plan(planSku)` · `allPlans(productSku)` · `localize(lng, entity)` · `shallowAuthentication(token)`. |
24
+ | `paymentApi` | Immutable protocol tree — `paymentApi.subscription.propagate`, `paymentApi.service.checkout.session.external.create`. |
25
+ | `CheckoutPricingMode` | `Amount` for a caller-selected net monetary value; `Quantity` for reusable unit prices. |
26
+ | `AmountCheckoutPolicy` / `QuantityCheckoutPolicy` (+ schemas) | Configured bounds/default/presets and adjustment, or quantity bounds/default. |
27
+ | `assertAmountCheckoutPolicy` / `assertQuantityCheckoutPolicy` / `assertCheckoutAmount` | Startup and request-boundary validation. |
28
+ | `chargeAmountMinor(amount, policy)` | Integer-only gross-up of net amount before tax. |
29
+ | `entitled(params, opts?)` · `ENTITLEMENT_GATE` | Declare on a route that an entrypoint needs a paid capability. |
30
+ | `hasEntitlement(capabilities, param)` · `entitlementList(capabilities)` · `parseEntitlementParam` · `formatEntitlementParam` | The entitlement grammar — pure, and shared by the server gate and the UI. |
31
+ | `CAPABILITY_FEATURE_SCOPE` | `'feature'`, the scope that carries flags. |
32
+ | `Product` · `ProductPlan` · `PlanSubscription` · `Localization` · `LimitConfig` · `CapabilityUsage` | The record shapes, each with a matching `…Schema` for entrypoint body validation. |
33
+ | `CreateCheckoutBody` / `CreateCheckoutResponse` · `SubscriptionPropagateBody` (+ schemas) | The wire shapes of the two calls that cross a service boundary. |
34
+ | `ProductType` · `PlanStatus` · `PlanDuration` · `SubscriptionStatus` · `PaymentEntityType` (+ schemas) | The enumerations. All string-valued, so they survive a config file. |
35
+ | `PRODUCT_RECORD_TYPE` · `PLAN_RECORD_TYPE` · `L10N_RECORD_TYPE` (+ the matching `…_PREFIX`) · `l10nToId` | How catalogue records are typed and addressed in the config resource. |
36
+ | `PaymentError` · `PaygateError` · `UnknownPaygate` · `PaygateMappingError` · `ProductError` · `UnknownProduct` · `UnknownPlan` · `PaymentIdentificationError` · `SubscriptionError` · `UnknownSubscription` | The `ResilientError` family. Importing the package also registers its translated messages. |
37
+
38
+ Subpath: `./utils` — the `Config` / `Context` aliases to type your own context against.
39
+
40
+ ## The catalogue is config, not a table
41
+
42
+ `PaymentService` reads everything through the context's config resource, so a deployment ships its
43
+ catalogue the same way it ships any other configuration:
44
+
45
+ | Record | Id | Type |
46
+ |---|---|---|
47
+ | product | `product:<sku>` | `PRODUCT_RECORD_TYPE` |
48
+ | plan | `plan:<planSku>` | `PLAN_RECORD_TYPE` |
49
+ | localization | `l10nToId(l10n, true)` → `l10n:<entityType>:<sku>:<lng>` | `L10N_RECORD_TYPE` |
50
+
51
+ `product` and `plan` read the record with the config resource's `get`, which **throws
52
+ `UnknownRecordError`** (`@owlmeans/resource`) when the id is absent rather than returning null — so
53
+ that, not `UnknownProduct` / `UnknownPlan`, is what a checkout for a sku outside the catalogue
54
+ raises, and what a caller answering "no such product" catches. `localize` is the opposite: it reads
55
+ with `load`, tries the asked-for language, falls back to the default one, and returns `null` when
56
+ neither exists, because a missing translation is a display problem and never a reason to fail a
57
+ call.
58
+
59
+ ## Entitlements
24
60
 
25
- ## Subpath Exports
61
+ A paid capability is a `PermissionSet` on a plan, a product or a subscription, and one requirement
62
+ is written as a string:
26
63
 
27
- - `./utils` — payment helpers
64
+ [<scope>:]<permission>[>=<n>]
65
+
66
+ `feature:branding--whitelabel` · `renewable:credits>=100` · `production--standalone`
67
+
68
+ - **`@` is deliberately not part of the grammar.** That is `@owlmeans/iam`'s resource-selector
69
+ syntax; reusing it would make two different things look identical in a route declaration.
70
+ - **Keep flags and quotas in different scopes.** `CAPABILITY_FEATURE_SCOPE` carries booleans;
71
+ numeric allowances belong under their own scope. Merged, "has one slot left" and "may remove the
72
+ platform credit" become the same number, and the purchase that spends the quota takes the feature
73
+ with it.
74
+ - **A floor is a numeric question.** `>=n` passes only for a number at least that big — a boolean
75
+ flag, however true, does not answer it.
76
+ - **A malformed parameter answers `false`, it never throws.** A gate that crashed on a typo would
77
+ take down the endpoint it guards, which is strictly worse than refusing the request.
78
+ - **Declare the requirement on the protocol, not in the handler.** `entitled(...)` is sugar over
79
+ the protocol's `gate: { alias: ENTITLEMENT_GATE, params }` option; the framework asserts a gate before the handler is entered, so
80
+ the route table states what a feature costs and no new endpoint can forget to check. Several
81
+ parameters are OR'd, as with every other gate.
82
+ - The gate service itself is not here — bind something under `ENTITLEMENT_GATE` in the server
83
+ application, or every entitled route refuses.
84
+
85
+ ```typescript
86
+ import { entitled, hasEntitlement, entitlementList } from '@owlmeans/payment'
87
+
88
+ // On the protocol:
89
+ protocol(
90
+ route(MY_ROUTE, '/whitelabel', backend(BASE, RouteMethod.POST)),
91
+ contract(typed()),
92
+ { gate: { alias: ENTITLEMENT_GATE, params: ['feature:branding--whitelabel'] } },
93
+ )
94
+
95
+ // In the UI, to render a control disabled rather than let it fail:
96
+ const allowed = hasEntitlement(capabilities, 'renewable:credits>=100')
97
+ // On the wire, as the answer to "what does this subscription grant?":
98
+ const granted = entitlementList(capabilities)
99
+ ```
28
100
 
29
- ## Usage
101
+ ## Checkout
30
102
 
31
- Spread the entrypoints into your app, then call them via `ctx.entrypoint(paymentApi....)`:
103
+ Bind `paymentApi.service` directly in both client and server layers. Call the protocol object; its
104
+ body and response are inferred without a consumer generic. `protocols(paymentApi.service)` is only
105
+ for framework materialization, never a public compatibility export.
32
106
 
33
107
  ```typescript
34
- import { paymentApi, paymentModules } from '@owlmeans/payment'
35
- import type { CreateCheckoutResponse } from '@owlmeans/payment'
36
- import type { ClientEntrypoint } from '@owlmeans/entrypoint'
108
+ import { paymentApi } from '@owlmeans/payment'
109
+ import { bindAll } from '@owlmeans/client-entrypoint'
37
110
 
38
- export const appModules = [...modules, ...paymentModules]
111
+ export const appEntrypoints = [...bindAll(paymentApi.service)]
39
112
 
40
- // In a handler:
41
- const [result] = await ctx.entrypoint<ClientEntrypoint<CreateCheckoutResponse>>(
42
- paymentApi.service.checkout.session.external.create
43
- ).call({
44
- body: { productSku: 'tokens', entityId, service: VIB_ALIAS, successUrl: helper.makeUrl(service) }
113
+ const result = await ctx.entrypoint(paymentApi.service.checkout.session.external.create).call({
114
+ body: { productSku, entitySlug, service, amountMinor, successUrl }
45
115
  })
116
+ window.location.assign(result.url)
46
117
  ```
47
118
 
119
+ `entitySlug` is the only organization value on a public checkout body. A server resolves it to the
120
+ stable `entityId` before persisting a customer/session. `PlanSubscription.entityId` remains an
121
+ internal record key, not an HTTP body convention.
122
+
123
+ ### Amount checkout
124
+
125
+ `amountMinor` is the net value credited to the customer, in integer currency minor units. The
126
+ policy bounds that value; fees and tax do not enlarge the credit. Gross up the pre-tax charge with:
127
+
128
+ ```
129
+ ceil((amountMinor + fixedMinor) * 10_000 / (10_000 - rateBps))
130
+ ```
131
+
132
+ Validate the whole policy when configuration is declared, then validate every selected amount at
133
+ the backend boundary. Minimum, default, maximum, preset entries, fixed adjustment and basis-point
134
+ rate are safe integers; presets are unique/in-range and the rate is below 100%. The maximum applies
135
+ to `amountMinor`, not the adjusted checkout subtotal or Stripe tax-inclusive total.
136
+
137
+ Quantity checkout remains supported. It uses its reusable unit price and quantity policy; do not
138
+ infer a pricing mode from the presence of `amountMinor`.
139
+
140
+ ## One propagation protocol
141
+
142
+ `paymentApi.subscription.propagate` is the one subscription propagation route. Its body carries the
143
+ organization as `entitySlug`; `entityId` belongs only to stored `PlanSubscription` records and
144
+ in-process services. Do not add misspelled aliases or flattened declaration lists as compatibility
145
+ surfaces: a consumer imports and binds the named protocol from the immutable tree.
146
+
147
+ ## `shallowAuthentication` identifies, it does not authorize
148
+
149
+ It reads the `profileId` out of an envelope token WITHOUT verifying the signature, and throws
150
+ `PaymentIdentificationError` when there is no token or no profile in it. Use it to correlate a
151
+ checkout return with a visitor; never as the basis of an access decision — that is a gate's job.
152
+
48
153
  ## Depends On
49
154
 
50
- - `@owlmeans/entrypoint`, `@owlmeans/route`
51
- - `@owlmeans/auth`, `@owlmeans/error`, `@owlmeans/i18n`
155
+ - `@owlmeans/entrypoint` · `@owlmeans/route` · `@owlmeans/config` · `@owlmeans/resource`
156
+ - `@owlmeans/auth` (`PermissionSet`) · `@owlmeans/basic-envelope` · `@owlmeans/context`
157
+ - `@owlmeans/error` · `@owlmeans/i18n` · peer `ajv`
158
+
159
+ ## Related
160
+
161
+ - [[client-payment]] — the browser-side adaptation of the same service
162
+ - [[iam]] — `PermissionSet` and the resource-selector syntax entitlements deliberately avoid
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=advertise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advertise.d.ts","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import { CONFIG_RECORD } from '@owlmeans/context';
2
+ import { apiConfigPlugin, every } from '@owlmeans/api-config';
3
+ import { L10N_RECORD_TYPE, PLAN_RECORD_TYPE, PRODUCT_RECORD_TYPE } from './consts.js';
4
+ const advertisedRecordTypes = new Set([L10N_RECORD_TYPE, PLAN_RECORD_TYPE, PRODUCT_RECORD_TYPE]);
5
+ apiConfigPlugin({
6
+ allow: {
7
+ [CONFIG_RECORD]: every(true, value => value != null && typeof value === 'object'
8
+ && advertisedRecordTypes.has(value.recordType ?? '')),
9
+ },
10
+ });
11
+ //# sourceMappingURL=advertise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advertise.js","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAErF,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAEhG,eAAe,CAAC;IACd,KAAK,EAAE;QACL,CAAC,aAAa,CAAC,EAAE,KAAK,CACpB,IAAI,EACJ,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;eAC9C,qBAAqB,CAAC,GAAG,CAAE,KAAiC,CAAC,UAAU,IAAI,EAAE,CAAC,CACpF;KACF;CACF,CAAC,CAAA"}
package/build/consts.d.ts CHANGED
@@ -4,6 +4,10 @@ export declare enum ProductType {
4
4
  Service = "service",
5
5
  Consumable = "consumable"
6
6
  }
7
+ export declare enum CheckoutPricingMode {
8
+ Quantity = "quantity",
9
+ Amount = "amount"
10
+ }
7
11
  export declare enum PaymentEntityType {
8
12
  Product = "product",
9
13
  Plan = "plan",
@@ -41,6 +45,7 @@ export declare enum SubscriptionStatus {
41
45
  Consumable = "consumable"
42
46
  }
43
47
  export declare const ProductTypeSchema: JSONSchemaType<ProductType>;
48
+ export declare const CheckoutPricingModeSchema: JSONSchemaType<CheckoutPricingMode>;
44
49
  export declare const PaymentEntityTypeSchema: JSONSchemaType<PaymentEntityType>;
45
50
  export declare const PlanStatusSchema: JSONSchemaType<PlanStatus>;
46
51
  export declare const PlanDurationSchema: JSONSchemaType<PlanDuration>;
@@ -56,27 +61,4 @@ export declare const L10N_RECORD_TYPE = "l10n";
56
61
  export declare const L10N_RECORD_PREFIX = "l10n";
57
62
  export declare const DEFAULT_ALIAS = "payment";
58
63
  export declare const PAYMENT_SERVICE = "payment";
59
- export declare const paymentApi: {
60
- subscription: {
61
- base: string;
62
- /**
63
- * @deprecated Use propagate instead
64
- */
65
- propogate: string;
66
- propagate: string;
67
- };
68
- service: {
69
- base: string;
70
- checkout: {
71
- base: string;
72
- session: {
73
- base: string;
74
- external: {
75
- base: string;
76
- create: string;
77
- };
78
- };
79
- };
80
- };
81
- };
82
64
  //# sourceMappingURL=consts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEzC,oBAAY,WAAW;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,UAAU,eAAe;CAC1B;AAED,oBAAY,iBAAiB;IAC3B,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,aAAa,mBAAmB;CACjC;AAED,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,SAAS,cAAc;CACxB;AAED,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB;;;OAGG;IACH,UAAU,eAAe;CAC1B;AAED,oBAAY,kBAAkB;IAC5B,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,UAAU,eAAe;CAC1B;AAED,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,WAAW,CAGzD,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cAAc,CAAC,iBAAiB,CAGrE,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,UAAU,CAGvD,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,YAAY,CAG3D,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,cAAc,CAAC,kBAAkB,CAGvE,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,MAAM,CAErD,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,cAAc,CAAC,MAAM,CAE3D,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,MAAM,CAExD,CAAA;AAED,eAAO,MAAM,mBAAmB,YAAY,CAAA;AAC5C,eAAO,MAAM,qBAAqB,YAAsB,CAAA;AAExD,eAAO,MAAM,gBAAgB,SAAS,CAAA;AACtC,eAAO,MAAM,kBAAkB,SAAmB,CAAA;AAElD,eAAO,MAAM,gBAAgB,SAAS,CAAA;AACtC,eAAO,MAAM,kBAAkB,SAAmB,CAAA;AAElD,eAAO,MAAM,aAAa,YAAY,CAAA;AAEtC,eAAO,MAAM,eAAe,YAAgB,CAAA;AAE5C,eAAO,MAAM,UAAU;IACrB,YAAY;QACV,IAAI;QACJ;;WAEG;QACH,SAAS;QACT,SAAS;;IAEX,OAAO;QACL,IAAI;QACJ,QAAQ;YACN,IAAI;YACJ,OAAO;gBACL,IAAI;gBACJ,QAAQ;oBACN,IAAI;oBACJ,MAAM;;;;;CAKf,CAAA"}
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAEzC,oBAAY,WAAW;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,UAAU,eAAe;CAC1B;AAED,oBAAY,mBAAmB;IAC7B,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,oBAAY,iBAAiB;IAC3B,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,aAAa,mBAAmB;CACjC;AAED,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,SAAS,cAAc;CACxB;AAED,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB;;;OAGG;IACH,UAAU,eAAe;CAC1B;AAED,oBAAY,kBAAkB;IAC5B,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,UAAU,eAAe;CAC1B;AAED,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,WAAW,CAGzD,CAAA;AAED,eAAO,MAAM,yBAAyB,EAAE,cAAc,CAAC,mBAAmB,CAGzE,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cAAc,CAAC,iBAAiB,CAGrE,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,UAAU,CAGvD,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,YAAY,CAG3D,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,cAAc,CAAC,kBAAkB,CAGvE,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,MAAM,CAErD,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,cAAc,CAAC,MAAM,CAE3D,CAAA;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,MAAM,CAExD,CAAA;AAED,eAAO,MAAM,mBAAmB,YAAY,CAAA;AAC5C,eAAO,MAAM,qBAAqB,YAAsB,CAAA;AAExD,eAAO,MAAM,gBAAgB,SAAS,CAAA;AACtC,eAAO,MAAM,kBAAkB,SAAmB,CAAA;AAElD,eAAO,MAAM,gBAAgB,SAAS,CAAA;AACtC,eAAO,MAAM,kBAAkB,SAAmB,CAAA;AAElD,eAAO,MAAM,aAAa,YAAY,CAAA;AAEtC,eAAO,MAAM,eAAe,YAAgB,CAAA"}
package/build/consts.js CHANGED
@@ -4,6 +4,11 @@ export var ProductType;
4
4
  ProductType["Service"] = "service";
5
5
  ProductType["Consumable"] = "consumable";
6
6
  })(ProductType || (ProductType = {}));
7
+ export var CheckoutPricingMode;
8
+ (function (CheckoutPricingMode) {
9
+ CheckoutPricingMode["Quantity"] = "quantity";
10
+ CheckoutPricingMode["Amount"] = "amount";
11
+ })(CheckoutPricingMode || (CheckoutPricingMode = {}));
7
12
  export var PaymentEntityType;
8
13
  (function (PaymentEntityType) {
9
14
  PaymentEntityType["Product"] = "product";
@@ -48,6 +53,10 @@ export const ProductTypeSchema = {
48
53
  type: 'string',
49
54
  enum: Object.values(ProductType)
50
55
  };
56
+ export const CheckoutPricingModeSchema = {
57
+ type: 'string',
58
+ enum: Object.values(CheckoutPricingMode),
59
+ };
51
60
  export const PaymentEntityTypeSchema = {
52
61
  type: 'string',
53
62
  enum: Object.values(PaymentEntityType)
@@ -81,27 +90,4 @@ export const L10N_RECORD_TYPE = 'l10n';
81
90
  export const L10N_RECORD_PREFIX = L10N_RECORD_TYPE;
82
91
  export const DEFAULT_ALIAS = 'payment';
83
92
  export const PAYMENT_SERVICE = DEFAULT_ALIAS;
84
- export const paymentApi = {
85
- subscription: {
86
- base: 'payment-api:subscription',
87
- /**
88
- * @deprecated Use propagate instead
89
- */
90
- propogate: 'payment-api:subscription:propogate',
91
- propagate: 'payment-api:subscription:propagate',
92
- },
93
- service: {
94
- base: 'payment-service:base',
95
- checkout: {
96
- base: 'payment-service:checkout',
97
- session: {
98
- base: 'payment-service:checkout:session',
99
- external: {
100
- base: 'payment-service:checkout:session:external',
101
- create: 'payment-service:checkout:session:external:create',
102
- }
103
- }
104
- }
105
- }
106
- };
107
93
  //# sourceMappingURL=consts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type { EntrypointOptions } from '@owlmeans/entrypoint';
2
+ import type { PermissionSet } from '@owlmeans/auth';
3
+ /**
4
+ * The gate alias a paid capability is asserted under.
5
+ *
6
+ * Distinct from `paymentGate.base` (a ROUTE id) and from the gateway service alias — three
7
+ * different things that would otherwise all be called "payment gate".
8
+ */
9
+ export declare const ENTITLEMENT_GATE = "entitlement-gate";
10
+ /**
11
+ * The capability scope that carries FEATURE flags.
12
+ *
13
+ * Kept apart from `renewable`, which carries numeric quotas that are consumed or counted. Merging
14
+ * them would make "has one production slot left" and "may remove the platform credit" the same
15
+ * number, and the first purchase that spent the quota would take the feature with it.
16
+ */
17
+ export declare const CAPABILITY_FEATURE_SCOPE = "feature";
18
+ export interface EntitlementParam {
19
+ /** Capability scope. Absent means any scope. */
20
+ scope?: string;
21
+ /** The permission key inside `PermissionSet.permissions`. */
22
+ permission: string;
23
+ /** Numeric floor: `credits>=100` passes when the held value is a number at least that big. */
24
+ atLeast?: number;
25
+ }
26
+ /**
27
+ * Grammar: `[<scope>:]<permission>[>=<n>]`.
28
+ *
29
+ * `feature:branding--whitelabel` · `renewable:credits>=100` · `production--standalone`
30
+ *
31
+ * `@` is deliberately not part of it: that is `@owlmeans/iam`'s resource-selector syntax, and a
32
+ * grammar that reused it would make two different things look the same in a route declaration.
33
+ */
34
+ export declare const parseEntitlementParam: (param: string) => EntitlementParam;
35
+ export declare const formatEntitlementParam: (parsed: EntitlementParam) => string;
36
+ /**
37
+ * Whether a union of capability sets satisfies one requirement.
38
+ *
39
+ * Pure, and shared by the server gate and the browser: the UI has to know whether to render a
40
+ * control disabled, and a second implementation of the rule for the client would eventually
41
+ * disagree with the one that actually refuses.
42
+ *
43
+ * A malformed parameter answers `false` rather than throwing. A gate that crashed on a typo would
44
+ * take down the endpoint it guards, which is a strictly worse failure than refusing it.
45
+ */
46
+ export declare const hasEntitlement: (capabilities: PermissionSet[] | undefined, param: string) => boolean;
47
+ /** Everything a union grants, formatted back into parameters. The wire shape of a client read. */
48
+ export declare const entitlementList: (capabilities: PermissionSet[] | undefined) => string[];
49
+ /**
50
+ * Declare that an entrypoint needs a paid capability.
51
+ *
52
+ * Compatibility sugar over the protocol option
53
+ * `{ gate: { alias: ENTITLEMENT_GATE, params } }` so a route reads as what it means. Several
54
+ * parameters are OR'd, matching every other gate in the framework.
55
+ *
56
+ * Putting the requirement HERE rather than in a handler is the point: the framework asserts a gate
57
+ * before the handler is entered, so the route table states what a feature costs and no new
58
+ * endpoint can forget to check.
59
+ */
60
+ export declare const entitled: (params: string | string[], opts?: EntrypointOptions) => EntrypointOptions;
61
+ //# sourceMappingURL=entitlement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlement.d.ts","sourceRoot":"","sources":["../src/entitlement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,YAAY,CAAA;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAA;IAClB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,UAAW,MAAM,KAAG,gBAerD,CAAA;AAED,eAAO,MAAM,sBAAsB,WAAY,gBAAgB,KAAG,MAER,CAAA;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,iBACX,aAAa,EAAE,GAAG,SAAS,SAAS,MAAM,KACvD,OAqBF,CAAA;AAED,kGAAkG;AAClG,eAAO,MAAM,eAAe,iBAAkB,aAAa,EAAE,GAAG,SAAS,KAAG,MAAM,EAYjF,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,WACX,MAAM,GAAG,MAAM,EAAE,SAAS,iBAAiB,KAClD,iBAGD,CAAA"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * The gate alias a paid capability is asserted under.
3
+ *
4
+ * Distinct from `paymentGate.base` (a ROUTE id) and from the gateway service alias — three
5
+ * different things that would otherwise all be called "payment gate".
6
+ */
7
+ export const ENTITLEMENT_GATE = 'entitlement-gate';
8
+ /**
9
+ * The capability scope that carries FEATURE flags.
10
+ *
11
+ * Kept apart from `renewable`, which carries numeric quotas that are consumed or counted. Merging
12
+ * them would make "has one production slot left" and "may remove the platform credit" the same
13
+ * number, and the first purchase that spent the quota would take the feature with it.
14
+ */
15
+ export const CAPABILITY_FEATURE_SCOPE = 'feature';
16
+ /**
17
+ * Grammar: `[<scope>:]<permission>[>=<n>]`.
18
+ *
19
+ * `feature:branding--whitelabel` · `renewable:credits>=100` · `production--standalone`
20
+ *
21
+ * `@` is deliberately not part of it: that is `@owlmeans/iam`'s resource-selector syntax, and a
22
+ * grammar that reused it would make two different things look the same in a route declaration.
23
+ */
24
+ export const parseEntitlementParam = (param) => {
25
+ const [scoped, floor] = param.split('>=');
26
+ const colon = scoped.indexOf(':');
27
+ const parsed = colon >= 0
28
+ ? { scope: scoped.slice(0, colon), permission: scoped.slice(colon + 1) }
29
+ : { permission: scoped };
30
+ if (floor != null) {
31
+ const value = Number.parseFloat(floor);
32
+ if (!Number.isNaN(value)) {
33
+ parsed.atLeast = value;
34
+ }
35
+ }
36
+ return parsed;
37
+ };
38
+ export const formatEntitlementParam = (parsed) => `${parsed.scope != null ? `${parsed.scope}:` : ''}${parsed.permission}` +
39
+ `${parsed.atLeast != null ? `>=${parsed.atLeast}` : ''}`;
40
+ /**
41
+ * Whether a union of capability sets satisfies one requirement.
42
+ *
43
+ * Pure, and shared by the server gate and the browser: the UI has to know whether to render a
44
+ * control disabled, and a second implementation of the rule for the client would eventually
45
+ * disagree with the one that actually refuses.
46
+ *
47
+ * A malformed parameter answers `false` rather than throwing. A gate that crashed on a typo would
48
+ * take down the endpoint it guards, which is a strictly worse failure than refusing it.
49
+ */
50
+ export const hasEntitlement = (capabilities, param) => {
51
+ if (capabilities == null || capabilities.length < 1) {
52
+ return false;
53
+ }
54
+ const { scope, permission, atLeast } = parseEntitlementParam(param);
55
+ if (permission === '') {
56
+ return false;
57
+ }
58
+ return capabilities.some(set => {
59
+ if (scope != null && set.scope !== scope) {
60
+ return false;
61
+ }
62
+ const held = set.permissions?.[permission];
63
+ if (held == null || held === false) {
64
+ return false;
65
+ }
66
+ // A floor is a numeric question: a boolean flag, however true, does not answer it.
67
+ return atLeast != null ? typeof held === 'number' && held >= atLeast : true;
68
+ });
69
+ };
70
+ /** Everything a union grants, formatted back into parameters. The wire shape of a client read. */
71
+ export const entitlementList = (capabilities) => {
72
+ const list = [];
73
+ for (const set of capabilities ?? []) {
74
+ for (const [permission, value] of Object.entries(set.permissions ?? {})) {
75
+ if (value == null || value === false) {
76
+ continue;
77
+ }
78
+ list.push(formatEntitlementParam({ scope: set.scope, permission }));
79
+ }
80
+ }
81
+ return [...new Set(list)];
82
+ };
83
+ /**
84
+ * Declare that an entrypoint needs a paid capability.
85
+ *
86
+ * Compatibility sugar over the protocol option
87
+ * `{ gate: { alias: ENTITLEMENT_GATE, params } }` so a route reads as what it means. Several
88
+ * parameters are OR'd, matching every other gate in the framework.
89
+ *
90
+ * Putting the requirement HERE rather than in a handler is the point: the framework asserts a gate
91
+ * before the handler is entered, so the route table states what a feature costs and no new
92
+ * endpoint can forget to check.
93
+ */
94
+ export const entitled = (params, opts) => ({
95
+ ...opts,
96
+ gate: { alias: ENTITLEMENT_GATE, params },
97
+ });
98
+ //# sourceMappingURL=entitlement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlement.js","sourceRoot":"","sources":["../src/entitlement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /** Public payment protocols. Alias strings stay private to this declaration module. */
2
+ export declare const paymentApi: {
3
+ readonly subscription: {
4
+ readonly base: import("@owlmeans/entrypoint").EntrypointProtocol<{}, undefined>;
5
+ readonly propagate: import("@owlmeans/entrypoint").EntrypointProtocol<{
6
+ body: import("./types.js").SubscriptionPropagateBody;
7
+ }, undefined>;
8
+ };
9
+ readonly service: {
10
+ readonly base: import("@owlmeans/entrypoint").EntrypointProtocol<{}, undefined>;
11
+ readonly checkout: {
12
+ readonly base: import("@owlmeans/entrypoint").EntrypointProtocol<{}, undefined>;
13
+ readonly session: {
14
+ readonly base: import("@owlmeans/entrypoint").EntrypointProtocol<{}, undefined>;
15
+ readonly external: {
16
+ readonly base: import("@owlmeans/entrypoint").EntrypointProtocol<{}, undefined>;
17
+ readonly create: import("@owlmeans/entrypoint").EntrypointProtocol<{
18
+ body: import("./types.js").CreateCheckoutBody;
19
+ }, import("./types.js").CreateCheckoutResponse>;
20
+ };
21
+ };
22
+ };
23
+ };
24
+ };
25
+ //# sourceMappingURL=entrypoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AA+BA,uFAAuF;AACvF,eAAO,MAAM,UAAU;aACrB,YAAY;iBACV,IAAI;iBACJ,SAAS;;;;aAKX,OAAO;iBACL,IAAI;iBACJ,QAAQ;qBACN,IAAI;qBACJ,OAAO;yBACL,IAAI;yBACJ,QAAQ;6BACN,IAAI;6BACJ,MAAM;;;;;;;CAQN,CAAA"}