@akira-io/billing-js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +274 -0
- package/dist/checkout.cjs +10 -0
- package/dist/checkout.cjs.map +1 -0
- package/dist/checkout.d.cts +3 -0
- package/dist/checkout.d.ts +3 -0
- package/dist/checkout.js +8 -0
- package/dist/checkout.js.map +1 -0
- package/dist/client-DpOXhuxx.d.cts +141 -0
- package/dist/client-DpOXhuxx.d.ts +141 -0
- package/dist/client.cjs +179 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +176 -0
- package/dist/client.js.map +1 -0
- package/dist/downloads.cjs +51 -0
- package/dist/downloads.cjs.map +1 -0
- package/dist/downloads.d.cts +34 -0
- package/dist/downloads.d.ts +34 -0
- package/dist/downloads.js +46 -0
- package/dist/downloads.js.map +1 -0
- package/dist/helpers.cjs +116 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +55 -0
- package/dist/helpers.d.ts +55 -0
- package/dist/helpers.js +109 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +439 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +416 -0
- package/dist/index.js.map +1 -0
- package/dist/pricing.cjs +104 -0
- package/dist/pricing.cjs.map +1 -0
- package/dist/pricing.d.cts +15 -0
- package/dist/pricing.d.ts +15 -0
- package/dist/pricing.js +101 -0
- package/dist/pricing.js.map +1 -0
- package/dist/react.cjs +219 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +39 -0
- package/dist/react.d.ts +39 -0
- package/dist/react.js +215 -0
- package/dist/react.js.map +1 -0
- package/dist/types-CH4Vkivj.d.cts +59 -0
- package/dist/types-CH4Vkivj.d.ts +59 -0
- package/dist/vue.cjs +218 -0
- package/dist/vue.cjs.map +1 -0
- package/dist/vue.d.cts +32 -0
- package/dist/vue.d.ts +32 -0
- package/dist/vue.js +214 -0
- package/dist/vue.js.map +1 -0
- package/package.json +113 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Akira
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# @akira-io/billing-js
|
|
2
|
+
|
|
3
|
+
TypeScript client for the [Akira Billing API](https://github.com/akira-foundation/billing).
|
|
4
|
+
Two surfaces:
|
|
5
|
+
|
|
6
|
+
- **Storefront helpers** (`/pricing`, `/downloads`, `/checkout`, `/react`, `/vue`) — browser-safe,
|
|
7
|
+
no secret required. For landing pages, marketing sites, and SPAs that only call
|
|
8
|
+
unauthenticated endpoints.
|
|
9
|
+
- **`BillingClient`** (`/client`) — full HMAC-signed client mirroring the
|
|
10
|
+
[Go](https://github.com/akira-io/billing-sdk-go) and
|
|
11
|
+
[Rust](https://github.com/akira-io/billing-sdk-rust) SDKs. For trusted runtimes that hold a
|
|
12
|
+
`productSecret`: Node servers, Next.js route handlers, Cloudflare Workers, Deno, Bun,
|
|
13
|
+
CLI scripts, controlled webviews. **Never ship the secret to a browser bundle.**
|
|
14
|
+
|
|
15
|
+
Zero runtime dependencies. Dual ESM + CJS. Tree-shakeable per-module entry points.
|
|
16
|
+
|
|
17
|
+
## BillingClient (`/client`)
|
|
18
|
+
|
|
19
|
+
Runtime-agnostic class. Works anywhere `fetch` and `crypto.subtle` exist (Node 18+,
|
|
20
|
+
Bun, Deno, Cloudflare Workers, every modern serverless runtime). Reads the secret
|
|
21
|
+
from your environment, never from `import.meta.env` exposed to a browser bundle.
|
|
22
|
+
|
|
23
|
+
### Serverless route handler — instantiate per request
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { BillingClient } from '@akira-io/billing-js/client';
|
|
27
|
+
|
|
28
|
+
// app/api/login/route.ts (Next.js route handler — also fits Vercel, Netlify, CF Workers)
|
|
29
|
+
export async function POST(req: Request) {
|
|
30
|
+
const client = new BillingClient({
|
|
31
|
+
baseUrl: process.env.AKIRA_BILLING_URL!,
|
|
32
|
+
productSlug: 'unified-dev',
|
|
33
|
+
productSecret: process.env.AKIRA_BILLING_SECRET!,
|
|
34
|
+
});
|
|
35
|
+
const { email, code } = await req.json();
|
|
36
|
+
const result = await client.verifyOtp({ email, code });
|
|
37
|
+
// store result.access_token in a session cookie
|
|
38
|
+
return Response.json(result);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Long-lived server — instantiate once, reuse
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { BillingClient } from '@akira-io/billing-js/client';
|
|
46
|
+
import express from 'express';
|
|
47
|
+
|
|
48
|
+
const billing = new BillingClient({
|
|
49
|
+
baseUrl: process.env.AKIRA_BILLING_URL!,
|
|
50
|
+
productSlug: 'unified-dev',
|
|
51
|
+
productSecret: process.env.AKIRA_BILLING_SECRET!,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const app = express();
|
|
55
|
+
app.post('/login', async (req, res) => {
|
|
56
|
+
const result = await billing.verifyOtp(req.body);
|
|
57
|
+
res.json(result);
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Per-customer token
|
|
62
|
+
|
|
63
|
+
After OTP verify the SDK stores the bearer on the instance. For follow-up
|
|
64
|
+
authenticated calls, either reuse the same client or call `setCustomerToken`:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
client.setCustomerToken(req.cookies.akira_token);
|
|
68
|
+
const me = await client.customerMe();
|
|
69
|
+
const features = await client.entitlements();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Available methods
|
|
73
|
+
|
|
74
|
+
| Method | Endpoint |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `requestOtp(payload)` | `POST /api/auth/customer/otp/request` |
|
|
77
|
+
| `verifyOtp(payload)` | `POST /api/auth/customer/otp/verify` (auto-sets bearer) |
|
|
78
|
+
| `customerMe()` | `GET /api/me` |
|
|
79
|
+
| `licenseCheck(payload)` | `POST /api/licenses/check` |
|
|
80
|
+
| `licenseActivate(payload)` | `POST /api/licenses/activate` |
|
|
81
|
+
| `licenseRefresh(payload)` | `POST /api/licenses/refresh` |
|
|
82
|
+
| `entitlements()` | `GET /api/me/entitlements` |
|
|
83
|
+
| `billingPortal(returnUrl)` | `GET /api/billing/portal` |
|
|
84
|
+
| `trackUsage(payload)` | `POST /api/me/usage` |
|
|
85
|
+
| `publicLicenseKeys()` | `GET /api/v1/license-keys/public` (no HMAC) |
|
|
86
|
+
|
|
87
|
+
### Errors
|
|
88
|
+
|
|
89
|
+
Non-2xx responses throw `BillingApiError` with `status` and `code` fields populated
|
|
90
|
+
from the server error payload.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { BillingApiError } from '@akira-io/billing-js/client';
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await client.licenseActivate({ ... });
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error instanceof BillingApiError && error.code === 'no_active_plan') {
|
|
99
|
+
// redirect to upgrade
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Custom fetch
|
|
106
|
+
|
|
107
|
+
Pass `fetcher` to override `globalThis.fetch` (custom retry, observability, etc):
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
new BillingClient({ baseUrl, productSlug, productSecret, fetcher: myFetch });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
## Install
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pnpm add @akira-io/billing-js
|
|
118
|
+
# or
|
|
119
|
+
npm install @akira-io/billing-js
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Pricing
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { fetchPricing, formatPrice } from '@akira-io/billing-js/pricing';
|
|
126
|
+
|
|
127
|
+
const pricing = await fetchPricing({
|
|
128
|
+
baseUrl: 'https://billing.akira.foundation',
|
|
129
|
+
productKey: 'unified-dev',
|
|
130
|
+
tierMeta: {
|
|
131
|
+
free: { tagline: 'Local dev', highlighted: false, label: 'Free', order: 10, ctaLabel: 'Download' },
|
|
132
|
+
pro: { tagline: 'Unlimited runs', highlighted: true, label: 'Pro', order: 20, ctaLabel: 'Subscribe' },
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
pricing.tiers.forEach((tier) => {
|
|
137
|
+
const monthly = tier.monthly ? formatPrice(tier.monthly.amount, tier.monthly.currency) : '€0';
|
|
138
|
+
console.log(`${tier.name}: ${monthly}/month`);
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The shape of `PricingTier` mirrors what landing pages render: separate `monthly`, `yearly`,
|
|
143
|
+
and `oneTime` slots with the originating `planKey` so you can build a checkout URL from it.
|
|
144
|
+
|
|
145
|
+
## Downloads
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { triggerDownload } from '@akira-io/billing-js/downloads';
|
|
149
|
+
|
|
150
|
+
document.querySelector('#download-arm')!.addEventListener('click', () =>
|
|
151
|
+
triggerDownload({
|
|
152
|
+
baseUrl: 'https://billing.akira.foundation',
|
|
153
|
+
product: 'unified-dev',
|
|
154
|
+
channel: 'stable',
|
|
155
|
+
platform: 'macos-arm64',
|
|
156
|
+
query: { utm_source: 'landing' },
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`triggerDownload`:
|
|
162
|
+
|
|
163
|
+
1. Calls `GET /api/v1/downloads/{product}/{channel}/{platform}` with `Accept: application/json`.
|
|
164
|
+
2. Navigates the current tab to the returned signed URL.
|
|
165
|
+
3. Schedules `navigator.sendBeacon` against the returned `beaconUrl` after a short delay so
|
|
166
|
+
the backend can mark the event as completed.
|
|
167
|
+
|
|
168
|
+
Need more control? `issueDownload` returns the payload without redirecting; `downloadUrl`
|
|
169
|
+
just builds the endpoint URL; `sendCompletionBeacon` ships the beacon on its own.
|
|
170
|
+
|
|
171
|
+
## Checkout
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { checkoutUrl } from '@akira-io/billing-js/checkout';
|
|
175
|
+
|
|
176
|
+
const url = checkoutUrl('https://billing.akira.foundation', 'unified-dev', 'pro_monthly');
|
|
177
|
+
// → https://billing.akira.foundation/subscribe/unified-dev/pro_monthly
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The billing app handles the rest (guest Stripe Checkout session, redirect, webhook).
|
|
181
|
+
|
|
182
|
+
## React hooks (`/react`)
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { usePricing, useDownload } from '@akira-io/billing-js/react';
|
|
186
|
+
import { formatPrice } from '@akira-io/billing-js/pricing';
|
|
187
|
+
|
|
188
|
+
function Pricing() {
|
|
189
|
+
const { data, isLoading, refresh } = usePricing({
|
|
190
|
+
baseUrl: 'https://billing.akira.foundation',
|
|
191
|
+
productKey: 'unified-dev',
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
if (isLoading) return <Skeleton />;
|
|
195
|
+
|
|
196
|
+
return data?.tiers.map((tier) => (
|
|
197
|
+
<Card key={tier.key}>
|
|
198
|
+
<h3>{tier.name}</h3>
|
|
199
|
+
{tier.monthly && <p>{formatPrice(tier.monthly.amount, tier.monthly.currency)}/mo</p>}
|
|
200
|
+
<ul>{tier.features.map((f) => <li key={f.key}>{f.name}</li>)}</ul>
|
|
201
|
+
</Card>
|
|
202
|
+
));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function DownloadButton() {
|
|
206
|
+
const { trigger, isPending } = useDownload({
|
|
207
|
+
baseUrl: 'https://billing.akira.foundation',
|
|
208
|
+
product: 'unified-dev',
|
|
209
|
+
channel: 'stable',
|
|
210
|
+
platform: 'macos-arm64',
|
|
211
|
+
});
|
|
212
|
+
return <button disabled={isPending} onClick={trigger}>{isPending ? 'Starting…' : 'Download'}</button>;
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Vue composables (`/vue`)
|
|
217
|
+
|
|
218
|
+
```vue
|
|
219
|
+
<script setup lang="ts">
|
|
220
|
+
import { usePricing, useDownload } from '@akira-io/billing-js/vue';
|
|
221
|
+
import { formatPrice } from '@akira-io/billing-js/pricing';
|
|
222
|
+
|
|
223
|
+
const { data, isLoading } = usePricing(() => ({
|
|
224
|
+
baseUrl: 'https://billing.akira.foundation',
|
|
225
|
+
productKey: 'unified-dev',
|
|
226
|
+
}));
|
|
227
|
+
|
|
228
|
+
const { trigger, isPending } = useDownload(() => ({
|
|
229
|
+
baseUrl: 'https://billing.akira.foundation',
|
|
230
|
+
product: 'unified-dev',
|
|
231
|
+
channel: 'stable',
|
|
232
|
+
platform: 'macos-arm64',
|
|
233
|
+
}));
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<template>
|
|
237
|
+
<div v-if="isLoading">Loading…</div>
|
|
238
|
+
<div v-else v-for="tier in data?.tiers ?? []" :key="tier.key">
|
|
239
|
+
<h3>{{ tier.name }}</h3>
|
|
240
|
+
<p v-if="tier.monthly">{{ formatPrice(tier.monthly.amount, tier.monthly.currency) }}/mo</p>
|
|
241
|
+
</div>
|
|
242
|
+
<button :disabled="isPending" @click="trigger">{{ isPending ? 'Starting…' : 'Download' }}</button>
|
|
243
|
+
</template>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
React and Vue are listed as **optional peer dependencies** — install only the
|
|
247
|
+
one your app needs. The core modules (`/pricing`, `/downloads`, `/checkout`)
|
|
248
|
+
have no framework dependency.
|
|
249
|
+
|
|
250
|
+
## Bundled types
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import type {
|
|
254
|
+
PricingPayload,
|
|
255
|
+
PricingTier,
|
|
256
|
+
PricingFeature,
|
|
257
|
+
TierMeta,
|
|
258
|
+
IssuedDownload,
|
|
259
|
+
ReleaseChannel,
|
|
260
|
+
AssetPlatform,
|
|
261
|
+
} from '@akira-io/billing-js';
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Development
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
pnpm install
|
|
268
|
+
pnpm test
|
|
269
|
+
pnpm build
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## License
|
|
273
|
+
|
|
274
|
+
MIT.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/checkout.ts
|
|
4
|
+
function checkoutUrl(baseUrl, productKey, planKey) {
|
|
5
|
+
return `${baseUrl.replace(/\/$/, "")}/subscribe/${productKey}/${planKey}`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
exports.checkoutUrl = checkoutUrl;
|
|
9
|
+
//# sourceMappingURL=checkout.cjs.map
|
|
10
|
+
//# sourceMappingURL=checkout.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkout.ts"],"names":[],"mappings":";;;AAAO,SAAS,WAAA,CAAY,OAAA,EAAiB,UAAA,EAAoB,OAAA,EAAyB;AACtF,EAAA,OAAO,CAAA,EAAG,QAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,WAAA,EAAc,UAAU,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAC3E","file":"checkout.cjs","sourcesContent":["export function checkoutUrl(baseUrl: string, productKey: string, planKey: string): string {\n return `${baseUrl.replace(/\\/$/, '')}/subscribe/${productKey}/${planKey}`;\n}\n"]}
|
package/dist/checkout.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkout.ts"],"names":[],"mappings":";AAAO,SAAS,WAAA,CAAY,OAAA,EAAiB,UAAA,EAAoB,OAAA,EAAyB;AACtF,EAAA,OAAO,CAAA,EAAG,QAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,WAAA,EAAc,UAAU,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAC3E","file":"checkout.js","sourcesContent":["export function checkoutUrl(baseUrl: string, productKey: string, planKey: string): string {\n return `${baseUrl.replace(/\\/$/, '')}/subscribe/${productKey}/${planKey}`;\n}\n"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
interface OtpRequestPayload {
|
|
2
|
+
email: string;
|
|
3
|
+
device_fp?: string;
|
|
4
|
+
platform?: string;
|
|
5
|
+
app_version?: string;
|
|
6
|
+
}
|
|
7
|
+
interface OtpVerifyPayload {
|
|
8
|
+
email: string;
|
|
9
|
+
code: string;
|
|
10
|
+
device_fp?: string;
|
|
11
|
+
}
|
|
12
|
+
interface OtpCustomer {
|
|
13
|
+
id: string;
|
|
14
|
+
email: string;
|
|
15
|
+
}
|
|
16
|
+
interface OtpVerifyResponse {
|
|
17
|
+
access_token: string;
|
|
18
|
+
customer: OtpCustomer;
|
|
19
|
+
}
|
|
20
|
+
interface Customer {
|
|
21
|
+
id: string;
|
|
22
|
+
email: string;
|
|
23
|
+
name: string | null;
|
|
24
|
+
trial_ends_at: string | null;
|
|
25
|
+
plan: string | null;
|
|
26
|
+
}
|
|
27
|
+
interface LicenseCheckPayload {
|
|
28
|
+
product: string;
|
|
29
|
+
feature: string;
|
|
30
|
+
}
|
|
31
|
+
interface LicenseCheckResponse {
|
|
32
|
+
allowed: boolean;
|
|
33
|
+
product: string;
|
|
34
|
+
plan: string | null;
|
|
35
|
+
feature: string;
|
|
36
|
+
source: string | null;
|
|
37
|
+
}
|
|
38
|
+
interface LicenseActivatePayload {
|
|
39
|
+
product: string;
|
|
40
|
+
device_type: string;
|
|
41
|
+
platform?: string;
|
|
42
|
+
device_name?: string;
|
|
43
|
+
app_version?: string;
|
|
44
|
+
fingerprint: string;
|
|
45
|
+
}
|
|
46
|
+
interface LicenseRefreshPayload {
|
|
47
|
+
product: string;
|
|
48
|
+
fingerprint: string;
|
|
49
|
+
}
|
|
50
|
+
interface SignedLicense {
|
|
51
|
+
key_id: string;
|
|
52
|
+
algorithm: string;
|
|
53
|
+
payload: string;
|
|
54
|
+
signature: string;
|
|
55
|
+
valid_until: string;
|
|
56
|
+
}
|
|
57
|
+
interface ActivatedDevice {
|
|
58
|
+
id: string;
|
|
59
|
+
type: string;
|
|
60
|
+
slots_used: number;
|
|
61
|
+
slots_limit: number | null;
|
|
62
|
+
}
|
|
63
|
+
interface LicenseActivateResponse {
|
|
64
|
+
allowed: boolean;
|
|
65
|
+
product: string;
|
|
66
|
+
plan: string;
|
|
67
|
+
features: Record<string, boolean>;
|
|
68
|
+
device: ActivatedDevice;
|
|
69
|
+
license: SignedLicense;
|
|
70
|
+
}
|
|
71
|
+
interface EntitlementCustomer {
|
|
72
|
+
id: string;
|
|
73
|
+
email: string;
|
|
74
|
+
name: string | null;
|
|
75
|
+
}
|
|
76
|
+
interface EntitlementsResponse {
|
|
77
|
+
customer: EntitlementCustomer;
|
|
78
|
+
entitlements: unknown;
|
|
79
|
+
devices: unknown;
|
|
80
|
+
}
|
|
81
|
+
interface BillingPortalResponse {
|
|
82
|
+
url: string;
|
|
83
|
+
}
|
|
84
|
+
interface LicensePublicKey {
|
|
85
|
+
key_id: string;
|
|
86
|
+
algorithm: string;
|
|
87
|
+
public_key_base64: string;
|
|
88
|
+
}
|
|
89
|
+
interface LicensePublicKeysResponse {
|
|
90
|
+
keys: LicensePublicKey[];
|
|
91
|
+
active_key_id: string | null;
|
|
92
|
+
}
|
|
93
|
+
interface UsagePayload {
|
|
94
|
+
product: string;
|
|
95
|
+
feature: string;
|
|
96
|
+
date: string;
|
|
97
|
+
device_fp: string;
|
|
98
|
+
action: 'check' | 'increment';
|
|
99
|
+
}
|
|
100
|
+
interface UsageResponse {
|
|
101
|
+
count: number;
|
|
102
|
+
limit: number | null;
|
|
103
|
+
allowed: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface BillingClientConfig {
|
|
107
|
+
baseUrl: string;
|
|
108
|
+
productSlug: string;
|
|
109
|
+
productSecret: string;
|
|
110
|
+
customerToken?: string;
|
|
111
|
+
fetcher?: typeof fetch;
|
|
112
|
+
}
|
|
113
|
+
declare class BillingApiError extends Error {
|
|
114
|
+
status: number;
|
|
115
|
+
code: string;
|
|
116
|
+
constructor(status: number, code: string);
|
|
117
|
+
}
|
|
118
|
+
declare class BillingClient {
|
|
119
|
+
private readonly baseUrl;
|
|
120
|
+
private readonly productSlug;
|
|
121
|
+
private readonly productSecret;
|
|
122
|
+
private customerToken;
|
|
123
|
+
private readonly fetcher;
|
|
124
|
+
constructor(config: BillingClientConfig);
|
|
125
|
+
setCustomerToken(token: string): void;
|
|
126
|
+
requestOtp(payload: OtpRequestPayload): Promise<void>;
|
|
127
|
+
verifyOtp(payload: OtpVerifyPayload): Promise<OtpVerifyResponse>;
|
|
128
|
+
customerMe(): Promise<Customer>;
|
|
129
|
+
licenseCheck(payload: LicenseCheckPayload): Promise<LicenseCheckResponse>;
|
|
130
|
+
licenseActivate(payload: LicenseActivatePayload): Promise<LicenseActivateResponse>;
|
|
131
|
+
licenseRefresh(payload: LicenseRefreshPayload): Promise<LicenseActivateResponse>;
|
|
132
|
+
entitlements(): Promise<EntitlementsResponse>;
|
|
133
|
+
billingPortal(returnUrl: string): Promise<BillingPortalResponse>;
|
|
134
|
+
trackUsage(payload: UsagePayload): Promise<UsageResponse>;
|
|
135
|
+
publicLicenseKeys(): Promise<LicensePublicKeysResponse>;
|
|
136
|
+
private signed;
|
|
137
|
+
private unsigned;
|
|
138
|
+
private parseResponse;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { type ActivatedDevice as A, BillingApiError as B, type Customer as C, type EntitlementCustomer as E, type LicenseActivatePayload as L, type OtpCustomer as O, type SignedLicense as S, type UsagePayload as U, BillingClient as a, type BillingClientConfig as b, type BillingPortalResponse as c, type EntitlementsResponse as d, type LicenseActivateResponse as e, type LicenseCheckPayload as f, type LicenseCheckResponse as g, type LicensePublicKey as h, type LicensePublicKeysResponse as i, type LicenseRefreshPayload as j, type OtpRequestPayload as k, type OtpVerifyPayload as l, type OtpVerifyResponse as m, type UsageResponse as n };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
interface OtpRequestPayload {
|
|
2
|
+
email: string;
|
|
3
|
+
device_fp?: string;
|
|
4
|
+
platform?: string;
|
|
5
|
+
app_version?: string;
|
|
6
|
+
}
|
|
7
|
+
interface OtpVerifyPayload {
|
|
8
|
+
email: string;
|
|
9
|
+
code: string;
|
|
10
|
+
device_fp?: string;
|
|
11
|
+
}
|
|
12
|
+
interface OtpCustomer {
|
|
13
|
+
id: string;
|
|
14
|
+
email: string;
|
|
15
|
+
}
|
|
16
|
+
interface OtpVerifyResponse {
|
|
17
|
+
access_token: string;
|
|
18
|
+
customer: OtpCustomer;
|
|
19
|
+
}
|
|
20
|
+
interface Customer {
|
|
21
|
+
id: string;
|
|
22
|
+
email: string;
|
|
23
|
+
name: string | null;
|
|
24
|
+
trial_ends_at: string | null;
|
|
25
|
+
plan: string | null;
|
|
26
|
+
}
|
|
27
|
+
interface LicenseCheckPayload {
|
|
28
|
+
product: string;
|
|
29
|
+
feature: string;
|
|
30
|
+
}
|
|
31
|
+
interface LicenseCheckResponse {
|
|
32
|
+
allowed: boolean;
|
|
33
|
+
product: string;
|
|
34
|
+
plan: string | null;
|
|
35
|
+
feature: string;
|
|
36
|
+
source: string | null;
|
|
37
|
+
}
|
|
38
|
+
interface LicenseActivatePayload {
|
|
39
|
+
product: string;
|
|
40
|
+
device_type: string;
|
|
41
|
+
platform?: string;
|
|
42
|
+
device_name?: string;
|
|
43
|
+
app_version?: string;
|
|
44
|
+
fingerprint: string;
|
|
45
|
+
}
|
|
46
|
+
interface LicenseRefreshPayload {
|
|
47
|
+
product: string;
|
|
48
|
+
fingerprint: string;
|
|
49
|
+
}
|
|
50
|
+
interface SignedLicense {
|
|
51
|
+
key_id: string;
|
|
52
|
+
algorithm: string;
|
|
53
|
+
payload: string;
|
|
54
|
+
signature: string;
|
|
55
|
+
valid_until: string;
|
|
56
|
+
}
|
|
57
|
+
interface ActivatedDevice {
|
|
58
|
+
id: string;
|
|
59
|
+
type: string;
|
|
60
|
+
slots_used: number;
|
|
61
|
+
slots_limit: number | null;
|
|
62
|
+
}
|
|
63
|
+
interface LicenseActivateResponse {
|
|
64
|
+
allowed: boolean;
|
|
65
|
+
product: string;
|
|
66
|
+
plan: string;
|
|
67
|
+
features: Record<string, boolean>;
|
|
68
|
+
device: ActivatedDevice;
|
|
69
|
+
license: SignedLicense;
|
|
70
|
+
}
|
|
71
|
+
interface EntitlementCustomer {
|
|
72
|
+
id: string;
|
|
73
|
+
email: string;
|
|
74
|
+
name: string | null;
|
|
75
|
+
}
|
|
76
|
+
interface EntitlementsResponse {
|
|
77
|
+
customer: EntitlementCustomer;
|
|
78
|
+
entitlements: unknown;
|
|
79
|
+
devices: unknown;
|
|
80
|
+
}
|
|
81
|
+
interface BillingPortalResponse {
|
|
82
|
+
url: string;
|
|
83
|
+
}
|
|
84
|
+
interface LicensePublicKey {
|
|
85
|
+
key_id: string;
|
|
86
|
+
algorithm: string;
|
|
87
|
+
public_key_base64: string;
|
|
88
|
+
}
|
|
89
|
+
interface LicensePublicKeysResponse {
|
|
90
|
+
keys: LicensePublicKey[];
|
|
91
|
+
active_key_id: string | null;
|
|
92
|
+
}
|
|
93
|
+
interface UsagePayload {
|
|
94
|
+
product: string;
|
|
95
|
+
feature: string;
|
|
96
|
+
date: string;
|
|
97
|
+
device_fp: string;
|
|
98
|
+
action: 'check' | 'increment';
|
|
99
|
+
}
|
|
100
|
+
interface UsageResponse {
|
|
101
|
+
count: number;
|
|
102
|
+
limit: number | null;
|
|
103
|
+
allowed: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface BillingClientConfig {
|
|
107
|
+
baseUrl: string;
|
|
108
|
+
productSlug: string;
|
|
109
|
+
productSecret: string;
|
|
110
|
+
customerToken?: string;
|
|
111
|
+
fetcher?: typeof fetch;
|
|
112
|
+
}
|
|
113
|
+
declare class BillingApiError extends Error {
|
|
114
|
+
status: number;
|
|
115
|
+
code: string;
|
|
116
|
+
constructor(status: number, code: string);
|
|
117
|
+
}
|
|
118
|
+
declare class BillingClient {
|
|
119
|
+
private readonly baseUrl;
|
|
120
|
+
private readonly productSlug;
|
|
121
|
+
private readonly productSecret;
|
|
122
|
+
private customerToken;
|
|
123
|
+
private readonly fetcher;
|
|
124
|
+
constructor(config: BillingClientConfig);
|
|
125
|
+
setCustomerToken(token: string): void;
|
|
126
|
+
requestOtp(payload: OtpRequestPayload): Promise<void>;
|
|
127
|
+
verifyOtp(payload: OtpVerifyPayload): Promise<OtpVerifyResponse>;
|
|
128
|
+
customerMe(): Promise<Customer>;
|
|
129
|
+
licenseCheck(payload: LicenseCheckPayload): Promise<LicenseCheckResponse>;
|
|
130
|
+
licenseActivate(payload: LicenseActivatePayload): Promise<LicenseActivateResponse>;
|
|
131
|
+
licenseRefresh(payload: LicenseRefreshPayload): Promise<LicenseActivateResponse>;
|
|
132
|
+
entitlements(): Promise<EntitlementsResponse>;
|
|
133
|
+
billingPortal(returnUrl: string): Promise<BillingPortalResponse>;
|
|
134
|
+
trackUsage(payload: UsagePayload): Promise<UsageResponse>;
|
|
135
|
+
publicLicenseKeys(): Promise<LicensePublicKeysResponse>;
|
|
136
|
+
private signed;
|
|
137
|
+
private unsigned;
|
|
138
|
+
private parseResponse;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { type ActivatedDevice as A, BillingApiError as B, type Customer as C, type EntitlementCustomer as E, type LicenseActivatePayload as L, type OtpCustomer as O, type SignedLicense as S, type UsagePayload as U, BillingClient as a, type BillingClientConfig as b, type BillingPortalResponse as c, type EntitlementsResponse as d, type LicenseActivateResponse as e, type LicenseCheckPayload as f, type LicenseCheckResponse as g, type LicensePublicKey as h, type LicensePublicKeysResponse as i, type LicenseRefreshPayload as j, type OtpRequestPayload as k, type OtpVerifyPayload as l, type OtpVerifyResponse as m, type UsageResponse as n };
|