@vuoma/sdk 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +179 -47
- package/package.json +25 -6
- package/src/index.d.ts +64 -3
- package/src/index.js +87 -13
- package/src/member-contracts.js +98 -0
- package/src/organization-contracts.generated.d.ts +31 -0
- package/src/organization-contracts.generated.js +1343 -0
- package/src/organization.d.ts +23 -0
- package/src/organization.js +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Vuoma Connected Application License
|
|
2
|
+
Version 1.0 — October 19, 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 UPPP LLC, doing business as Vuoma.
|
|
5
|
+
|
|
6
|
+
Permission is granted, without a separate software license fee, to use, copy,
|
|
7
|
+
modify and distribute this package and its documentation (the Software) solely
|
|
8
|
+
to develop, test, operate and distribute applications that integrate with the
|
|
9
|
+
Vuoma service through authorized Vuoma APIs. This includes commercial,
|
|
10
|
+
studio-branded applications, websites, and development or test versions using
|
|
11
|
+
mocked Vuoma responses. You may share the Software with your developers and
|
|
12
|
+
contractors for these purposes and include it in source or compiled application
|
|
13
|
+
distributions, subject to this license.
|
|
14
|
+
|
|
15
|
+
You must retain this license and the copyright notice in copies or substantial
|
|
16
|
+
portions of the Software, including an application's third-party notices. Your
|
|
17
|
+
modifications must remain subject to these permitted-use limits. You may not
|
|
18
|
+
use or distribute the Software as a general-purpose library for applications
|
|
19
|
+
unconnected to Vuoma, or to implement or operate a replacement for the Vuoma
|
|
20
|
+
service, without separate written permission from UPPP LLC.
|
|
21
|
+
|
|
22
|
+
This license applies only to the Software included in this package. It does
|
|
23
|
+
not license Vuoma's backend, databases, customer data, studio branding,
|
|
24
|
+
third-party assets or trademarks. Separately identified third-party software
|
|
25
|
+
remains subject to its own license. You retain any rights you otherwise hold
|
|
26
|
+
in your application code and content.
|
|
27
|
+
|
|
28
|
+
This license does not grant API credentials, access to any account or data,
|
|
29
|
+
hosting, support, or a right to continued service. Access to Vuoma remains
|
|
30
|
+
subject to applicable service agreements, permissions and charges. Ending
|
|
31
|
+
service does not transfer the backend or authorize continued API access. You
|
|
32
|
+
may retain archival copies and use the Software in development intended for an
|
|
33
|
+
authorized Vuoma integration; operating it for an unrelated replacement service
|
|
34
|
+
requires separate permission.
|
|
35
|
+
|
|
36
|
+
All rights not expressly granted are reserved. Use outside these terms is not
|
|
37
|
+
licensed. This is a source-available, restricted-use license, not an open-source
|
|
38
|
+
license. Separate written agreements with UPPP LLC may grant additional rights.
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
41
|
+
IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
42
|
+
NONINFRINGEMENT. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE COPYRIGHT HOLDER
|
|
43
|
+
IS NOT LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE
|
|
44
|
+
SOFTWARE OR ITS USE. Nothing in this license limits liability or rights that
|
|
45
|
+
cannot lawfully be limited.
|
package/README.md
CHANGED
|
@@ -3,29 +3,30 @@
|
|
|
3
3
|
Framework-neutral JavaScript and TypeScript client for the existing Vuoma v1
|
|
4
4
|
public organization and member account APIs. Works with a host-provided Fetch
|
|
5
5
|
implementation; it imports no React, Svelte, Expo or Supabase runtime. The package
|
|
6
|
-
does not store credentials, read environment variables,
|
|
7
|
-
|
|
6
|
+
does not store credentials, read environment variables, or grant access. Account
|
|
7
|
+
setup and booking use the same reviewed organization-member API methods as the
|
|
8
|
+
Vuoma native apps. Server authorization and studio policies remain authoritative.
|
|
9
|
+
Install the public package in your own application; access to Vuoma's private
|
|
10
|
+
repository is not required:
|
|
8
11
|
|
|
9
12
|
```sh
|
|
10
|
-
npm install @vuoma/sdk@0.
|
|
13
|
+
npm install @vuoma/sdk@0.2.1
|
|
11
14
|
```
|
|
12
15
|
|
|
13
|
-
Use SvelteKit and SvelteKit UI with `@vuoma/
|
|
14
|
-
and same-origin server sessions. Use React Native
|
|
16
|
+
Use SvelteKit and SvelteKit UI with `@vuoma/svelte` for website account components
|
|
17
|
+
and same-origin server sessions. Use `@vuoma/react-native-ui` for React Native account and booking UI and this SDK as
|
|
15
18
|
its framework-neutral API transport. The complete `@vuoma/react-native` studio
|
|
16
19
|
app core remains a private workspace; independent apps do not depend on it.
|
|
17
20
|
The public setup guide is at `/developers` and `/o/<organization_slug>/developers`
|
|
18
21
|
on the same combined Vuoma application and landing-page deployment. The current
|
|
19
|
-
origin is `https://vuoma.
|
|
20
|
-
cutover and exact-origin configuration have been verified.
|
|
22
|
+
verified API origin is `https://vuoma.com`.
|
|
21
23
|
|
|
22
24
|
```js
|
|
23
25
|
import { createVuomaClient } from '@vuoma/sdk'
|
|
24
26
|
|
|
25
27
|
const vuoma = createVuomaClient({
|
|
26
|
-
apiOrigin: 'https://vuoma.
|
|
28
|
+
apiOrigin: 'https://vuoma.com', // Use your verified Vuoma origin.
|
|
27
29
|
organizationSlug: 'your-studio',
|
|
28
|
-
appKey: publishableAppKey, // The organization's registered vuoma_pk_ app key.
|
|
29
30
|
fetch: globalThis.fetch,
|
|
30
31
|
})
|
|
31
32
|
|
|
@@ -37,12 +38,11 @@ const schedule = await vuoma.public.getSchedule({
|
|
|
37
38
|
})
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
The
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
binding. Schedule timestamps are normalized to
|
|
41
|
+
The organization slug is public routing configuration, built into each studio app.
|
|
42
|
+
Sign-in authenticates a person for that studio. Private calls require their bearer
|
|
43
|
+
token; the server verifies the live session, studio membership and permissions.
|
|
44
|
+
Public schedule and catalog reads need no registration or app key.
|
|
45
|
+
Schedule timestamps are normalized to
|
|
46
46
|
UTC, and ranges must be positive and at most 63 days. The response preserves
|
|
47
47
|
`schedule.has_more`; when it is true, split the requested range and fetch each
|
|
48
48
|
part rather than displaying the first response as a complete schedule.
|
|
@@ -57,9 +57,8 @@ server or native host; it does not establish a browser cookie session.
|
|
|
57
57
|
```js
|
|
58
58
|
let session = null // Example in-memory host state; no SDK persistence.
|
|
59
59
|
const vuoma = createVuomaClient({
|
|
60
|
-
apiOrigin: 'https://vuoma.
|
|
60
|
+
apiOrigin: 'https://vuoma.com',
|
|
61
61
|
organizationSlug: 'your-studio',
|
|
62
|
-
appKey: publishableAppKey,
|
|
63
62
|
tokenAdapter: { getSession: () => session },
|
|
64
63
|
})
|
|
65
64
|
|
|
@@ -82,11 +81,8 @@ Native, keep refresh tokens in Keychain/Keystore through a secure-storage adapte
|
|
|
82
81
|
keep access tokens in memory, and refresh through the documented member route.
|
|
83
82
|
Refresh scheduling, retries and persistence remain host responsibilities.
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
or replacing an app key does not restore those sessions: remove the rejected
|
|
88
|
-
session from your host adapter and require a fresh member sign-in. The SDK does
|
|
89
|
-
not retry authorization failures or silently change registrations.
|
|
84
|
+
Existing signed-in sessions remain valid while the native app-key system is removed.
|
|
85
|
+
Authorization failures do not trigger SDK retries or change the host session.
|
|
90
86
|
|
|
91
87
|
The SDK uses `credentials: 'omit'`, prevents redirects, and sends member access
|
|
92
88
|
tokens only to its exact configured origin and organization. It rejects missing,
|
|
@@ -103,19 +99,109 @@ business/financial validation, and do not replace the server's authorization or
|
|
|
103
99
|
canonical schemas. The configured response byte limit is checked after reading
|
|
104
100
|
the response text and against a supplied Content-Length header.
|
|
105
101
|
|
|
102
|
+
## Signup, activation and password reset
|
|
103
|
+
|
|
104
|
+
Email confirmation and password creation stay within the host UI; the person
|
|
105
|
+
reads the complete code in their email app. The client accepts the supported
|
|
106
|
+
six- and eight-digit codes and preserves leading zeroes. No access token, cookie or API key
|
|
107
|
+
is sent by these methods. For new or automatically resolved accounts, collect a
|
|
108
|
+
display name. Choose `auto` to let verified email ownership resolve a new profile,
|
|
109
|
+
an imported profile or an existing studio account; `activate` performs the same
|
|
110
|
+
verified resolution without collecting a new name. `new` and `migrate` retain
|
|
111
|
+
the dedicated signup confirmation path. Recovery uses its own code path.
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
await vuoma.auth.requestAccountCode({
|
|
115
|
+
mode: 'signup', signupIntent: 'auto', email, displayName,
|
|
116
|
+
})
|
|
117
|
+
const capability = await vuoma.auth.confirmAccountCode({
|
|
118
|
+
mode: 'signup', signupIntent: 'auto', email, code,
|
|
119
|
+
})
|
|
120
|
+
// The resolution contains only the verified display name and masked contacts.
|
|
121
|
+
const resolution = capability.account_resolution
|
|
122
|
+
await vuoma.auth.completePassword({ capability, password })
|
|
123
|
+
session = await vuoma.auth.signIn({ email, password })
|
|
124
|
+
|
|
125
|
+
// Password reset uses the same scoped completion step.
|
|
126
|
+
await vuoma.auth.requestAccountCode({ mode: 'recovery', email })
|
|
127
|
+
const reset = await vuoma.auth.confirmAccountCode({ mode: 'recovery', email, code })
|
|
128
|
+
await vuoma.auth.completePassword({ capability: reset, password: newPassword })
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Keep password capabilities in memory and scoped to their original studio. They
|
|
132
|
+
are not login tokens. A `VuomaApiError` with status `400` and code
|
|
133
|
+
`weak_password_retry` lets the person choose a stronger password using the same
|
|
134
|
+
capability. Other failures retain their HTTP status and safe machine code; raw
|
|
135
|
+
backend messages and credentials are never reflected in SDK error messages.
|
|
136
|
+
|
|
137
|
+
## Class and appointment booking
|
|
138
|
+
|
|
139
|
+
Every mutation executes **once**. Create a `source_request_id` before submission
|
|
140
|
+
and retain it with the exact payload until the outcome is confirmed. A timeout,
|
|
141
|
+
abort or invalid response may follow a committed mutation. Retrying the same
|
|
142
|
+
class payload with the same ID uses the server's existing idempotency boundary;
|
|
143
|
+
do not generate a new ID to recover an uncertain result. Availability, credits,
|
|
144
|
+
prices, cancellation policies and current authorization are rechecked by Vuoma.
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
const bookingRequest = {
|
|
148
|
+
service_session_id: selectedSession.id,
|
|
149
|
+
source_request_id: crypto.randomUUID(),
|
|
150
|
+
// entitlement_id is optional; the server can select an eligible benefit.
|
|
151
|
+
}
|
|
152
|
+
const receipt = await vuoma.member.bookClass(bookingRequest)
|
|
153
|
+
const terms = await vuoma.member.getCancellationQuote(receipt.booking.id)
|
|
154
|
+
// Present terms and collect confirmation before this call.
|
|
155
|
+
await vuoma.member.cancelBooking(receipt.booking.id, {
|
|
156
|
+
expectedFeeAmount: terms.quote.fee_amount,
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
When required by the studio, class requests also supply the complete existing
|
|
161
|
+
policy acceptance: `policy_version`, `policy_consent: true`,
|
|
162
|
+
`payment_authorized: true` and `payment_authorization_id`. Never invent consent
|
|
163
|
+
or a card authorization; payment/card setup is outside these methods. A
|
|
164
|
+
`booking_cancellation_quote_changed` response requires fetching and presenting
|
|
165
|
+
fresh terms before another cancellation attempt. `cancelBooking` also cancels an
|
|
166
|
+
individual appointment booking through the same reviewed API.
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
const bookingCatalog = await vuoma.public.getBookingCatalog()
|
|
170
|
+
const availability = await vuoma.public.getAppointmentAvailability({ from, to })
|
|
171
|
+
// If has_more is true, split the range and load both halves before presenting it
|
|
172
|
+
// as complete. Availability accepts half-open ranges spanning at most 14 days.
|
|
173
|
+
const visitRequest = {
|
|
174
|
+
source_request_id: crypto.randomUUID(),
|
|
175
|
+
appointments: selectedSlots.map(({ service_offering_id, starts_at, ends_at, credit_cost }) =>
|
|
176
|
+
({ service_offering_id, starts_at, ends_at, credit_cost })),
|
|
177
|
+
}
|
|
178
|
+
const visit = await vuoma.member.bookAppointmentVisit(visitRequest)
|
|
179
|
+
// After an uncertain result, read the original receipt before resubmitting.
|
|
180
|
+
const recovered = await vuoma.member.getAppointmentVisit(visitRequest)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Visits contain 1–10 ordered, non-overlapping appointments. Submission and
|
|
184
|
+
reconciliation validate the request ID, each selected offering/time/credit cost,
|
|
185
|
+
receipt totals and unique booking/session IDs. A status `404` alone does not
|
|
186
|
+
prove an earlier in-flight submission cannot finish; retain the saved payload
|
|
187
|
+
and recover/resubmit only with that same ID. The SDK does not persist pending
|
|
188
|
+
requests, retry mutations or decide when to clear recovery state.
|
|
189
|
+
|
|
190
|
+
Native hosts that keep an access token separately from customer profile data may
|
|
191
|
+
supply `bookingTokenAdapter: { getCredential: () => ({ organization_slug,
|
|
192
|
+
access_token }) }` instead of `tokenAdapter`. Return the **current** credential or
|
|
193
|
+
`null`, so completion after sign-out/account change is rejected. This adapter
|
|
194
|
+
supports only class/visit/quote/cancellation methods, rejects platform-account
|
|
195
|
+
and integration credentials, and does not authorize profile or commerce reads.
|
|
196
|
+
The complete member session adapter is preferred when available. Existing
|
|
197
|
+
Vuoma platform-account flows remain a separate private authority path.
|
|
198
|
+
|
|
106
199
|
## Keys and client IDs
|
|
107
200
|
|
|
108
|
-
- **Publishable Vuoma app keys** have the exact format `vuoma_pk_` followed by
|
|
109
|
-
32 lowercase hexadecimal characters. They may be included in an app bundle
|
|
110
|
-
and identify its organization registration. The SDK sends them only in
|
|
111
|
-
`X-Vuoma-App-Key` to its configured origin, never in `Authorization`, a URL
|
|
112
|
-
or a request body. They do not sign a customer in or grant private access;
|
|
113
|
-
member access/refresh tokens and the server's live app/session checks remain
|
|
114
|
-
required. Confidential organization or Supabase service keys are rejected
|
|
115
|
-
as `appKey` values.
|
|
116
201
|
- **Organization integration/delegated API keys** are confidential server
|
|
117
|
-
credentials.
|
|
118
|
-
|
|
202
|
+
credentials. Keep them on an integration server and outside website bundles,
|
|
203
|
+
native binaries, URLs and the member client's session adapter. Use the separate
|
|
204
|
+
organization client below for supported scoped API reads.
|
|
119
205
|
- **Registered OAuth client IDs** are public app identifiers. Existing shared
|
|
120
206
|
sign-in grants only `openid`, `profile` and `email`; those identity tokens do
|
|
121
207
|
not authorize this SDK's member account methods.
|
|
@@ -125,26 +211,72 @@ the response text and against a supplied Content-Length header.
|
|
|
125
211
|
Platform-account sessions are a separate boundary and are intentionally not
|
|
126
212
|
accepted by this member client.
|
|
127
213
|
|
|
128
|
-
This package adds no OAuth grant
|
|
129
|
-
|
|
130
|
-
|
|
214
|
+
This package adds no OAuth grant or backend permission. Vuoma's member routes
|
|
215
|
+
allow cross-origin requests with explicit bearer credentials and no cookies.
|
|
216
|
+
Browser cookie sessions use the website's same-origin backend adapter. Live user
|
|
217
|
+
sessions and studio permissions are enforced by the API; a studio slug never
|
|
131
218
|
authorizes private account data.
|
|
132
219
|
|
|
133
|
-
Supported routes
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
220
|
+
Supported routes include public `/api/v1/o/{slug}/member/{bootstrap,schedule,catalog,booking-catalog,availability}`;
|
|
221
|
+
organization Auth `/api/v1/o/{slug}/auth/{sign-in,refresh,sign-out,sign-up,recovery,password}`
|
|
222
|
+
and the reviewed `sign-up`, `account` and `recovery` `confirm-code` endpoints;
|
|
223
|
+
member profile GET (`/me/profile?view=basic`), PATCH `/me/profile`, GET `/me/commerce`,
|
|
224
|
+
POST `/me/commerce/bookings`, booking `cancellation-quote`/`cancel`, and
|
|
225
|
+
POST/GET `/me/commerce/visits` with receipt lookup by request ID.
|
|
226
|
+
Payments, uploads, staff administration and platform-account authentication
|
|
227
|
+
remain outside this member client.
|
|
228
|
+
|
|
229
|
+
## Contract-generated organization operations
|
|
230
|
+
|
|
231
|
+
The server-side `@vuoma/sdk/organization` entry point accepts a confidential
|
|
232
|
+
scoped API token. It shares generated request and response schemas with the
|
|
233
|
+
operation registry, OpenAPI document and organization MCP server. The seven
|
|
234
|
+
reviewed reads cover organization details, locations, services, schedule,
|
|
235
|
+
the user directory, task lists and inventory. Route inventory is not a reviewed
|
|
236
|
+
payload contract and does not automatically become an SDK method.
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
import { createOrganizationApiClient } from '@vuoma/sdk/organization'
|
|
240
|
+
|
|
241
|
+
const api = createOrganizationApiClient({
|
|
242
|
+
apiOrigin: 'https://vuoma.com',
|
|
243
|
+
organizationSlug: 'your-studio',
|
|
244
|
+
getApiToken: () => integrationServerToken,
|
|
245
|
+
})
|
|
246
|
+
const result = await api.operations['users.directory.read']({ limit: 25 })
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
The host supplies the current token for every request; the client does not store
|
|
250
|
+
it. Queries and responses are validated against the generated contracts, and
|
|
251
|
+
redirects and oversized responses are rejected. The server rechecks the exact
|
|
252
|
+
scope, current organization permissions and tenant access on every call. There
|
|
253
|
+
are no automatic retries. Three explicitly reviewed mutations are available in
|
|
254
|
+
`api.writeOperations`: `messages.send`, `messages.read_state.update` and
|
|
255
|
+
`messages.mute.update`. Supply `{ body: { channel_id, body } }` to send, or
|
|
256
|
+
`{ path: { channel_id }, body: { message_id } }` / `{ path: { channel_id }, body: { is_muted } }`
|
|
257
|
+
to advance read state / mute a channel. The client validates path, payload and response
|
|
258
|
+
contracts and enforces the request byte limit. Each call executes once; reconcile
|
|
259
|
+
an uncertain send by reading the channel before repeating it. Generated MCP tools
|
|
260
|
+
remain reviewed reads only. Run
|
|
261
|
+
`npm run api:generate` from the repository root after changing a reviewed
|
|
262
|
+
contract; `npm run api:check` verifies that generated files are current.
|
|
263
|
+
|
|
264
|
+
## Maintainer verification and package artifact
|
|
137
265
|
|
|
138
|
-
|
|
266
|
+
From the Vuoma source checkout:
|
|
139
267
|
|
|
140
268
|
```sh
|
|
141
|
-
npm
|
|
142
|
-
npm run verify
|
|
269
|
+
npm run verify --workspace @vuoma/sdk
|
|
143
270
|
```
|
|
144
271
|
|
|
145
272
|
Verification tests the actual wire route/header/session boundaries and creates
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
273
|
+
`packages/sdk/artifacts/vuoma-sdk-0.2.0.tgz`. For pre-publication testing, a
|
|
274
|
+
maintainer can provide that reviewed archive to a consumer, which can install it
|
|
275
|
+
with `npm install ./vendor/vuoma-sdk-reviewed.tgz` and retain it with its lockfile. It checks the archive's public
|
|
276
|
+
file list, installs its declared dependencies in an isolated temporary directory,
|
|
277
|
+
and loads both packed entry points.
|
|
278
|
+
The verification command does not publish or attempt registry authentication. The [Vuoma Connected Application License](./LICENSE) permits use, modification
|
|
279
|
+
and redistribution for authorized Vuoma-connected apps, including commercial
|
|
280
|
+
studio apps and mocked development. It does not license an unrelated replacement
|
|
281
|
+
backend or grant API access. It is a restricted-use license, not an open-source
|
|
282
|
+
license. Include the license in your application's third-party notices.
|
package/package.json
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vuoma/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Framework-neutral client for Vuoma public organization and member account APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
|
-
"license": "
|
|
8
|
-
"files": [
|
|
7
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
8
|
+
"files": [
|
|
9
|
+
"src",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
9
13
|
"exports": {
|
|
10
|
-
".": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./src/index.d.ts",
|
|
16
|
+
"import": "./src/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./organization": {
|
|
19
|
+
"types": "./src/organization.d.ts",
|
|
20
|
+
"import": "./src/organization.js"
|
|
21
|
+
}
|
|
11
22
|
},
|
|
12
23
|
"types": "./src/index.d.ts",
|
|
13
24
|
"sideEffects": false,
|
|
@@ -16,6 +27,14 @@
|
|
|
16
27
|
"verify": "npm test && node scripts/verify-package.mjs",
|
|
17
28
|
"prepack": "npm test"
|
|
18
29
|
},
|
|
19
|
-
"publishConfig": {
|
|
20
|
-
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"ajv": "^8.20.0",
|
|
38
|
+
"ajv-formats": "^3.0.1"
|
|
39
|
+
}
|
|
21
40
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -16,16 +16,22 @@ export interface MemberTokenAdapter {
|
|
|
16
16
|
getSession(): MemberAuthSession | null | Promise<MemberAuthSession | null>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/** For native booking wrappers that hold an access token separately from profile data.
|
|
20
|
+
* Accepted only by booking/visit methods; never accepts platform-account credentials. */
|
|
21
|
+
export interface MemberBookingTokenAdapter {
|
|
22
|
+
getCredential(): { organization_slug: string; access_token: string } | null | Promise<{ organization_slug: string; access_token: string } | null>
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
export interface VuomaClientOptions {
|
|
20
26
|
/** Origin only. HTTPS required except HTTP loopback during local development. */
|
|
21
27
|
apiOrigin: string
|
|
22
28
|
organizationSlug: string
|
|
23
29
|
/** Optional stronger client-side tenant check against the member JWT claim. */
|
|
24
30
|
organizationId?: string
|
|
25
|
-
|
|
26
|
-
appKey?: string
|
|
27
|
-
fetch?: typeof globalThis.fetch
|
|
31
|
+
fetch?: (url: string, init: RequestInit) => Promise<Response>
|
|
28
32
|
tokenAdapter?: MemberTokenAdapter
|
|
33
|
+
/** Mutually exclusive with tokenAdapter. Profile/commerce reads still require a full session. */
|
|
34
|
+
bookingTokenAdapter?: MemberBookingTokenAdapter
|
|
29
35
|
/** Default 2 MiB; accepted range 1 KiB–16 MiB. */
|
|
30
36
|
maximumResponseBytes?: number
|
|
31
37
|
}
|
|
@@ -106,14 +112,61 @@ export interface MemberCommerceSnapshot {
|
|
|
106
112
|
orders: ApiRecord[]
|
|
107
113
|
}
|
|
108
114
|
|
|
115
|
+
export type MemberSignupIntent = 'new' | 'migrate' | 'auto' | 'activate'
|
|
116
|
+
export type MemberAccountCodeRequest = RequestOptions & { email: string } & (
|
|
117
|
+
{ mode: 'recovery'; signupIntent?: never; displayName?: never } |
|
|
118
|
+
{ mode: 'signup'; signupIntent: 'new' | 'auto'; displayName: string } |
|
|
119
|
+
{ mode: 'signup'; signupIntent: 'migrate' | 'activate'; displayName?: never }
|
|
120
|
+
)
|
|
121
|
+
export type MemberAccountCodeConfirmation = RequestOptions & { email: string; code: string } & (
|
|
122
|
+
{ mode: 'recovery'; signupIntent?: never } | { mode: 'signup'; signupIntent: MemberSignupIntent }
|
|
123
|
+
)
|
|
124
|
+
export interface MemberAccountResolution { kind: 'existing_account' | 'existing_profile' | 'new_profile'; display_name: string; masked_email: string; masked_phone: string | null }
|
|
125
|
+
export interface MemberPasswordCapability { organization_slug: string; value: string; account_resolution?: MemberAccountResolution }
|
|
126
|
+
export interface MemberBookingPolicyAcceptance { policy_version: string; policy_consent: true; payment_authorized: true; payment_authorization_id: string }
|
|
127
|
+
export type MemberClassBookingInput = { service_session_id: string; entitlement_id?: string | null; source_request_id: string } & (MemberBookingPolicyAcceptance | { policy_version?: never; policy_consent?: never; payment_authorized?: never; payment_authorization_id?: never })
|
|
128
|
+
export interface MemberClassBookingResult { api_version: 1; booking: { id: string; status: 'confirmed' | 'waitlisted' | 'cancelled' | 'attended' | 'no_show' }; redemption: { id: string; status: 'waitlisted' | 'reserved' | 'consumed' | 'released' | 'reversed' } }
|
|
129
|
+
export interface MemberCancellationQuote {
|
|
130
|
+
policy_version: string | null; can_cancel: boolean; late: boolean; late_cancellation_deadline: string | null;
|
|
131
|
+
grace_until: string | null; grace_applies: boolean; demand_observed: boolean; fee_amount: number; currency: string;
|
|
132
|
+
reason: 'no_policy' | 'fees_disabled' | 'legacy_booking' | 'on_time' | 'waitlisted' | 'booking_grace' | 'quiet_class' | 'late_fee_if_unfilled' | 'seat_refilled' | 'teacher_assignment' | 'started';
|
|
133
|
+
waive_if_filled: boolean; credit_return: boolean; quoted_at: string; policy_context?: ApiRecord | null
|
|
134
|
+
}
|
|
135
|
+
export interface MemberCancellationQuoteResult { api_version: 1; booking_id: string; quote: MemberCancellationQuote }
|
|
136
|
+
export interface MemberBookingCancellation { api_version: 1; booking_id: string; status: 'cancelled'; canceled: true; cancellation_quote: MemberCancellationQuote | null }
|
|
137
|
+
export interface MemberAppointmentSelection { service_offering_id: string; starts_at: string; ends_at: string; credit_cost: number }
|
|
138
|
+
export interface MemberAppointmentVisitRequest { source_request_id: string; appointments: MemberAppointmentSelection[] }
|
|
139
|
+
export interface MemberAppointmentVisitResult {
|
|
140
|
+
api_version: 1; visit_id: string; source_request_id: string; credit_cost: number;
|
|
141
|
+
bookings: Array<MemberAppointmentSelection & { booking_id: string; service_session_id: string; status: 'confirmed' | 'cancelled' | 'attended' | 'no_show' }>
|
|
142
|
+
}
|
|
143
|
+
export interface MemberLocation { public_id: string; name: string; timezone: string; city: string | null; region: string | null }
|
|
144
|
+
export interface MemberAppointmentCandidate extends MemberAppointmentSelection {
|
|
145
|
+
candidate_id: string; service_id: string; duration_minutes: number; location: MemberLocation;
|
|
146
|
+
service: { id: string; name: string; description: string | null }
|
|
147
|
+
}
|
|
148
|
+
export interface MemberPublicAvailability { api_version: 1; generated_at: string; range: { from: string; to: string }; slots: MemberAppointmentCandidate[]; has_more: boolean }
|
|
149
|
+
export interface MemberBookingCatalog {
|
|
150
|
+
api_version: 1; generated_at: string; cancellation_notice_minutes?: number;
|
|
151
|
+
experience: { classes: boolean; appointments: boolean; default_view: 'classes' | 'appointments' };
|
|
152
|
+
services: Array<{ id: string; name: string; description: string | null; offerings: Array<{ id: string; duration_minutes: number; location_public_id: string; credit_cost: number | null }> }>;
|
|
153
|
+
locations: MemberLocation[]
|
|
154
|
+
}
|
|
155
|
+
|
|
109
156
|
export interface VuomaClient {
|
|
110
157
|
readonly public: {
|
|
111
158
|
getBootstrap(options?: RequestOptions & { includeEvents?: boolean }): Promise<MemberBootstrap>
|
|
112
159
|
/** Returns one server range. If has_more is true, split the range and request again. */
|
|
113
160
|
getSchedule(options: RequestOptions & { from: string; to: string; includeEvents?: boolean; fresh?: boolean }): Promise<MemberPublicSchedule>
|
|
161
|
+
getBookingCatalog(options?: RequestOptions): Promise<MemberBookingCatalog>
|
|
162
|
+
/** One half-open range, up to 14 days. Split when has_more is true. */
|
|
163
|
+
getAppointmentAvailability(options: RequestOptions & { from: string; to: string }): Promise<MemberPublicAvailability>
|
|
114
164
|
getCatalog(options?: RequestOptions & { includeCreditPurchases?: boolean }): Promise<MemberPublicCatalog>
|
|
115
165
|
}
|
|
116
166
|
readonly auth: {
|
|
167
|
+
requestAccountCode(options: MemberAccountCodeRequest): Promise<{ ok: true; mode: 'signup' | 'recovery'; requires_email_code: true }>
|
|
168
|
+
confirmAccountCode(options: MemberAccountCodeConfirmation): Promise<MemberPasswordCapability>
|
|
169
|
+
completePassword(options: RequestOptions & { capability: MemberPasswordCapability; password: string }): Promise<void>
|
|
117
170
|
/** Returns credentials to the host; the SDK neither stores nor installs them. */
|
|
118
171
|
signIn(options: RequestOptions & { email: string; password: string }): Promise<MemberAuthSession>
|
|
119
172
|
refresh(options: RequestOptions & { refreshToken: string }): Promise<MemberAuthSession>
|
|
@@ -121,6 +174,14 @@ export interface VuomaClient {
|
|
|
121
174
|
signOut(options: RequestOptions & { refreshToken: string }): Promise<void>
|
|
122
175
|
}
|
|
123
176
|
readonly member: {
|
|
177
|
+
/** Executes once. Retain source_request_id and the exact payload for uncertain-result recovery. */
|
|
178
|
+
bookClass(input: MemberClassBookingInput, options?: RequestOptions): Promise<MemberClassBookingResult>
|
|
179
|
+
getCancellationQuote(bookingId: string, options?: RequestOptions): Promise<MemberCancellationQuoteResult>
|
|
180
|
+
/** Applies to individual class and appointment bookings. Recheck a changed quote before retrying. */
|
|
181
|
+
cancelBooking(bookingId: string, options?: RequestOptions & { expectedFeeAmount?: number }): Promise<MemberBookingCancellation>
|
|
182
|
+
bookAppointmentVisit(input: MemberAppointmentVisitRequest, options?: RequestOptions): Promise<MemberAppointmentVisitResult>
|
|
183
|
+
/** Read the original receipt using its saved request; validates every returned selection. */
|
|
184
|
+
getAppointmentVisit(input: MemberAppointmentVisitRequest, options?: RequestOptions): Promise<MemberAppointmentVisitResult>
|
|
124
185
|
getProfile(options?: RequestOptions): Promise<MemberProfile>
|
|
125
186
|
updateProfile(changes: MemberProfileChanges, options?: RequestOptions): Promise<MemberProfile>
|
|
126
187
|
getCommerce(options?: RequestOptions): Promise<MemberCommerceSnapshot>
|