@vuoma/sdk 0.1.0 → 0.1.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/README.md +42 -9
- package/package.json +1 -1
- package/src/index.d.ts +2 -0
- package/src/index.js +4 -0
package/README.md
CHANGED
|
@@ -4,15 +4,28 @@ 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
6
|
does not store credentials, read environment variables, create accounts, or
|
|
7
|
-
grant access.
|
|
8
|
-
|
|
7
|
+
grant access. Install the public package and pin the reviewed version:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @vuoma/sdk@0.1.1
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Use SvelteKit and SvelteKit UI with `@vuoma/web` for website account components
|
|
14
|
+
and same-origin server sessions. Use React Native for mobile UI and this SDK as
|
|
15
|
+
its framework-neutral API transport. The complete `@vuoma/react-native` studio
|
|
16
|
+
app core remains a private workspace; independent apps do not depend on it.
|
|
17
|
+
The public setup guide is at `/developers` and `/o/<organization_slug>/developers`
|
|
18
|
+
on the same combined Vuoma application and landing-page deployment. The current
|
|
19
|
+
origin is `https://vuoma.vercel.app`; use `https://vuoma.com` only after domain
|
|
20
|
+
cutover and exact-origin configuration have been verified.
|
|
9
21
|
|
|
10
22
|
```js
|
|
11
23
|
import { createVuomaClient } from '@vuoma/sdk'
|
|
12
24
|
|
|
13
25
|
const vuoma = createVuomaClient({
|
|
14
|
-
apiOrigin: '
|
|
26
|
+
apiOrigin: 'https://vuoma.vercel.app', // Use your verified Vuoma origin.
|
|
15
27
|
organizationSlug: 'your-studio',
|
|
28
|
+
appKey: publishableAppKey, // The organization's registered vuoma_pk_ app key.
|
|
16
29
|
fetch: globalThis.fetch,
|
|
17
30
|
})
|
|
18
31
|
|
|
@@ -24,7 +37,12 @@ const schedule = await vuoma.public.getSchedule({
|
|
|
24
37
|
})
|
|
25
38
|
```
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
The optional `appKey` identifies a registered organization app. Obtain its
|
|
41
|
+
publishable `vuoma_pk_` key from the organization's app registration and use the
|
|
42
|
+
same key for public reads, sign-in, refresh, sign-out and member requests. Public
|
|
43
|
+
reads also work without an app key where the API allows anonymous access. The
|
|
44
|
+
organization slug is a route hint; the server validates the app's organization
|
|
45
|
+
binding. Schedule timestamps are normalized to
|
|
28
46
|
UTC, and ranges must be positive and at most 63 days. The response preserves
|
|
29
47
|
`schedule.has_more`; when it is true, split the requested range and fetch each
|
|
30
48
|
part rather than displaying the first response as a complete schedule.
|
|
@@ -39,8 +57,9 @@ server or native host; it does not establish a browser cookie session.
|
|
|
39
57
|
```js
|
|
40
58
|
let session = null // Example in-memory host state; no SDK persistence.
|
|
41
59
|
const vuoma = createVuomaClient({
|
|
42
|
-
apiOrigin: '
|
|
60
|
+
apiOrigin: 'https://vuoma.vercel.app',
|
|
43
61
|
organizationSlug: 'your-studio',
|
|
62
|
+
appKey: publishableAppKey,
|
|
44
63
|
tokenAdapter: { getSession: () => session },
|
|
45
64
|
})
|
|
46
65
|
|
|
@@ -63,6 +82,12 @@ Native, keep refresh tokens in Keychain/Keystore through a secure-storage adapte
|
|
|
63
82
|
keep access tokens in memory, and refresh through the documented member route.
|
|
64
83
|
Refresh scheduling, retries and persistence remain host responsibilities.
|
|
65
84
|
|
|
85
|
+
An app-bound member session requires the same active app registration on each
|
|
86
|
+
request. Revoking that registration invalidates its bound sessions. Re-enabling
|
|
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.
|
|
90
|
+
|
|
66
91
|
The SDK uses `credentials: 'omit'`, prevents redirects, and sends member access
|
|
67
92
|
tokens only to its exact configured origin and organization. It rejects missing,
|
|
68
93
|
expired, cross-organization, platform-account, organization API, identity-only
|
|
@@ -80,6 +105,14 @@ the response text and against a supplied Content-Length header.
|
|
|
80
105
|
|
|
81
106
|
## Keys and client IDs
|
|
82
107
|
|
|
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.
|
|
83
116
|
- **Organization integration/delegated API keys** are confidential server
|
|
84
117
|
credentials. Never put them in a website bundle, native binary, URL or SDK
|
|
85
118
|
token adapter. They do not sign a customer in.
|
|
@@ -93,9 +126,9 @@ the response text and against a supplied Content-Length header.
|
|
|
93
126
|
accepted by this member client.
|
|
94
127
|
|
|
95
128
|
This package adds no OAuth grant, CORS policy or backend permission. A third-party
|
|
96
|
-
website still needs its backend adapter.
|
|
97
|
-
|
|
98
|
-
|
|
129
|
+
website still needs its backend adapter. App registration and app-scoped member
|
|
130
|
+
session grants are enforced by the API; a publishable app key alone never
|
|
131
|
+
authorizes private account data.
|
|
99
132
|
|
|
100
133
|
Supported routes are public `/api/v1/o/{slug}/member/{bootstrap,schedule,catalog}`;
|
|
101
134
|
member sign-in, profile GET/PATCH and commerce GET; plus the existing global
|
|
@@ -112,6 +145,6 @@ npm run verify
|
|
|
112
145
|
Verification tests the actual wire route/header/session boundaries and creates
|
|
113
146
|
an installable npm archive under `artifacts/`. It checks the archive's public
|
|
114
147
|
file list and loads the packed module in an isolated temporary directory.
|
|
115
|
-
|
|
148
|
+
The verification command does not publish or attempt registry authentication. The inherited
|
|
116
149
|
license remains `UNLICENSED`; `private: false` prepares packaging without granting
|
|
117
150
|
open-source licensing rights.
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export interface VuomaClientOptions {
|
|
|
22
22
|
organizationSlug: string
|
|
23
23
|
/** Optional stronger client-side tenant check against the member JWT claim. */
|
|
24
24
|
organizationId?: string
|
|
25
|
+
/** Publishable vuoma_pk_ app identity; private calls still require member auth. */
|
|
26
|
+
appKey?: string
|
|
25
27
|
fetch?: typeof globalThis.fetch
|
|
26
28
|
tokenAdapter?: MemberTokenAdapter
|
|
27
29
|
/** Default 2 MiB; accepted range 1 KiB–16 MiB. */
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Public package: no environment reads, provider clients, persistence or secrets.
|
|
2
2
|
const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u
|
|
3
|
+
const appKeyPattern = /^vuoma_pk_[0-9a-f]{32}$/u
|
|
3
4
|
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu
|
|
4
5
|
const timestampPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/u
|
|
5
6
|
const maximumRange = 63 * 24 * 60 * 60 * 1000
|
|
@@ -134,6 +135,8 @@ export function createVuomaClient(options) {
|
|
|
134
135
|
if (typeof organizationSlug !== "string" || organizationSlug.length < 2 || organizationSlug.length > 80 || !slugPattern.test(organizationSlug)) throw new TypeError("Use an exact organization slug.")
|
|
135
136
|
const organizationId = options.organizationId
|
|
136
137
|
if (organizationId !== undefined && !uuid(organizationId)) throw new TypeError("Use a valid organization ID.")
|
|
138
|
+
const appKey = options.appKey
|
|
139
|
+
if (appKey !== undefined && (typeof appKey !== "string" || !appKeyPattern.test(appKey))) throw new TypeError("Use a publishable Vuoma app key.")
|
|
137
140
|
const requestFetch = options.fetch ?? globalThis.fetch
|
|
138
141
|
if (typeof requestFetch !== "function") throw new TypeError("A fetch implementation is required.")
|
|
139
142
|
const tokenAdapter = options.tokenAdapter
|
|
@@ -151,6 +154,7 @@ export function createVuomaClient(options) {
|
|
|
151
154
|
const url = new URL(path, origin)
|
|
152
155
|
if (query) for (const [key, value] of Object.entries(query)) url.searchParams.set(key, value)
|
|
153
156
|
const headers = { accept: "application/json" }
|
|
157
|
+
if (appKey !== undefined) headers["x-vuoma-app-key"] = appKey
|
|
154
158
|
if (body !== undefined) headers["content-type"] = "application/json"
|
|
155
159
|
if (accessToken) headers.authorization = `Bearer ${accessToken}`
|
|
156
160
|
const response = await requestFetch(url.href, {
|