@syndew/oluso-sdk 0.0.0-stage → 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/README.md +509 -2
- package/dist/auth/embed.global.js +210 -0
- package/dist/auth/embed.global.js.map +1 -0
- package/dist/auth/index.d.mts +535 -0
- package/dist/auth/index.d.ts +535 -0
- package/dist/auth/index.js +2118 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +2088 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/embed.global.js +448 -0
- package/dist/embed.global.js.map +1 -0
- package/dist/index.d.mts +810 -0
- package/dist/index.d.ts +810 -0
- package/dist/index.js +2127 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2095 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +559 -0
- package/dist/react.d.ts +559 -0
- package/dist/react.js +1674 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +1642 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +67 -4
package/README.md
CHANGED
|
@@ -1,3 +1,510 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @syndew/oluso-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
JavaScript/TypeScript SDK for Oluso. Includes journey forms (waitlists, surveys), authentication (inline/modal journeys and OIDC redirect), role/permission checks, and drop-in embed scripts.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @syndew/oluso-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Packages
|
|
12
|
+
|
|
13
|
+
| Entry Point | Description |
|
|
14
|
+
|-------------|-------------|
|
|
15
|
+
| `@syndew/oluso-sdk` | Core client + auth SDK (ESM/CJS) |
|
|
16
|
+
| `@syndew/oluso-sdk/react` | React components and hooks |
|
|
17
|
+
| `@syndew/oluso-sdk/embed` | Drop-in `<script>` for journey modals |
|
|
18
|
+
| `@syndew/oluso-sdk/auth` | Auth SDK standalone (ESM/CJS) |
|
|
19
|
+
| `@syndew/oluso-sdk/auth-embed` | Drop-in `<script>` for auth modals |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Journey Forms
|
|
24
|
+
|
|
25
|
+
### Vanilla JavaScript
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { createClient } from '@syndew/oluso-sdk';
|
|
29
|
+
|
|
30
|
+
const oluso = createClient({
|
|
31
|
+
serverUrl: 'https://auth.yoursite.com',
|
|
32
|
+
tenant: 'acme',
|
|
33
|
+
apiKey: 'pk_...', // Optional
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Get journey info (form fields)
|
|
37
|
+
const journey = await oluso.getJourney('waitlist');
|
|
38
|
+
console.log(journey.fields); // [{ name: 'email', type: 'email', ... }]
|
|
39
|
+
|
|
40
|
+
// Submit data
|
|
41
|
+
const result = await oluso.submit('waitlist', {
|
|
42
|
+
email: 'user@example.com',
|
|
43
|
+
name: 'John Doe',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (result.success) {
|
|
47
|
+
console.log('Submitted!', result.submissionId);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### React
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { OlusoProvider, JourneyForm, useJourney } from '@syndew/oluso-sdk/react';
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
return (
|
|
58
|
+
<OlusoProvider config={{ serverUrl: 'https://auth.yoursite.com', tenant: 'acme' }}>
|
|
59
|
+
<WaitlistPage />
|
|
60
|
+
</OlusoProvider>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Pre-built form component
|
|
65
|
+
function WaitlistPage() {
|
|
66
|
+
return (
|
|
67
|
+
<JourneyForm
|
|
68
|
+
slug="waitlist"
|
|
69
|
+
onSuccess={() => console.log('Thanks!')}
|
|
70
|
+
submitText="Join Waitlist"
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Headless hook for custom UI
|
|
76
|
+
function CustomForm() {
|
|
77
|
+
const { journey, values, setValue, submit, isSubmitting, fieldErrors } = useJourney({
|
|
78
|
+
slug: 'waitlist',
|
|
79
|
+
onSuccess: (result) => console.log('Submitted!', result),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (!journey) return <div>Loading...</div>;
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<form onSubmit={(e) => { e.preventDefault(); submit(); }}>
|
|
86
|
+
{journey.fields.map((field) => (
|
|
87
|
+
<div key={field.name}>
|
|
88
|
+
<label>{field.label}</label>
|
|
89
|
+
<input
|
|
90
|
+
type={field.type}
|
|
91
|
+
value={values[field.name] as string || ''}
|
|
92
|
+
onChange={(e) => setValue(field.name, e.target.value)}
|
|
93
|
+
required={field.required}
|
|
94
|
+
/>
|
|
95
|
+
{fieldErrors[field.name] && <span>{fieldErrors[field.name]}</span>}
|
|
96
|
+
</div>
|
|
97
|
+
))}
|
|
98
|
+
<button type="submit" disabled={isSubmitting}>Submit</button>
|
|
99
|
+
</form>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Multi-Step Journeys
|
|
105
|
+
|
|
106
|
+
Any journey can run step by step from your own UI. Each call returns the session: the
|
|
107
|
+
step to render (`session.step`, with its type and model) or the completion.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const oluso = createClient({ serverUrl: 'https://auth.yoursite.com', tenant: 'acme' });
|
|
111
|
+
|
|
112
|
+
let session = await oluso.startJourney('onboarding-survey');
|
|
113
|
+
while (session.status === 'in_progress') {
|
|
114
|
+
const input = await renderStep(session.step); // your UI for session.step
|
|
115
|
+
session = await oluso.submitStep(session.sessionId, input);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (session.completed) {
|
|
119
|
+
console.log(session.message);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`oluso.getSession(sessionId)` returns where a session stands without running it.
|
|
124
|
+
Authentication journeys run inline through the auth client (`auth.signIn(data)`), which
|
|
125
|
+
completes them with tokens.
|
|
126
|
+
|
|
127
|
+
### Drop-in Embed (No Build Step)
|
|
128
|
+
|
|
129
|
+
Add the script to any HTML page. Buttons with `data-oluso-trigger` open a modal form:
|
|
130
|
+
|
|
131
|
+
```html
|
|
132
|
+
<script src="https://cdn.oluso.io/sdk/embed.js"></script>
|
|
133
|
+
|
|
134
|
+
<button data-oluso-trigger="waitlist">Join Waitlist</button>
|
|
135
|
+
<button data-oluso-trigger="demo">Request Demo</button>
|
|
136
|
+
|
|
137
|
+
<script>
|
|
138
|
+
Oluso.init({
|
|
139
|
+
serverUrl: 'https://auth.yoursite.com',
|
|
140
|
+
tenant: 'acme',
|
|
141
|
+
journeys: {
|
|
142
|
+
waitlist: { title: 'Join the Waitlist' },
|
|
143
|
+
demo: { title: 'Request a Demo' },
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
</script>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Programmatic API:
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
Oluso.open('waitlist');
|
|
153
|
+
Oluso.close();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Embedding a journey in your own iframe
|
|
157
|
+
|
|
158
|
+
Journeys can ask for documents and photos (a file field with *Take a photo*, the
|
|
159
|
+
Business Verification step's supporting documents, or a verification provider's widget
|
|
160
|
+
that captures ID or a selfie). Browsers only give an iframe the camera and microphone
|
|
161
|
+
when the host page allows it, so include `allow="camera; microphone"`:
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<iframe
|
|
165
|
+
src="https://auth.yoursite.com/journey/start/merchant-signup"
|
|
166
|
+
allow="camera; microphone"
|
|
167
|
+
style="border:none;width:100%;min-height:640px"
|
|
168
|
+
title="Merchant sign-up"></iframe>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`JourneyEmbed` (React) and the modal sign-in (`auth.signIn()`) set this for you. If your
|
|
172
|
+
site sends a `Permissions-Policy` header, it must also allow `camera` and `microphone` for
|
|
173
|
+
the auth server's origin (e.g. `Permissions-Policy: camera=(self "https://auth.yoursite.com")`).
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Authentication
|
|
178
|
+
|
|
179
|
+
The auth SDK provides inline and modal authentication (using the journey system) and standard OIDC redirect flow, plus role and permission checking.
|
|
180
|
+
|
|
181
|
+
### Setup
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { OlusoAuth } from '@syndew/oluso-sdk';
|
|
185
|
+
|
|
186
|
+
const auth = new OlusoAuth({
|
|
187
|
+
serverUrl: 'https://auth.yoursite.com',
|
|
188
|
+
tenant: 'acme',
|
|
189
|
+
clientId: 'my-spa-client',
|
|
190
|
+
storage: 'localStorage', // 'memory' | 'localStorage' | 'sessionStorage'
|
|
191
|
+
onAuthStateChange: (user) => {
|
|
192
|
+
console.log('Auth state:', user);
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Modal Sign-In (Secure Iframe)
|
|
198
|
+
|
|
199
|
+
Call `signIn()` without arguments to open a secure modal. Credentials are entered inside an iframe hosted on the auth server — the host page never has access to passwords:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Opens modal, resolves when auth completes
|
|
203
|
+
const result = await auth.signIn();
|
|
204
|
+
|
|
205
|
+
if (result.success) {
|
|
206
|
+
console.log('Logged in:', result.user.name);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
This is the recommended approach for most integrations. It works on any site (first-party or third-party) and handles MFA, password reset, etc. inside the iframe automatically.
|
|
211
|
+
|
|
212
|
+
### Programmatic Sign-In (First-Party Only)
|
|
213
|
+
|
|
214
|
+
For trusted first-party apps where you control the page and collect credentials yourself.
|
|
215
|
+
The journey runs step by step through the headless journey API and completes with an
|
|
216
|
+
authorization code bound to this client's PKCE verifier, which the SDK redeems for tokens:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const result = await auth.signIn({
|
|
220
|
+
username: 'user@example.com',
|
|
221
|
+
password: 'secret',
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
if (result.success) {
|
|
225
|
+
console.log('Logged in:', result.user.name);
|
|
226
|
+
console.log('Token:', result.tokens.accessToken);
|
|
227
|
+
} else if (result.requiresStep) {
|
|
228
|
+
// MFA or another step: result.step describes what to render
|
|
229
|
+
const mfaResult = await auth.continueStep(result.sessionId, {
|
|
230
|
+
code: '123456',
|
|
231
|
+
});
|
|
232
|
+
} else {
|
|
233
|
+
console.error(result.error); // e.g. invalid credentials
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The calling page's origin must be registered for the client (one of its CORS origins, or the
|
|
238
|
+
origin of one of its redirect URIs); a journey's own allowed origins can narrow that further. The
|
|
239
|
+
client must be enabled and allow the authorization code grant, the scopes must be ones the client
|
|
240
|
+
is allowed, and a PKCE S256 challenge is required (the SDK sends one). The same rules apply to
|
|
241
|
+
every sign-in that returns a code to the page: the modal, passkeys and FedCM.
|
|
242
|
+
|
|
243
|
+
> **Security note**: Programmatic sign-in passes credentials through JavaScript on the host page. Only use this on pages you fully control. For third-party sites or untrusted environments, use the modal approach above.
|
|
244
|
+
|
|
245
|
+
### Sign-Up
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// Modal (secure)
|
|
249
|
+
const result = await auth.signUp();
|
|
250
|
+
|
|
251
|
+
// Or programmatic (first-party)
|
|
252
|
+
const result = await auth.signUp({
|
|
253
|
+
name: 'Jane Doe',
|
|
254
|
+
email: 'jane@example.com',
|
|
255
|
+
password: 'securePassword123',
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### OIDC Redirect Flow
|
|
260
|
+
|
|
261
|
+
For apps that prefer the standard redirect-based flow:
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// Redirect to login page
|
|
265
|
+
await auth.loginWithRedirect({
|
|
266
|
+
prompt: 'login', // Optional: 'login' | 'consent' | 'none'
|
|
267
|
+
state: '/dashboard', // Optional: return path
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// On callback page (/callback)
|
|
271
|
+
const result = await auth.handleCallback();
|
|
272
|
+
if (result.success) {
|
|
273
|
+
window.location.href = '/dashboard';
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Checking Roles & Permissions
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
const user = auth.getUser();
|
|
281
|
+
|
|
282
|
+
// Single role check
|
|
283
|
+
if (auth.hasRole('admin')) {
|
|
284
|
+
showAdminPanel();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Any of multiple roles
|
|
288
|
+
if (auth.hasAnyRole('admin', 'editor', 'moderator')) {
|
|
289
|
+
showEditButton();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Permission check
|
|
293
|
+
if (auth.hasPermission('documents:write')) {
|
|
294
|
+
enableUpload();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Access user claims directly
|
|
298
|
+
console.log(user.email);
|
|
299
|
+
console.log(user.tenantId);
|
|
300
|
+
console.log(user.claims); // Raw ID token claims
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Token Management
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// Get access token for API calls
|
|
307
|
+
const token = auth.getAccessToken();
|
|
308
|
+
fetch('/api/data', {
|
|
309
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Refresh token
|
|
313
|
+
const refreshed = await auth.refreshToken();
|
|
314
|
+
|
|
315
|
+
// Check auth state
|
|
316
|
+
if (auth.isAuthenticated()) { ... }
|
|
317
|
+
|
|
318
|
+
// Fetch updated user info from server
|
|
319
|
+
const user = await auth.fetchUserInfo();
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Logout
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// Local logout (clear tokens)
|
|
326
|
+
auth.logout();
|
|
327
|
+
|
|
328
|
+
// Logout with server-side session end
|
|
329
|
+
auth.logout({ redirect: true });
|
|
330
|
+
|
|
331
|
+
// Custom post-logout redirect
|
|
332
|
+
auth.logout({
|
|
333
|
+
redirect: true,
|
|
334
|
+
postLogoutRedirectUri: 'https://yoursite.com/goodbye',
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Passkeys (WebAuthn)
|
|
339
|
+
|
|
340
|
+
Sign in with passkeys — no form, no iframe, just a native biometric/key prompt. Works with discoverable credentials (usernameless) and username-based flows.
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// Discoverable credential (shows all passkeys for this site)
|
|
344
|
+
const result = await auth.signInWithPasskey();
|
|
345
|
+
|
|
346
|
+
// Username-based (shows passkeys for a specific user)
|
|
347
|
+
const result = await auth.signInWithPasskey({ username: 'user@example.com' });
|
|
348
|
+
|
|
349
|
+
// Conditional mediation (passkey suggestions in autofill)
|
|
350
|
+
const ac = new AbortController();
|
|
351
|
+
const result = await auth.signInWithPasskey({ conditional: true, signal: ac.signal });
|
|
352
|
+
|
|
353
|
+
if (result.success) {
|
|
354
|
+
console.log('Signed in with passkey:', result.user.name);
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
> **Note**: Passkeys require the FIDO2 plugin to be enabled on the server (and passkeys not turned off for the tenant). Users must have previously registered a passkey via their account settings. The page's origin must be registered for the client and the scopes allowed for it, as for programmatic sign-in above.
|
|
359
|
+
|
|
360
|
+
### FedCM (Browser-Native Account Picker)
|
|
361
|
+
|
|
362
|
+
FedCM enables browser-native federated sign-in without redirects or popups. The browser shows an account picker if the user has an active session on the auth server.
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
const result = await auth.signInWithFedCM();
|
|
366
|
+
|
|
367
|
+
// With login hint to pre-select an account
|
|
368
|
+
const result = await auth.signInWithFedCM({ loginHint: 'user@example.com' });
|
|
369
|
+
|
|
370
|
+
// Silent re-authentication (if user previously approved)
|
|
371
|
+
const result = await auth.signInWithFedCM({ autoReauth: true });
|
|
372
|
+
|
|
373
|
+
if (result.success) {
|
|
374
|
+
console.log('Signed in via FedCM:', result.user.name);
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
> **Browser support**: Chrome 132+, Edge 132+ (the SDK binds the code to the page with a PKCE challenge sent in the provider's `params`). Returns an error on unsupported browsers — use as a progressive enhancement alongside modal sign-in. The page's origin must be registered for the client.
|
|
379
|
+
|
|
380
|
+
### OIDC Endpoint Discovery
|
|
381
|
+
|
|
382
|
+
Endpoints are automatically discovered from `.well-known/openid-configuration`. You can also specify them manually:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
const auth = new OlusoAuth({
|
|
386
|
+
serverUrl: 'https://auth.yoursite.com',
|
|
387
|
+
tenant: 'acme',
|
|
388
|
+
clientId: 'my-spa-client',
|
|
389
|
+
endpoints: {
|
|
390
|
+
authorization: 'https://auth.yoursite.com/connect/authorize',
|
|
391
|
+
token: 'https://auth.yoursite.com/connect/token',
|
|
392
|
+
userinfo: 'https://auth.yoursite.com/connect/userinfo',
|
|
393
|
+
endSession: 'https://auth.yoursite.com/connect/endsession',
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Drop-in Auth Embed (No Build Step)
|
|
399
|
+
|
|
400
|
+
Add auth to any site with a single script tag:
|
|
401
|
+
|
|
402
|
+
```html
|
|
403
|
+
<script src="https://cdn.oluso.io/sdk/auth-embed.js"></script>
|
|
404
|
+
|
|
405
|
+
<button data-oluso-auth="signin">Sign In</button>
|
|
406
|
+
<button data-oluso-auth="signup">Create Account</button>
|
|
407
|
+
<button data-oluso-auth="passkey">Sign In with Passkey</button>
|
|
408
|
+
|
|
409
|
+
<script>
|
|
410
|
+
OlusoAuth.init({
|
|
411
|
+
serverUrl: 'https://auth.yoursite.com',
|
|
412
|
+
tenant: 'acme',
|
|
413
|
+
clientId: 'my-spa-client',
|
|
414
|
+
storage: 'localStorage',
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Listen for auth state changes
|
|
418
|
+
OlusoAuth.onAuth((user) => {
|
|
419
|
+
if (user) {
|
|
420
|
+
document.getElementById('greeting').textContent = `Hello, ${user.name}`;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
</script>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Programmatic API:
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
OlusoAuth.open('signin'); // Open sign-in modal
|
|
430
|
+
OlusoAuth.open('signup'); // Open sign-up modal
|
|
431
|
+
OlusoAuth.close();
|
|
432
|
+
|
|
433
|
+
// Passkey & FedCM (no modal needed)
|
|
434
|
+
OlusoAuth.signInWithPasskey(); // Native passkey prompt
|
|
435
|
+
OlusoAuth.signInWithFedCM(); // Browser account picker
|
|
436
|
+
|
|
437
|
+
// After auth
|
|
438
|
+
OlusoAuth.getUser(); // { sub, name, email, roles, permissions, ... }
|
|
439
|
+
OlusoAuth.hasRole('admin'); // true/false
|
|
440
|
+
OlusoAuth.hasPermission('read'); // true/false
|
|
441
|
+
OlusoAuth.logout();
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Configuration Reference
|
|
447
|
+
|
|
448
|
+
### `OlusoConfig` (Journey Client)
|
|
449
|
+
|
|
450
|
+
| Option | Type | Required | Description |
|
|
451
|
+
|--------|------|----------|-------------|
|
|
452
|
+
| `serverUrl` | `string` | Yes | Base URL of your Oluso server |
|
|
453
|
+
| `tenant` | `string` | Yes | Your tenant ID or subdomain |
|
|
454
|
+
| `apiKey` | `string` | No | Public API key |
|
|
455
|
+
| `fetch` | `typeof fetch` | No | Custom fetch implementation (SSR) |
|
|
456
|
+
|
|
457
|
+
### `OlusoAuthConfig` (Auth Client)
|
|
458
|
+
|
|
459
|
+
| Option | Type | Required | Description |
|
|
460
|
+
|--------|------|----------|-------------|
|
|
461
|
+
| `serverUrl` | `string` | Yes | Base URL of your Oluso server |
|
|
462
|
+
| `tenant` | `string` | Yes | Your tenant ID or subdomain |
|
|
463
|
+
| `clientId` | `string` | Yes | OAuth2 client ID (public client) |
|
|
464
|
+
| `redirectUri` | `string` | No | Redirect URI for OIDC code flow |
|
|
465
|
+
| `scopes` | `string` | No | Scopes to request (default: `openid profile email`) |
|
|
466
|
+
| `endpoints` | `OidcEndpoints` | No | Manual OIDC endpoint overrides |
|
|
467
|
+
| `signInJourney` | `string` | No | Slug of the sign-in journey (default: `signin`) |
|
|
468
|
+
| `signUpJourney` | `string` | No | Slug of the sign-up journey (default: `signup`) |
|
|
469
|
+
| `passwordResetJourney` | `string` | No | Slug of the password-reset journey |
|
|
470
|
+
| `storage` | `string` | No | Token storage: `memory`, `localStorage`, `sessionStorage` |
|
|
471
|
+
| `apiKey` | `string` | No | Public API key, sent as `X-API-Key` |
|
|
472
|
+
| `onAuthStateChange` | `function` | No | Callback when auth state changes |
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## Events
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
const oluso = createClient({ ... });
|
|
480
|
+
|
|
481
|
+
oluso.on('submission:success', (event) => {
|
|
482
|
+
console.log('Submitted:', event.data);
|
|
483
|
+
});
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Event types: `journey:started`, `journey:step`, `journey:completed`, `journey:error`, `submission:success`, `submission:error`, `auth:success`, `auth:error`. Each event carries the journey's `slug`; journey events also carry the `sessionId`.
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## TypeScript
|
|
491
|
+
|
|
492
|
+
All types are exported:
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
import type {
|
|
496
|
+
OlusoConfig,
|
|
497
|
+
JourneyInfo,
|
|
498
|
+
JourneyField,
|
|
499
|
+
SubmissionResult,
|
|
500
|
+
OlusoAuthConfig,
|
|
501
|
+
OlusoUser,
|
|
502
|
+
TokenSet,
|
|
503
|
+
AuthResult,
|
|
504
|
+
OidcEndpoints,
|
|
505
|
+
JourneySession,
|
|
506
|
+
JourneyStepView,
|
|
507
|
+
StepResult,
|
|
508
|
+
JourneyStepData,
|
|
509
|
+
} from '@syndew/oluso-sdk';
|
|
510
|
+
```
|