@takeal/cusfront-sdk 0.1.0 → 0.2.8
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/CHANGELOG.md +28 -2
- package/README.md +29 -12
- package/dist/{http-BkZZZI8K.d.cts → http-BkCfOCR0.d.cts} +4 -1
- package/dist/{http-BkZZZI8K.d.ts → http-BkCfOCR0.d.ts} +4 -1
- package/dist/index.cjs +150 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -3
- package/dist/index.d.ts +16 -3
- package/dist/index.js +150 -10
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.cts +4 -1
- package/dist/react/index.d.ts +4 -1
- package/dist/resources/auth.cjs +37 -4
- package/dist/resources/auth.cjs.map +1 -1
- package/dist/resources/auth.d.cts +45 -6
- package/dist/resources/auth.d.ts +45 -6
- package/dist/resources/auth.js +37 -4
- package/dist/resources/auth.js.map +1 -1
- package/dist/resources/balance.cjs +4 -3
- package/dist/resources/balance.cjs.map +1 -1
- package/dist/resources/balance.d.cts +8 -9
- package/dist/resources/balance.d.ts +8 -9
- package/dist/resources/balance.js +4 -3
- package/dist/resources/balance.js.map +1 -1
- package/dist/resources/blog.d.cts +1 -1
- package/dist/resources/blog.d.ts +1 -1
- package/dist/resources/branding.cjs.map +1 -1
- package/dist/resources/branding.d.cts +8 -2
- package/dist/resources/branding.d.ts +8 -2
- package/dist/resources/branding.js.map +1 -1
- package/dist/resources/cards.d.cts +1 -1
- package/dist/resources/cards.d.ts +1 -1
- package/dist/resources/deposits.d.cts +1 -1
- package/dist/resources/deposits.d.ts +1 -1
- package/dist/resources/push.cjs +61 -0
- package/dist/resources/push.cjs.map +1 -0
- package/dist/resources/push.d.cts +79 -0
- package/dist/resources/push.d.ts +79 -0
- package/dist/resources/push.js +58 -0
- package/dist/resources/push.js.map +1 -0
- package/dist/resources/sessions.cjs +26 -0
- package/dist/resources/sessions.cjs.map +1 -0
- package/dist/resources/sessions.d.cts +43 -0
- package/dist/resources/sessions.d.ts +43 -0
- package/dist/resources/sessions.js +24 -0
- package/dist/resources/sessions.js.map +1 -0
- package/dist/resources/subscriptions.d.cts +1 -1
- package/dist/resources/subscriptions.d.ts +1 -1
- package/dist/resources/wallet.cjs +24 -0
- package/dist/resources/wallet.cjs.map +1 -0
- package/dist/resources/wallet.d.cts +39 -0
- package/dist/resources/wallet.d.ts +39 -0
- package/dist/resources/wallet.js +22 -0
- package/dist/resources/wallet.js.map +1 -0
- package/dist/telegram.cjs +150 -10
- package/dist/telegram.cjs.map +1 -1
- package/dist/telegram.d.cts +4 -1
- package/dist/telegram.d.ts +4 -1
- package/dist/telegram.js +150 -10
- package/dist/telegram.js.map +1 -1
- package/package.json +22 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,10 +4,36 @@ All notable changes to `@takeal/cusfront-sdk` are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [0.2.8] — 2026-09-13
|
|
8
|
+
|
|
9
|
+
The version number now matches the Takeal platform release the SDK was
|
|
10
|
+
checked against, so this release jumps from 0.1.0 to 0.2.8 (platform tag
|
|
11
|
+
`v0.2.8`).
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **API paths are versioned.** Every request now goes to `/v1/...`
|
|
16
|
+
(`/v1/auth/login`, `/v1/me/deposits`, …); the SDK adds the prefix itself,
|
|
17
|
+
so `baseUrl` stays the bare API origin and resource calls are unchanged.
|
|
18
|
+
Only `/ready` and `/branding` remain unversioned. The API answers the old
|
|
19
|
+
unversioned paths with `410 Gone`, so 0.1.0 no longer works against it.
|
|
20
|
+
- The npm page links to the repository with a plain `https://` URL.
|
|
8
21
|
|
|
9
22
|
### Added
|
|
10
23
|
|
|
24
|
+
- `client.auth.register()` creates an account and signs it in. Takes an
|
|
25
|
+
optional `wallet_currency`.
|
|
26
|
+
- `client.auth.completeTotpSetup()` finishes a `totp_setup_required` login
|
|
27
|
+
and returns the ten one-time backup codes.
|
|
28
|
+
- `client.auth.changePassword()`. The account's other sessions are signed out.
|
|
29
|
+
- `client.sessions`: `list()`, `revoke(jti)` and `revokeOthers()`.
|
|
30
|
+
- `client.push`: `status()`, `save()`, `remove()`, plus `enable(registration)`
|
|
31
|
+
and `disable(registration)`, which subscribe or unsubscribe the browser and
|
|
32
|
+
update the server in one call.
|
|
33
|
+
- Sub-exports `@takeal/cusfront-sdk/wallet`, `/sessions` and `/push`. Auth
|
|
34
|
+
types (`User`, `LoginResponse`, `Session` and the rest) are exported from
|
|
35
|
+
the package root.
|
|
36
|
+
|
|
11
37
|
- `client.blog.list()` / `client.blog.get(slug)` — public posts returned as
|
|
12
38
|
structured blocks (`body_blocks`) plus raw Markdown, so a site renders them
|
|
13
39
|
in its own components instead of fighting server-side HTML.
|
|
@@ -31,7 +57,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
31
57
|
billing fields, issuing metrics, branding). `refresh-types` now scrubs
|
|
32
58
|
internal references from doc comments before generating.
|
|
33
59
|
|
|
34
|
-
## [0.1.0] — first public release
|
|
60
|
+
## [0.1.0] — 2026-08-25 — first public release
|
|
35
61
|
|
|
36
62
|
Initial release of the typed client for the Takeal end-user API.
|
|
37
63
|
|
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @takeal/cusfront-sdk
|
|
2
2
|
|
|
3
|
-
Typed TypeScript client for the **Takeal end-user API
|
|
3
|
+
Typed TypeScript client for the **Takeal end-user API**: sign-up and login, wallet, deposits, cards, sessions, push notifications and webhook signature verification.
|
|
4
4
|
|
|
5
|
-
The SDK powers any
|
|
5
|
+
The SDK powers any end-user client app on top of a Takeal deployment: a PWA, a Capacitor-wrapped mobile app, a Telegram Mini App, or anything else that talks to the `/auth/*` + `/me/*` surface. One client, runtime brand swap, zero runtime deps in the core.
|
|
6
6
|
|
|
7
|
-
> **
|
|
7
|
+
> **Versioning:** the SDK version matches the Takeal platform release it was checked against (SDK 0.2.8 goes with API release v0.2.8). Until 1.0, a minor version can break things; read the [changelog](./CHANGELOG.md) before upgrading.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -42,9 +42,23 @@ if (result.stage === "jwt") {
|
|
|
42
42
|
} else if (result.stage === "totp_required") {
|
|
43
43
|
// Step-up required. Prompt the user for their TOTP code,
|
|
44
44
|
// then call client.auth.verifyTotp({ challenge_token, code }).
|
|
45
|
+
} else if (result.stage === "totp_setup_required") {
|
|
46
|
+
// The account has to enrol an authenticator first. Show result.otpauth_url
|
|
47
|
+
// as a QR code, then call client.auth.completeTotpSetup({ challenge_token, code })
|
|
48
|
+
// and show the backup_codes it returns. They are never sent again.
|
|
45
49
|
}
|
|
46
50
|
```
|
|
47
51
|
|
|
52
|
+
New users sign up with `register`, which also signs them in:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
await client.auth.register({
|
|
56
|
+
email: "user@example.com",
|
|
57
|
+
password: "a-long-Passw0rd",
|
|
58
|
+
wallet_currency: "EUR", // optional; must be offered by the deployment
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
48
62
|
## Telegram Mini App
|
|
49
63
|
|
|
50
64
|
Run inside a Telegram Mini App? Exchange the Telegram-signed `initData` for a
|
|
@@ -96,7 +110,7 @@ you built yourself.
|
|
|
96
110
|
|
|
97
111
|
## Brand config
|
|
98
112
|
|
|
99
|
-
Whitelabel-friendly by design — the SDK ships no embedded brand. Pass `brand` at runtime and the
|
|
113
|
+
Whitelabel-friendly by design — the SDK ships no embedded brand. Pass `brand` at runtime and the client app reads it back via `client.brand`:
|
|
100
114
|
|
|
101
115
|
```ts
|
|
102
116
|
type BrandConfig = {
|
|
@@ -112,8 +126,9 @@ Switching brands does **not** require forking or re-publishing the SDK.
|
|
|
112
126
|
|
|
113
127
|
The deployment also publishes its live brand config at `GET /branding` (public,
|
|
114
128
|
no login needed) — `client.branding.get()` returns `platform_name`,
|
|
115
|
-
`merchant_portal_name`, `logo_url`, `favicon_url
|
|
116
|
-
|
|
129
|
+
`merchant_portal_name`, `logo_url`, `favicon_url`, `wallet_label` and the
|
|
130
|
+
`primary_color` / `secondary_color` / `accent_color` hex values, so a
|
|
131
|
+
client app can re-theme itself at runtime and call the balance whatever the
|
|
117
132
|
operator configured. Server values win over the build-time `brand` when both
|
|
118
133
|
are present.
|
|
119
134
|
|
|
@@ -134,6 +149,9 @@ Available now:
|
|
|
134
149
|
- `@takeal/cusfront-sdk/balance` — `BalanceResource` (per-currency wallet balance).
|
|
135
150
|
- `@takeal/cusfront-sdk/blog` — `BlogResource` (public posts as structured blocks).
|
|
136
151
|
- `@takeal/cusfront-sdk/subscriptions` — `SubscriptionsResource` (announcement channels).
|
|
152
|
+
- `@takeal/cusfront-sdk/wallet` — `WalletResource` (the wallet's currency).
|
|
153
|
+
- `@takeal/cusfront-sdk/sessions` — `SessionsResource` (where the user is signed in).
|
|
154
|
+
- `@takeal/cusfront-sdk/push` — `PushResource` (Web Push subscription).
|
|
137
155
|
- `@takeal/cusfront-sdk/webhooks` — HMAC-SHA256 signature verifier (no network, isomorphic).
|
|
138
156
|
- `@takeal/cusfront-sdk/react` — optional React hooks layer (`ClientProvider` + `useMe` / `useDeposits` / `useCards` / `useBalance`). React is a `peerDependency`, never bundled.
|
|
139
157
|
- `@takeal/cusfront-sdk/telegram` — Telegram Mini App `initData` → authenticated client bridge.
|
|
@@ -158,11 +176,10 @@ if (!ok) return res.status(401).end();
|
|
|
158
176
|
Algorithm: HMAC-SHA256, header `X-Takeal-Signature: sha256=<hex>`, signed over
|
|
159
177
|
the raw body bytes (no timestamp). Comparison is constant-time.
|
|
160
178
|
|
|
161
|
-
> **Card
|
|
162
|
-
>
|
|
163
|
-
>
|
|
164
|
-
> create
|
|
165
|
-
> terminate lifecycle actions.
|
|
179
|
+
> **Card details:** `client.cards.reveal()` returns the full card number and
|
|
180
|
+
> CVV. It asks for the user's password again (and a TOTP code if they have one
|
|
181
|
+
> enrolled), and the API rate-limits and logs every call. The rest of
|
|
182
|
+
> `client.cards` is create, get, list, balance, freeze, unfreeze and terminate.
|
|
166
183
|
|
|
167
184
|
## React hooks (`@takeal/cusfront-sdk/react`)
|
|
168
185
|
|
|
@@ -274,7 +291,7 @@ pnpm typecheck # tsc --noEmit
|
|
|
274
291
|
The OpenAPI snapshot lives at `openapi-snapshot.json` and is committed; refresh it from a running Takeal deployment with:
|
|
275
292
|
|
|
276
293
|
```sh
|
|
277
|
-
curl https://api.your-deployment.example.com/
|
|
294
|
+
curl https://api.your-deployment.example.com/docs/openapi.json > openapi-snapshot.json
|
|
278
295
|
pnpm refresh-types
|
|
279
296
|
```
|
|
280
297
|
|
|
@@ -28,7 +28,10 @@ declare function inMemoryStore(): TokenStore;
|
|
|
28
28
|
* Internal HTTP client. One per SDK instance; injected into each
|
|
29
29
|
* resource. Responsibilities:
|
|
30
30
|
*
|
|
31
|
-
* - Construct absolute URLs from `baseUrl` + path.
|
|
31
|
+
* - Construct absolute URLs from `baseUrl` + API version + path.
|
|
32
|
+
* Resources pass contract paths (`/me/deposits`); the `/v1` prefix is
|
|
33
|
+
* added here, in one place. Only the deployment-level endpoints
|
|
34
|
+
* (`/ready`, `/branding`, …) stay unversioned.
|
|
32
35
|
* - Set `Authorization: Bearer <jwt>` from the `TokenStore`.
|
|
33
36
|
* - Set `Content-Type: application/json` on bodies.
|
|
34
37
|
* - Parse JSON responses + map non-2xx to `ApiError`.
|
|
@@ -28,7 +28,10 @@ declare function inMemoryStore(): TokenStore;
|
|
|
28
28
|
* Internal HTTP client. One per SDK instance; injected into each
|
|
29
29
|
* resource. Responsibilities:
|
|
30
30
|
*
|
|
31
|
-
* - Construct absolute URLs from `baseUrl` + path.
|
|
31
|
+
* - Construct absolute URLs from `baseUrl` + API version + path.
|
|
32
|
+
* Resources pass contract paths (`/me/deposits`); the `/v1` prefix is
|
|
33
|
+
* added here, in one place. Only the deployment-level endpoints
|
|
34
|
+
* (`/ready`, `/branding`, …) stay unversioned.
|
|
32
35
|
* - Set `Authorization: Bearer <jwt>` from the `TokenStore`.
|
|
33
36
|
* - Set `Content-Type: application/json` on bodies.
|
|
34
37
|
* - Parse JSON responses + map non-2xx to `ApiError`.
|
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,15 @@ function isNetworkError(e) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// src/http.ts
|
|
30
|
+
var API_VERSION = "/v1";
|
|
31
|
+
var UNVERSIONED = /* @__PURE__ */ new Set(["/health", "/ready", "/branding", "/favicon.ico"]);
|
|
32
|
+
function versionedPath(path) {
|
|
33
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
34
|
+
const bare = p.split("?")[0];
|
|
35
|
+
if (UNVERSIONED.has(bare)) return p;
|
|
36
|
+
if (bare === API_VERSION || bare.startsWith(`${API_VERSION}/`)) return p;
|
|
37
|
+
return `${API_VERSION}${p}`;
|
|
38
|
+
}
|
|
30
39
|
var HttpClient = class {
|
|
31
40
|
constructor(baseUrl, tokens, fetchImpl) {
|
|
32
41
|
this.baseUrl = baseUrl;
|
|
@@ -83,8 +92,7 @@ var HttpClient = class {
|
|
|
83
92
|
absolute(path) {
|
|
84
93
|
if (path.startsWith("http://") || path.startsWith("https://")) return path;
|
|
85
94
|
const base = this.baseUrl.replace(/\/+$/, "");
|
|
86
|
-
|
|
87
|
-
return `${base}${tail}`;
|
|
95
|
+
return `${base}${versionedPath(path)}`;
|
|
88
96
|
}
|
|
89
97
|
};
|
|
90
98
|
async function parseResponse(resp) {
|
|
@@ -149,6 +157,40 @@ var AuthResource = class {
|
|
|
149
157
|
await Promise.resolve(this.tokens.set(resp.access_token));
|
|
150
158
|
return resp;
|
|
151
159
|
}
|
|
160
|
+
/** Create an end-user account and sign it in. The JWT is stored.
|
|
161
|
+
* `wallet_currency` must be one the deployment offers; omit it to take
|
|
162
|
+
* the deployment default (it can be switched later via `client.wallet`
|
|
163
|
+
* while the wallet is empty).
|
|
164
|
+
* Errors: 400 `validation` / `currency_not_allowed`, 409 email taken. */
|
|
165
|
+
async register(input) {
|
|
166
|
+
const resp = await this.http.post("/auth/register", {
|
|
167
|
+
body: input,
|
|
168
|
+
skipAuth: true
|
|
169
|
+
});
|
|
170
|
+
await Promise.resolve(this.tokens.set(resp.access_token));
|
|
171
|
+
return resp;
|
|
172
|
+
}
|
|
173
|
+
/** Finish a `totp_setup_required` login: send the first code from the
|
|
174
|
+
* authenticator app. The JWT is stored. The response carries ten
|
|
175
|
+
* one-time `backup_codes` that are never returned again, so show them to
|
|
176
|
+
* the user right away and don't keep them on the device. */
|
|
177
|
+
async completeTotpSetup(input) {
|
|
178
|
+
const resp = await this.http.post("/auth/login/totp-setup", {
|
|
179
|
+
body: input,
|
|
180
|
+
skipAuth: true
|
|
181
|
+
});
|
|
182
|
+
await Promise.resolve(this.tokens.set(resp.access_token));
|
|
183
|
+
return resp;
|
|
184
|
+
}
|
|
185
|
+
/** Change the signed-in user's password. Every other session of the
|
|
186
|
+
* account is signed out; this one stays valid.
|
|
187
|
+
* Errors: 400 when the new password fails the policy, 401 when the
|
|
188
|
+
* current one is wrong. */
|
|
189
|
+
async changePassword(input) {
|
|
190
|
+
return this.http.post("/auth/password", {
|
|
191
|
+
body: input
|
|
192
|
+
});
|
|
193
|
+
}
|
|
152
194
|
/** Swap the 2FA method mid-flow. Resolves to `otp_sent` for
|
|
153
195
|
* telegram/email; for TOTP it short-circuits back to the challenge. */
|
|
154
196
|
async switchMethod(input) {
|
|
@@ -185,10 +227,9 @@ var AuthResource = class {
|
|
|
185
227
|
async me() {
|
|
186
228
|
return this.http.get("/auth/me");
|
|
187
229
|
}
|
|
188
|
-
/** Local sign-out.
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* with a future session table. */
|
|
230
|
+
/** Local sign-out: forgets the stored JWT. To end the session on the
|
|
231
|
+
* server as well, revoke it first with `client.sessions.revoke(jti)`
|
|
232
|
+
* (the current one is marked `current: true` in `client.sessions.list()`). */
|
|
192
233
|
async signOut() {
|
|
193
234
|
await Promise.resolve(this.tokens.clear());
|
|
194
235
|
}
|
|
@@ -333,11 +374,12 @@ var BalanceResource = class {
|
|
|
333
374
|
this.http = http;
|
|
334
375
|
}
|
|
335
376
|
/**
|
|
336
|
-
* Fetch the user's wallet balance
|
|
337
|
-
*
|
|
338
|
-
*
|
|
377
|
+
* Fetch the user's wallet balance. Omit `currency` for the wallet's own
|
|
378
|
+
* currency; pass an ISO 4217 code (e.g. `"USD"`) to read another one —
|
|
379
|
+
* the ledger holds a separate balance per currency.
|
|
339
380
|
*/
|
|
340
381
|
async get(currency) {
|
|
382
|
+
if (!currency) return this.http.get("/me/balance");
|
|
341
383
|
const q = new URLSearchParams({ currency }).toString();
|
|
342
384
|
return this.http.get(`/me/balance?${q}`);
|
|
343
385
|
}
|
|
@@ -354,6 +396,25 @@ var BrandingResource = class {
|
|
|
354
396
|
}
|
|
355
397
|
};
|
|
356
398
|
|
|
399
|
+
// src/resources/wallet.ts
|
|
400
|
+
var WalletResource = class {
|
|
401
|
+
constructor(http) {
|
|
402
|
+
this.http = http;
|
|
403
|
+
}
|
|
404
|
+
/** Current wallet currency + the currencies the user may switch to. */
|
|
405
|
+
async get(opts = {}) {
|
|
406
|
+
return this.http.get("/me/wallet", { signal: opts.signal });
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Switch the wallet currency. Fails with `409 wallet_not_empty` while any
|
|
410
|
+
* balance is non-zero, and `400 currency_not_allowed` for a currency the
|
|
411
|
+
* deployment does not offer.
|
|
412
|
+
*/
|
|
413
|
+
async set(currency, opts = {}) {
|
|
414
|
+
return this.http.put("/me/wallet", { body: { currency }, signal: opts.signal });
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
|
|
357
418
|
// src/resources/blog.ts
|
|
358
419
|
var BlogResource = class {
|
|
359
420
|
constructor(http) {
|
|
@@ -407,6 +468,82 @@ var SubscriptionsResource = class {
|
|
|
407
468
|
}
|
|
408
469
|
};
|
|
409
470
|
|
|
471
|
+
// src/resources/sessions.ts
|
|
472
|
+
var SessionsResource = class {
|
|
473
|
+
constructor(http) {
|
|
474
|
+
this.http = http;
|
|
475
|
+
}
|
|
476
|
+
/** All live sessions of the account, this one included. */
|
|
477
|
+
async list() {
|
|
478
|
+
return this.http.get("/me/sessions");
|
|
479
|
+
}
|
|
480
|
+
/** Sign out one session. Works on the current one too; the stored JWT
|
|
481
|
+
* stops working, so follow with `client.auth.signOut()`.
|
|
482
|
+
* 404 when the session is unknown or already signed out. */
|
|
483
|
+
async revoke(jti) {
|
|
484
|
+
await this.http.delete(`/me/sessions/${encodeURIComponent(jti)}`);
|
|
485
|
+
}
|
|
486
|
+
/** Sign out every session except this one. */
|
|
487
|
+
async revokeOthers() {
|
|
488
|
+
return this.http.post("/me/sessions/terminate-others");
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// src/resources/push.ts
|
|
493
|
+
var PushResource = class {
|
|
494
|
+
constructor(http) {
|
|
495
|
+
this.http = http;
|
|
496
|
+
}
|
|
497
|
+
/** Whether the user is subscribed, plus the VAPID key to subscribe with. */
|
|
498
|
+
async status() {
|
|
499
|
+
return this.http.get("/me/push-subscription");
|
|
500
|
+
}
|
|
501
|
+
/** Store a subscription you created yourself.
|
|
502
|
+
* 409 `push_disabled` when the deployment has no VAPID keys. */
|
|
503
|
+
async save(input) {
|
|
504
|
+
return this.http.put("/me/push-subscription", { body: input });
|
|
505
|
+
}
|
|
506
|
+
/** Delete the stored subscription. Safe when nothing is stored. */
|
|
507
|
+
async remove() {
|
|
508
|
+
await this.http.delete("/me/push-subscription");
|
|
509
|
+
}
|
|
510
|
+
/** Subscribe this browser and store the subscription. Ask for
|
|
511
|
+
* notification permission before calling. Throws when push isn't set up
|
|
512
|
+
* on the deployment. */
|
|
513
|
+
async enable(registration) {
|
|
514
|
+
const { vapid_public_key } = await this.status();
|
|
515
|
+
if (!vapid_public_key) {
|
|
516
|
+
throw new Error("@takeal/cusfront-sdk: push notifications are not enabled on this deployment");
|
|
517
|
+
}
|
|
518
|
+
const sub = await registration.pushManager.subscribe({
|
|
519
|
+
userVisibleOnly: true,
|
|
520
|
+
applicationServerKey: base64UrlToBytes(vapid_public_key)
|
|
521
|
+
});
|
|
522
|
+
const json = sub.toJSON();
|
|
523
|
+
if (!json.endpoint || !json.keys?.p256dh || !json.keys.auth) {
|
|
524
|
+
throw new Error("@takeal/cusfront-sdk: the browser returned an incomplete push subscription");
|
|
525
|
+
}
|
|
526
|
+
return this.save({
|
|
527
|
+
endpoint: json.endpoint,
|
|
528
|
+
keys: { p256dh: json.keys.p256dh, auth: json.keys.auth }
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
/** Unsubscribe this browser and delete the stored subscription. */
|
|
532
|
+
async disable(registration) {
|
|
533
|
+
const sub = await registration.pushManager.getSubscription();
|
|
534
|
+
if (sub) await sub.unsubscribe();
|
|
535
|
+
await this.remove();
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
function base64UrlToBytes(input) {
|
|
539
|
+
const b64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
540
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
541
|
+
const bin = atob(padded);
|
|
542
|
+
const out = new Uint8Array(bin.length);
|
|
543
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
544
|
+
return out;
|
|
545
|
+
}
|
|
546
|
+
|
|
410
547
|
// src/token-store.ts
|
|
411
548
|
function defaultBrowserStore(key = "takeal_jwt") {
|
|
412
549
|
const fallback = inMemoryStore();
|
|
@@ -455,9 +592,12 @@ function createClient(opts) {
|
|
|
455
592
|
deposits: new DepositsResource(http),
|
|
456
593
|
cards: new CardsResource(http),
|
|
457
594
|
balance: new BalanceResource(http),
|
|
595
|
+
wallet: new WalletResource(http),
|
|
458
596
|
branding: new BrandingResource(http),
|
|
459
597
|
blog: new BlogResource(http),
|
|
460
|
-
subscriptions: new SubscriptionsResource(http)
|
|
598
|
+
subscriptions: new SubscriptionsResource(http),
|
|
599
|
+
sessions: new SessionsResource(http),
|
|
600
|
+
push: new PushResource(http)
|
|
461
601
|
};
|
|
462
602
|
}
|
|
463
603
|
function pickDefaultStore() {
|