foundation-sdk 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 +416 -0
- package/dist/index.cjs +267 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +202 -0
- package/dist/index.js +267 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# foundation-iframe-sdk
|
|
2
|
+
|
|
3
|
+
SDK for building applications that embed within the Foundation container.
|
|
4
|
+
|
|
5
|
+
> **Future Migration:** This package will be renamed to `@foundation/iframe-sdk` when the npm organization is set up.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install foundation-iframe-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createFoundationClient } from 'foundation-iframe-sdk'
|
|
17
|
+
|
|
18
|
+
const sdk = createFoundationClient()
|
|
19
|
+
|
|
20
|
+
// Wait for SDK to be ready (receives initial state from container)
|
|
21
|
+
await sdk.ready
|
|
22
|
+
|
|
23
|
+
// Access current user
|
|
24
|
+
console.log(sdk.auth.user)
|
|
25
|
+
|
|
26
|
+
// Fetch data
|
|
27
|
+
const { items } = await sdk.db.list('projects', { limit: 10 })
|
|
28
|
+
|
|
29
|
+
// Show a toast notification
|
|
30
|
+
await sdk.ui.toast('Hello from embedded app!', 'success')
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API Reference
|
|
34
|
+
|
|
35
|
+
### Initialization
|
|
36
|
+
|
|
37
|
+
#### `createFoundationClient(): FoundationClient`
|
|
38
|
+
|
|
39
|
+
Creates or returns the singleton SDK client instance.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const sdk = createFoundationClient()
|
|
43
|
+
|
|
44
|
+
// Check if ready
|
|
45
|
+
if (sdk.isReady) {
|
|
46
|
+
// SDK has received initial state
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Wait for ready
|
|
50
|
+
await sdk.ready
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
### Authentication (`sdk.auth`)
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
interface AuthService {
|
|
59
|
+
readonly user: User | null // Current user
|
|
60
|
+
readonly isAuthenticated: boolean // Is user logged in
|
|
61
|
+
getToken(): Promise<string> // Get auth token
|
|
62
|
+
login(): Promise<void> // Trigger login flow
|
|
63
|
+
logout(): Promise<void> // Trigger logout
|
|
64
|
+
onChange(callback): () => void // Subscribe to auth changes
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Example:**
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// Get current user
|
|
72
|
+
const user = sdk.auth.user
|
|
73
|
+
console.log(user?.email, user?.name)
|
|
74
|
+
|
|
75
|
+
// Get token for API calls
|
|
76
|
+
const token = await sdk.auth.getToken()
|
|
77
|
+
|
|
78
|
+
// Subscribe to auth changes
|
|
79
|
+
const unsubscribe = sdk.auth.onChange((user) => {
|
|
80
|
+
console.log('Auth changed:', user)
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### Database (`sdk.db`)
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
interface DbService {
|
|
90
|
+
list<T>(entity: string, options?: ListOptions): Promise<{ items: T[]; nextCursor?: string }>
|
|
91
|
+
get<T>(entity: string, id: string): Promise<T>
|
|
92
|
+
create<T>(entity: string, data: Partial<T>): Promise<T>
|
|
93
|
+
update<T>(entity: string, id: string, updates: Partial<T>): Promise<T>
|
|
94
|
+
delete(entity: string, id: string): Promise<void>
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface ListOptions {
|
|
98
|
+
filters?: Record<string, unknown>
|
|
99
|
+
limit?: number
|
|
100
|
+
cursor?: string
|
|
101
|
+
orderBy?: string
|
|
102
|
+
orderDir?: 'asc' | 'desc'
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Example:**
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// List with filters and pagination
|
|
110
|
+
const { items, nextCursor } = await sdk.db.list('projects', {
|
|
111
|
+
filters: { status: 'active' },
|
|
112
|
+
limit: 20,
|
|
113
|
+
orderBy: 'createdAt',
|
|
114
|
+
orderDir: 'desc'
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// Get single item
|
|
118
|
+
const project = await sdk.db.get('projects', 'project-123')
|
|
119
|
+
|
|
120
|
+
// Create
|
|
121
|
+
const newProject = await sdk.db.create('projects', {
|
|
122
|
+
name: 'New Project',
|
|
123
|
+
status: 'active'
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// Update
|
|
127
|
+
const updated = await sdk.db.update('projects', 'project-123', {
|
|
128
|
+
name: 'Updated Name'
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Delete
|
|
132
|
+
await sdk.db.delete('projects', 'project-123')
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### UI (`sdk.ui`)
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
interface UIService {
|
|
141
|
+
toast(message: string, type?: 'success' | 'error' | 'warn' | 'info'): Promise<void>
|
|
142
|
+
confirm(message: string): Promise<{ confirmed: boolean }>
|
|
143
|
+
loading: {
|
|
144
|
+
show(message?: string): Promise<void>
|
|
145
|
+
hide(): Promise<void>
|
|
146
|
+
}
|
|
147
|
+
banner: {
|
|
148
|
+
show(message: string, options?: BannerOptions): Promise<{ bannerId: string }>
|
|
149
|
+
hide(bannerId: string): Promise<void>
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Example:**
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// Toast notifications
|
|
158
|
+
await sdk.ui.toast('Operation successful', 'success')
|
|
159
|
+
await sdk.ui.toast('Something went wrong', 'error')
|
|
160
|
+
|
|
161
|
+
// Confirmation dialog
|
|
162
|
+
const { confirmed } = await sdk.ui.confirm('Delete this item?')
|
|
163
|
+
if (confirmed) {
|
|
164
|
+
await sdk.db.delete('items', itemId)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Loading overlay
|
|
168
|
+
sdk.ui.loading.show('Processing...')
|
|
169
|
+
try {
|
|
170
|
+
await doSomething()
|
|
171
|
+
} finally {
|
|
172
|
+
sdk.ui.loading.hide()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Banners
|
|
176
|
+
const { bannerId } = await sdk.ui.banner.show('New feature available!', {
|
|
177
|
+
type: 'info',
|
|
178
|
+
dismissible: true
|
|
179
|
+
})
|
|
180
|
+
// Later...
|
|
181
|
+
await sdk.ui.banner.hide(bannerId)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### Router (`sdk.router`)
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
interface RouterService {
|
|
190
|
+
readonly path: string
|
|
191
|
+
readonly query: Record<string, string>
|
|
192
|
+
readonly hash: string
|
|
193
|
+
push(path: string, options?: NavOptions): Promise<void>
|
|
194
|
+
replace(path: string, options?: NavOptions): Promise<void>
|
|
195
|
+
setQuery(params: Record<string, string>, options?: { replace?: boolean }): Promise<void>
|
|
196
|
+
onChange(callback: (route: RouterState) => void): () => void
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Example:**
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Navigate
|
|
204
|
+
await sdk.router.push('/dashboard')
|
|
205
|
+
await sdk.router.push('/projects', { query: { filter: 'active' } })
|
|
206
|
+
|
|
207
|
+
// Replace (no history entry)
|
|
208
|
+
await sdk.router.replace('/login')
|
|
209
|
+
|
|
210
|
+
// Update query params
|
|
211
|
+
await sdk.router.setQuery({ page: '2', sort: 'name' })
|
|
212
|
+
|
|
213
|
+
// Subscribe to route changes
|
|
214
|
+
const unsubscribe = sdk.router.onChange((route) => {
|
|
215
|
+
console.log('Route changed:', route.path, route.query)
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### Theme (`sdk.theme`)
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
interface ThemeService {
|
|
225
|
+
readonly isDark: boolean
|
|
226
|
+
readonly mode: 'light' | 'dark' | 'system'
|
|
227
|
+
onChange(callback: (theme: Theme) => void): () => void
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Example:**
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
// Check current theme
|
|
235
|
+
if (sdk.theme.isDark) {
|
|
236
|
+
// Apply dark styles
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Subscribe to theme changes
|
|
240
|
+
const unsubscribe = sdk.theme.onChange((theme) => {
|
|
241
|
+
document.body.classList.toggle('dark', theme.isDark)
|
|
242
|
+
})
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### Storage (`sdk.storage`)
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
interface StorageService {
|
|
251
|
+
upload(options: UploadOptions): Promise<{ id: string; url: string; name: string }>
|
|
252
|
+
get(fileId: string): Promise<FileMetadata>
|
|
253
|
+
delete(fileId: string): Promise<void>
|
|
254
|
+
list(options?: ListOptions): Promise<{ items: FileMetadata[]; nextCursor?: string }>
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Example:**
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// Upload a file (base64 encoded)
|
|
262
|
+
const file = await sdk.storage.upload({
|
|
263
|
+
name: 'document.pdf',
|
|
264
|
+
type: 'application/pdf',
|
|
265
|
+
size: fileBuffer.byteLength,
|
|
266
|
+
data: btoa(String.fromCharCode(...new Uint8Array(fileBuffer))),
|
|
267
|
+
folder: 'documents'
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
console.log(file.url) // URL to access the file
|
|
271
|
+
|
|
272
|
+
// List files
|
|
273
|
+
const { items } = await sdk.storage.list({ folder: 'documents' })
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
### Files (`sdk.files`)
|
|
279
|
+
|
|
280
|
+
For large file uploads using presigned URLs:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
interface FilesService {
|
|
284
|
+
initiate(options: InitiateOptions): Promise<{
|
|
285
|
+
id: string
|
|
286
|
+
name: string
|
|
287
|
+
signedUrl: string
|
|
288
|
+
signedData: Record<string, string>
|
|
289
|
+
}>
|
|
290
|
+
get(fileId: string): Promise<FileMetadata>
|
|
291
|
+
delete(fileId: string): Promise<void>
|
|
292
|
+
list(options?: ListOptions): Promise<{ items: FileMetadata[]; nextCursor?: string }>
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Example:**
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
// Initiate upload to get presigned URL
|
|
300
|
+
const { signedUrl, signedData, id } = await sdk.files.initiate({
|
|
301
|
+
name: 'large-video.mp4',
|
|
302
|
+
contentType: 'video/mp4',
|
|
303
|
+
contentLength: file.size
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
// Upload directly to storage
|
|
307
|
+
const formData = new FormData()
|
|
308
|
+
Object.entries(signedData).forEach(([key, value]) => {
|
|
309
|
+
formData.append(key, value)
|
|
310
|
+
})
|
|
311
|
+
formData.append('file', file)
|
|
312
|
+
|
|
313
|
+
await fetch(signedUrl, { method: 'POST', body: formData })
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### Logging (`sdk.log`)
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
interface LogService {
|
|
322
|
+
info(message: string, data?: Record<string, unknown>): void
|
|
323
|
+
warn(message: string, data?: Record<string, unknown>): void
|
|
324
|
+
error(message: string, data?: Record<string, unknown>): void
|
|
325
|
+
event(name: string, properties?: Record<string, unknown>): void
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Example:**
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// Log messages
|
|
333
|
+
sdk.log.info('User completed onboarding', { userId: user.id })
|
|
334
|
+
sdk.log.warn('API rate limit approaching', { remaining: 10 })
|
|
335
|
+
sdk.log.error('Failed to save', { error: err.message })
|
|
336
|
+
|
|
337
|
+
// Track analytics events
|
|
338
|
+
sdk.log.event('button_clicked', { buttonId: 'submit', page: 'checkout' })
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
### Config (`sdk.config`)
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
interface ConfigService {
|
|
347
|
+
readonly features: Record<string, unknown>
|
|
348
|
+
readonly app: { id?: string; name?: string; environment?: string }
|
|
349
|
+
get(key: string): Promise<unknown>
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Example:**
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// Check feature flags
|
|
357
|
+
if (sdk.config.features.newDashboard) {
|
|
358
|
+
// Show new dashboard
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Get app info
|
|
362
|
+
console.log(sdk.config.app.environment) // 'production' | 'staging' | 'development'
|
|
363
|
+
|
|
364
|
+
// Get specific config value
|
|
365
|
+
const apiUrl = await sdk.config.get('apiBaseUrl')
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
### Entity Changes
|
|
371
|
+
|
|
372
|
+
Subscribe to real-time entity changes for cache invalidation:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
const unsubscribe = sdk.onEntityChange((event) => {
|
|
376
|
+
console.log('Entity changed:', event)
|
|
377
|
+
// event.changeType: 'entity.created' | 'entity.updated' | 'entity.deleted'
|
|
378
|
+
// event.entityId: 'projects'
|
|
379
|
+
// event.id: 'project-123'
|
|
380
|
+
|
|
381
|
+
// Invalidate your cache
|
|
382
|
+
if (event.entityId === 'projects') {
|
|
383
|
+
refetchProjects()
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## TypeScript
|
|
391
|
+
|
|
392
|
+
Full TypeScript support with exported types:
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import type {
|
|
396
|
+
FoundationClient,
|
|
397
|
+
User,
|
|
398
|
+
Theme,
|
|
399
|
+
RouterState,
|
|
400
|
+
EntityChangeEvent,
|
|
401
|
+
AuthService,
|
|
402
|
+
DbService,
|
|
403
|
+
UIService,
|
|
404
|
+
// ... more types
|
|
405
|
+
} from 'foundation-iframe-sdk'
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Architecture
|
|
411
|
+
|
|
412
|
+
See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed diagrams of how the SDK communicates with the container.
|
|
413
|
+
|
|
414
|
+
## License
|
|
415
|
+
|
|
416
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
let clientInstance = null;
|
|
4
|
+
function createFoundationClient() {
|
|
5
|
+
if (clientInstance) {
|
|
6
|
+
return clientInstance;
|
|
7
|
+
}
|
|
8
|
+
let isReady = false;
|
|
9
|
+
let readyResolve = null;
|
|
10
|
+
let messageId = 0;
|
|
11
|
+
const pendingRequests = /* @__PURE__ */ new Map();
|
|
12
|
+
let user = null;
|
|
13
|
+
let theme = { isDark: false, mode: "system" };
|
|
14
|
+
let router = { path: "/", query: {}, hash: "" };
|
|
15
|
+
let config = { features: {}, app: {} };
|
|
16
|
+
let entities = [];
|
|
17
|
+
const themeListeners = [];
|
|
18
|
+
const authListeners = [];
|
|
19
|
+
const routerListeners = [];
|
|
20
|
+
const entityListeners = [];
|
|
21
|
+
const readyPromise = new Promise((resolve) => {
|
|
22
|
+
readyResolve = resolve;
|
|
23
|
+
});
|
|
24
|
+
function send(namespace, type, data = {}) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const id = ++messageId;
|
|
27
|
+
pendingRequests.set(id, {
|
|
28
|
+
resolve,
|
|
29
|
+
reject
|
|
30
|
+
});
|
|
31
|
+
window.parent.postMessage({
|
|
32
|
+
id,
|
|
33
|
+
namespace,
|
|
34
|
+
type: `${namespace}.${type}`,
|
|
35
|
+
data
|
|
36
|
+
}, "*");
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
if (pendingRequests.has(id)) {
|
|
39
|
+
pendingRequests.delete(id);
|
|
40
|
+
reject(new Error(`Request timeout: ${namespace}.${type}`));
|
|
41
|
+
}
|
|
42
|
+
}, 3e4);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function handleMessage(event) {
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
const message = event.data;
|
|
48
|
+
if ((message == null ? void 0 : message.type) === "SDK_READY") {
|
|
49
|
+
const payload = message.data;
|
|
50
|
+
user = payload.user || null;
|
|
51
|
+
theme = payload.theme || { isDark: false, mode: "system" };
|
|
52
|
+
router = payload.router || { path: "/", query: {}, hash: "" };
|
|
53
|
+
config = {
|
|
54
|
+
features: ((_a = payload.config) == null ? void 0 : _a.features) || {},
|
|
55
|
+
app: ((_b = payload.config) == null ? void 0 : _b.app) || {}
|
|
56
|
+
};
|
|
57
|
+
entities = payload.entities || [];
|
|
58
|
+
if (!isReady) {
|
|
59
|
+
isReady = true;
|
|
60
|
+
readyResolve == null ? void 0 : readyResolve();
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if ((message == null ? void 0 : message.type) === "THEME_CHANGED") {
|
|
65
|
+
theme = message.data;
|
|
66
|
+
themeListeners.forEach((fn) => {
|
|
67
|
+
try {
|
|
68
|
+
fn(theme);
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if ((message == null ? void 0 : message.type) === "AUTH_CHANGED") {
|
|
75
|
+
user = ((_c = message.data) == null ? void 0 : _c.user) || null;
|
|
76
|
+
authListeners.forEach((fn) => {
|
|
77
|
+
try {
|
|
78
|
+
fn(user);
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if ((message == null ? void 0 : message.type) === "ROUTER_CHANGED") {
|
|
85
|
+
router = message.data;
|
|
86
|
+
routerListeners.forEach((fn) => {
|
|
87
|
+
try {
|
|
88
|
+
fn(router);
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if ((message == null ? void 0 : message.type) === "ENTITY_CHANGED") {
|
|
95
|
+
const event2 = message.data;
|
|
96
|
+
entityListeners.forEach((fn) => {
|
|
97
|
+
try {
|
|
98
|
+
fn(event2);
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (typeof (message == null ? void 0 : message.id) === "number" && pendingRequests.has(message.id)) {
|
|
105
|
+
const { resolve, reject } = pendingRequests.get(message.id);
|
|
106
|
+
pendingRequests.delete(message.id);
|
|
107
|
+
const response = message;
|
|
108
|
+
if (response.success) {
|
|
109
|
+
resolve(response.data);
|
|
110
|
+
} else {
|
|
111
|
+
reject(new Error(response.error || "Unknown error"));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
window.addEventListener("message", handleMessage);
|
|
116
|
+
const authService = {
|
|
117
|
+
get user() {
|
|
118
|
+
return user;
|
|
119
|
+
},
|
|
120
|
+
get isAuthenticated() {
|
|
121
|
+
return !!user;
|
|
122
|
+
},
|
|
123
|
+
getToken: () => send("auth", "getToken"),
|
|
124
|
+
login: () => send("auth", "login"),
|
|
125
|
+
logout: () => send("auth", "logout"),
|
|
126
|
+
onChange(callback) {
|
|
127
|
+
authListeners.push(callback);
|
|
128
|
+
return () => {
|
|
129
|
+
const idx = authListeners.indexOf(callback);
|
|
130
|
+
if (idx > -1) authListeners.splice(idx, 1);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const themeService = {
|
|
135
|
+
get isDark() {
|
|
136
|
+
return theme.isDark;
|
|
137
|
+
},
|
|
138
|
+
get mode() {
|
|
139
|
+
return theme.mode;
|
|
140
|
+
},
|
|
141
|
+
setTheme: (mode) => send("ui", "setTheme", { mode }),
|
|
142
|
+
toggle: () => send("ui", "toggleTheme", {}),
|
|
143
|
+
onChange(callback) {
|
|
144
|
+
themeListeners.push(callback);
|
|
145
|
+
return () => {
|
|
146
|
+
const idx = themeListeners.indexOf(callback);
|
|
147
|
+
if (idx > -1) themeListeners.splice(idx, 1);
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const routerService = {
|
|
152
|
+
get path() {
|
|
153
|
+
return router.path;
|
|
154
|
+
},
|
|
155
|
+
get query() {
|
|
156
|
+
return router.query;
|
|
157
|
+
},
|
|
158
|
+
get hash() {
|
|
159
|
+
return router.hash;
|
|
160
|
+
},
|
|
161
|
+
push: (path, options = {}) => send("router", "push", { path, ...options }),
|
|
162
|
+
replace: (path, options = {}) => send("router", "replace", { path, ...options }),
|
|
163
|
+
setQuery: (params, options = {}) => send("router", "setQuery", { params, ...options }),
|
|
164
|
+
onChange(callback) {
|
|
165
|
+
routerListeners.push(callback);
|
|
166
|
+
return () => {
|
|
167
|
+
const idx = routerListeners.indexOf(callback);
|
|
168
|
+
if (idx > -1) routerListeners.splice(idx, 1);
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
const dbService = {
|
|
173
|
+
list: (entity, options = {}) => send("db", "list", { entity, ...options }),
|
|
174
|
+
get: (entity, id) => send("db", "get", { entity, itemId: id }),
|
|
175
|
+
create: (entity, item) => send("db", "create", { entity, item }),
|
|
176
|
+
update: (entity, id, updates) => send("db", "update", { entity, itemId: id, updates }),
|
|
177
|
+
delete: (entity, id) => send("db", "delete", { entity, itemId: id })
|
|
178
|
+
};
|
|
179
|
+
const uiService = {
|
|
180
|
+
toast: (message, type = "info") => send("ui", "toast", { message, toastType: type }),
|
|
181
|
+
confirm: (message) => send("ui", "confirm", { message }),
|
|
182
|
+
loading: {
|
|
183
|
+
show: (message) => send("ui", "loading.show", { message }),
|
|
184
|
+
hide: () => send("ui", "loading.hide", {})
|
|
185
|
+
},
|
|
186
|
+
banner: {
|
|
187
|
+
show: (message, options = {}) => send("ui", "banner.show", { message, ...options }),
|
|
188
|
+
hide: (bannerId) => send("ui", "banner.hide", { bannerId })
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const storageService = {
|
|
192
|
+
upload: (options) => send("storage", "upload", options),
|
|
193
|
+
get: (fileId) => send("storage", "get", { fileId }),
|
|
194
|
+
delete: (fileId) => send("storage", "delete", { fileId }),
|
|
195
|
+
list: (options = {}) => send("storage", "list", options)
|
|
196
|
+
};
|
|
197
|
+
const filesService = {
|
|
198
|
+
initiate: (options) => send("files", "initiate", options),
|
|
199
|
+
get: (fileId) => send("files", "get", { fileId }),
|
|
200
|
+
delete: (fileId) => send("files", "delete", { fileId }),
|
|
201
|
+
list: (options = {}) => send("files", "list", options)
|
|
202
|
+
};
|
|
203
|
+
const logService = {
|
|
204
|
+
info: (message, data) => {
|
|
205
|
+
send("log", "info", { message, data }).catch(() => {
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
warn: (message, data) => {
|
|
209
|
+
send("log", "warn", { message, data }).catch(() => {
|
|
210
|
+
});
|
|
211
|
+
},
|
|
212
|
+
error: (message, data) => {
|
|
213
|
+
send("log", "error", { message, data }).catch(() => {
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
event: (name, properties) => {
|
|
217
|
+
send("log", "event", { name, properties }).catch(() => {
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const configService = {
|
|
222
|
+
get features() {
|
|
223
|
+
return config.features;
|
|
224
|
+
},
|
|
225
|
+
get app() {
|
|
226
|
+
return config.app;
|
|
227
|
+
},
|
|
228
|
+
get: (key) => send("config", "get", { key })
|
|
229
|
+
};
|
|
230
|
+
clientInstance = {
|
|
231
|
+
get ready() {
|
|
232
|
+
return readyPromise;
|
|
233
|
+
},
|
|
234
|
+
get isReady() {
|
|
235
|
+
return isReady;
|
|
236
|
+
},
|
|
237
|
+
auth: authService,
|
|
238
|
+
// only logout - this is problematic - provides user and account
|
|
239
|
+
theme: themeService,
|
|
240
|
+
// only useful for themed tailwind projects - still useful anyway
|
|
241
|
+
router: routerService,
|
|
242
|
+
// once you're in app - external or container-ui level routing it just not very useful.
|
|
243
|
+
db: dbService,
|
|
244
|
+
ui: uiService,
|
|
245
|
+
storage: storageService,
|
|
246
|
+
files: filesService,
|
|
247
|
+
log: logService,
|
|
248
|
+
config: configService,
|
|
249
|
+
onEntityChange(callback) {
|
|
250
|
+
entityListeners.push(callback);
|
|
251
|
+
return () => {
|
|
252
|
+
const idx = entityListeners.indexOf(callback);
|
|
253
|
+
if (idx > -1) entityListeners.splice(idx, 1);
|
|
254
|
+
};
|
|
255
|
+
},
|
|
256
|
+
get entities() {
|
|
257
|
+
return entities;
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
return clientInstance;
|
|
261
|
+
}
|
|
262
|
+
function resetFoundationClient() {
|
|
263
|
+
clientInstance = null;
|
|
264
|
+
}
|
|
265
|
+
exports.createFoundationClient = createFoundationClient;
|
|
266
|
+
exports.resetFoundationClient = resetFoundationClient;
|
|
267
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/client.ts"],"sourcesContent":["import type {\n FoundationClient,\n User,\n Theme,\n RouterState,\n EntityDefinition,\n EntityChangeEvent,\n SDKReadyPayload,\n SDKResponse,\n AuthService,\n ThemeService,\n RouterService,\n DbService,\n UIService,\n StorageService,\n FilesService,\n LogService,\n ConfigService\n} from './types'\n\nlet clientInstance: FoundationClient | null = null\n\nexport function createFoundationClient(): FoundationClient {\n if (clientInstance) {\n return clientInstance\n }\n\n let isReady = false\n let readyResolve: (() => void) | null = null\n let messageId = 0\n const pendingRequests = new Map<number, { resolve: (data: unknown) => void; reject: (error: Error) => void }>()\n\n let user: User | null = null\n let theme: Theme = { isDark: false, mode: 'system' }\n let router: RouterState = { path: '/', query: {}, hash: '' }\n let config: { features: Record<string, unknown>; app: { id?: string; name?: string; environment?: string } } = { features: {}, app: {} }\n let entities: EntityDefinition[] = []\n\n const themeListeners: Array<(theme: Theme) => void> = []\n const authListeners: Array<(user: User | null) => void> = []\n const routerListeners: Array<(route: RouterState) => void> = []\n const entityListeners: Array<(event: EntityChangeEvent) => void> = []\n\n const readyPromise = new Promise<void>((resolve) => {\n readyResolve = resolve\n })\n\n function send<T = unknown>(namespace: string, type: string, data: Record<string, unknown> = {}): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = ++messageId\n pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject\n })\n\n window.parent.postMessage({\n id,\n namespace,\n type: `${namespace}.${type}`,\n data\n }, '*')\n\n setTimeout(() => {\n if (pendingRequests.has(id)) {\n pendingRequests.delete(id)\n reject(new Error(`Request timeout: ${namespace}.${type}`))\n }\n }, 30000)\n })\n }\n\n function handleMessage(event: MessageEvent) {\n const message = event.data\n\n if (message?.type === 'SDK_READY') {\n const payload = message.data as SDKReadyPayload\n user = payload.user || null\n theme = payload.theme || { isDark: false, mode: 'system' }\n router = payload.router || { path: '/', query: {}, hash: '' }\n config = {\n features: payload.config?.features || {},\n app: payload.config?.app || {}\n }\n entities = payload.entities || []\n\n if (!isReady) {\n isReady = true\n readyResolve?.()\n }\n return\n }\n\n if (message?.type === 'THEME_CHANGED') {\n theme = message.data as Theme\n themeListeners.forEach(fn => {\n try { fn(theme) } catch { /* ignore */ }\n })\n return\n }\n\n if (message?.type === 'AUTH_CHANGED') {\n user = message.data?.user || null\n authListeners.forEach(fn => {\n try { fn(user) } catch { /* ignore */ }\n })\n return\n }\n\n if (message?.type === 'ROUTER_CHANGED') {\n router = message.data as RouterState\n routerListeners.forEach(fn => {\n try { fn(router) } catch { /* ignore */ }\n })\n return\n }\n\n if (message?.type === 'ENTITY_CHANGED') {\n const event = message.data as EntityChangeEvent\n entityListeners.forEach(fn => {\n try { fn(event) } catch { /* ignore */ }\n })\n return\n }\n\n if (typeof message?.id === 'number' && pendingRequests.has(message.id)) {\n const { resolve, reject } = pendingRequests.get(message.id)!\n pendingRequests.delete(message.id)\n\n const response = message as SDKResponse\n if (response.success) {\n resolve(response.data)\n } else {\n reject(new Error(response.error || 'Unknown error'))\n }\n }\n }\n\n window.addEventListener('message', handleMessage)\n\n const authService: AuthService = {\n get user() { return user },\n get isAuthenticated() { return !!user },\n getToken: () => send<string>('auth', 'getToken'),\n login: () => send<void>('auth', 'login'),\n logout: () => send<void>('auth', 'logout'),\n onChange(callback) {\n authListeners.push(callback)\n return () => {\n const idx = authListeners.indexOf(callback)\n if (idx > -1) authListeners.splice(idx, 1)\n }\n }\n }\n\n const themeService: ThemeService = {\n get isDark() { return theme.isDark },\n get mode() { return theme.mode },\n setTheme: (mode) => send<void>('ui', 'setTheme', { mode }),\n toggle: () => send<void>('ui', 'toggleTheme', {}),\n onChange(callback) {\n themeListeners.push(callback)\n return () => {\n const idx = themeListeners.indexOf(callback)\n if (idx > -1) themeListeners.splice(idx, 1)\n }\n }\n }\n\n const routerService: RouterService = {\n get path() { return router.path },\n get query() { return router.query },\n get hash() { return router.hash },\n push: (path, options = {}) => send<void>('router', 'push', { path, ...options }),\n replace: (path, options = {}) => send<void>('router', 'replace', { path, ...options }),\n setQuery: (params, options = {}) => send<void>('router', 'setQuery', { params, ...options }),\n onChange(callback) {\n routerListeners.push(callback)\n return () => {\n const idx = routerListeners.indexOf(callback)\n if (idx > -1) routerListeners.splice(idx, 1)\n }\n }\n }\n\n const dbService: DbService = {\n list: (entity, options = {}) => send('db', 'list', { entity, ...options }),\n get: (entity, id) => send('db', 'get', { entity, itemId: id }),\n create: (entity, item) => send('db', 'create', { entity, item }),\n update: (entity, id, updates) => send('db', 'update', { entity, itemId: id, updates }),\n delete: (entity, id) => send('db', 'delete', { entity, itemId: id })\n }\n\n const uiService: UIService = {\n toast: (message, type = 'info') => send('ui', 'toast', { message, toastType: type }),\n confirm: (message) => send('ui', 'confirm', { message }),\n loading: {\n show: (message) => send('ui', 'loading.show', { message }),\n hide: () => send('ui', 'loading.hide', {})\n },\n banner: {\n show: (message, options = {}) => send('ui', 'banner.show', { message, ...options }),\n hide: (bannerId) => send('ui', 'banner.hide', { bannerId })\n }\n }\n\n const storageService: StorageService = {\n upload: (options) => send('storage', 'upload', options),\n get: (fileId) => send('storage', 'get', { fileId }),\n delete: (fileId) => send('storage', 'delete', { fileId }),\n list: (options = {}) => send('storage', 'list', options)\n }\n\n const filesService: FilesService = {\n initiate: (options) => send('files', 'initiate', options),\n get: (fileId) => send('files', 'get', { fileId }),\n delete: (fileId) => send('files', 'delete', { fileId }),\n list: (options = {}) => send('files', 'list', options)\n }\n\n const logService: LogService = {\n info: (message, data) => { send('log', 'info', { message, data }).catch(() => {}) },\n warn: (message, data) => { send('log', 'warn', { message, data }).catch(() => {}) },\n error: (message, data) => { send('log', 'error', { message, data }).catch(() => {}) },\n event: (name, properties) => { send('log', 'event', { name, properties }).catch(() => {}) }\n }\n\n const configService: ConfigService = {\n get features() { return config.features },\n get app() { return config.app },\n get: (key) => send('config', 'get', { key })\n }\n\n clientInstance = {\n get ready() { return readyPromise },\n get isReady() { return isReady },\n\n auth: authService, // only logout - this is problematic - provides user and account\n theme: themeService, // only useful for themed tailwind projects - still useful anyway\n router: routerService, // once you're in app - external or container-ui level routing it just not very useful.\n db: dbService,\n ui: uiService,\n storage: storageService,\n files: filesService,\n log: logService,\n config: configService,\n\n onEntityChange(callback) {\n entityListeners.push(callback)\n return () => {\n const idx = entityListeners.indexOf(callback)\n if (idx > -1) entityListeners.splice(idx, 1)\n }\n },\n\n get entities() { return entities }\n }\n\n return clientInstance\n}\n\nexport function resetFoundationClient(): void {\n clientInstance = null\n}\n"],"names":["event"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
export declare interface AuthService {
|
|
2
|
+
readonly user: User | null;
|
|
3
|
+
readonly isAuthenticated: boolean;
|
|
4
|
+
getToken(): Promise<string>;
|
|
5
|
+
login(): Promise<void>;
|
|
6
|
+
logout(): Promise<void>;
|
|
7
|
+
onChange(callback: (user: User | null) => void): () => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export declare interface ConfigService {
|
|
11
|
+
readonly features: Record<string, unknown>;
|
|
12
|
+
readonly app: {
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
environment?: string;
|
|
16
|
+
};
|
|
17
|
+
get(key: string): Promise<unknown>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export declare function createFoundationClient(): FoundationClient;
|
|
21
|
+
|
|
22
|
+
export declare interface DbService {
|
|
23
|
+
list<T = unknown>(entity: string, options?: {
|
|
24
|
+
filters?: Record<string, unknown>;
|
|
25
|
+
limit?: number;
|
|
26
|
+
cursor?: string;
|
|
27
|
+
orderBy?: string;
|
|
28
|
+
orderDir?: 'asc' | 'desc';
|
|
29
|
+
}): Promise<{
|
|
30
|
+
items: T[];
|
|
31
|
+
nextCursor?: string;
|
|
32
|
+
}>;
|
|
33
|
+
get<T = unknown>(entity: string, id: string): Promise<T>;
|
|
34
|
+
create<T = unknown>(entity: string, data: Partial<T>): Promise<T>;
|
|
35
|
+
update<T = unknown>(entity: string, id: string, updates: Partial<T>): Promise<T>;
|
|
36
|
+
delete(entity: string, id: string): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export declare interface EntityChangeEvent {
|
|
40
|
+
changeType: string;
|
|
41
|
+
entityId?: string;
|
|
42
|
+
id?: string;
|
|
43
|
+
namespace?: string;
|
|
44
|
+
timestamp?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export declare interface EntityDefinition {
|
|
48
|
+
name: string;
|
|
49
|
+
schema?: Record<string, unknown>;
|
|
50
|
+
methods?: string[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export declare interface FileMetadata {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
type: string;
|
|
57
|
+
size: number;
|
|
58
|
+
url: string;
|
|
59
|
+
folder?: string;
|
|
60
|
+
metadata?: Record<string, unknown>;
|
|
61
|
+
createdAt: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export declare interface FilesService {
|
|
65
|
+
initiate(options: {
|
|
66
|
+
name: string;
|
|
67
|
+
contentType: string;
|
|
68
|
+
contentLength: number;
|
|
69
|
+
metadata?: Record<string, unknown>;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
signedUrl: string;
|
|
74
|
+
signedData: Record<string, string>;
|
|
75
|
+
}>;
|
|
76
|
+
get(fileId: string): Promise<FileMetadata>;
|
|
77
|
+
delete(fileId: string): Promise<void>;
|
|
78
|
+
list(options?: {
|
|
79
|
+
limit?: number;
|
|
80
|
+
cursor?: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
items: FileMetadata[];
|
|
83
|
+
nextCursor?: string;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export declare interface FoundationClient {
|
|
88
|
+
readonly ready: Promise<void>;
|
|
89
|
+
readonly isReady: boolean;
|
|
90
|
+
auth: AuthService;
|
|
91
|
+
theme: ThemeService;
|
|
92
|
+
router: RouterService;
|
|
93
|
+
db: DbService;
|
|
94
|
+
ui: UIService;
|
|
95
|
+
storage: StorageService;
|
|
96
|
+
files: FilesService;
|
|
97
|
+
log: LogService;
|
|
98
|
+
config: ConfigService;
|
|
99
|
+
onEntityChange(callback: (event: EntityChangeEvent) => void): () => void;
|
|
100
|
+
readonly entities: EntityDefinition[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export declare interface LogService {
|
|
104
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
105
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
106
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
107
|
+
event(name: string, properties?: Record<string, unknown>): void;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export declare function resetFoundationClient(): void;
|
|
111
|
+
|
|
112
|
+
export declare interface RouterService {
|
|
113
|
+
readonly path: string;
|
|
114
|
+
readonly query: Record<string, string>;
|
|
115
|
+
readonly hash: string;
|
|
116
|
+
push(path: string, options?: {
|
|
117
|
+
query?: Record<string, string>;
|
|
118
|
+
hash?: string;
|
|
119
|
+
}): Promise<void>;
|
|
120
|
+
replace(path: string, options?: {
|
|
121
|
+
query?: Record<string, string>;
|
|
122
|
+
hash?: string;
|
|
123
|
+
}): Promise<void>;
|
|
124
|
+
setQuery(params: Record<string, string>, options?: {
|
|
125
|
+
replace?: boolean;
|
|
126
|
+
}): Promise<void>;
|
|
127
|
+
onChange(callback: (route: RouterState) => void): () => void;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export declare interface RouterState {
|
|
131
|
+
path: string;
|
|
132
|
+
query: Record<string, string>;
|
|
133
|
+
hash: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export declare interface StorageService {
|
|
137
|
+
upload(options: {
|
|
138
|
+
name: string;
|
|
139
|
+
type: string;
|
|
140
|
+
size: number;
|
|
141
|
+
data: string;
|
|
142
|
+
folder?: string;
|
|
143
|
+
metadata?: Record<string, unknown>;
|
|
144
|
+
}): Promise<{
|
|
145
|
+
id: string;
|
|
146
|
+
url: string;
|
|
147
|
+
name: string;
|
|
148
|
+
}>;
|
|
149
|
+
get(fileId: string): Promise<FileMetadata>;
|
|
150
|
+
delete(fileId: string): Promise<void>;
|
|
151
|
+
list(options?: {
|
|
152
|
+
folder?: string;
|
|
153
|
+
limit?: number;
|
|
154
|
+
cursor?: string;
|
|
155
|
+
}): Promise<{
|
|
156
|
+
items: FileMetadata[];
|
|
157
|
+
nextCursor?: string;
|
|
158
|
+
}>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export declare interface Theme {
|
|
162
|
+
isDark: boolean;
|
|
163
|
+
mode: 'light' | 'dark' | 'system';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export declare interface ThemeService {
|
|
167
|
+
readonly isDark: boolean;
|
|
168
|
+
readonly mode: 'light' | 'dark' | 'system';
|
|
169
|
+
setTheme(mode: 'light' | 'dark' | 'system'): Promise<void>;
|
|
170
|
+
toggle(): Promise<void>;
|
|
171
|
+
onChange(callback: (theme: Theme) => void): () => void;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export declare interface UIService {
|
|
175
|
+
toast(message: string, type?: 'success' | 'error' | 'warn' | 'info'): Promise<void>;
|
|
176
|
+
confirm(message: string): Promise<{
|
|
177
|
+
confirmed: boolean;
|
|
178
|
+
}>;
|
|
179
|
+
loading: {
|
|
180
|
+
show(message?: string): Promise<void>;
|
|
181
|
+
hide(): Promise<void>;
|
|
182
|
+
};
|
|
183
|
+
banner: {
|
|
184
|
+
show(message: string, options?: {
|
|
185
|
+
type?: 'info' | 'warning' | 'error' | 'success';
|
|
186
|
+
dismissible?: boolean;
|
|
187
|
+
}): Promise<{
|
|
188
|
+
bannerId: string;
|
|
189
|
+
}>;
|
|
190
|
+
hide(bannerId: string): Promise<void>;
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export declare interface User {
|
|
195
|
+
id: string;
|
|
196
|
+
email: string;
|
|
197
|
+
name?: string;
|
|
198
|
+
picture?: string;
|
|
199
|
+
[key: string]: unknown;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
let clientInstance = null;
|
|
2
|
+
function createFoundationClient() {
|
|
3
|
+
if (clientInstance) {
|
|
4
|
+
return clientInstance;
|
|
5
|
+
}
|
|
6
|
+
let isReady = false;
|
|
7
|
+
let readyResolve = null;
|
|
8
|
+
let messageId = 0;
|
|
9
|
+
const pendingRequests = /* @__PURE__ */ new Map();
|
|
10
|
+
let user = null;
|
|
11
|
+
let theme = { isDark: false, mode: "system" };
|
|
12
|
+
let router = { path: "/", query: {}, hash: "" };
|
|
13
|
+
let config = { features: {}, app: {} };
|
|
14
|
+
let entities = [];
|
|
15
|
+
const themeListeners = [];
|
|
16
|
+
const authListeners = [];
|
|
17
|
+
const routerListeners = [];
|
|
18
|
+
const entityListeners = [];
|
|
19
|
+
const readyPromise = new Promise((resolve) => {
|
|
20
|
+
readyResolve = resolve;
|
|
21
|
+
});
|
|
22
|
+
function send(namespace, type, data = {}) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const id = ++messageId;
|
|
25
|
+
pendingRequests.set(id, {
|
|
26
|
+
resolve,
|
|
27
|
+
reject
|
|
28
|
+
});
|
|
29
|
+
window.parent.postMessage({
|
|
30
|
+
id,
|
|
31
|
+
namespace,
|
|
32
|
+
type: `${namespace}.${type}`,
|
|
33
|
+
data
|
|
34
|
+
}, "*");
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
if (pendingRequests.has(id)) {
|
|
37
|
+
pendingRequests.delete(id);
|
|
38
|
+
reject(new Error(`Request timeout: ${namespace}.${type}`));
|
|
39
|
+
}
|
|
40
|
+
}, 3e4);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function handleMessage(event) {
|
|
44
|
+
var _a, _b, _c;
|
|
45
|
+
const message = event.data;
|
|
46
|
+
if ((message == null ? void 0 : message.type) === "SDK_READY") {
|
|
47
|
+
const payload = message.data;
|
|
48
|
+
user = payload.user || null;
|
|
49
|
+
theme = payload.theme || { isDark: false, mode: "system" };
|
|
50
|
+
router = payload.router || { path: "/", query: {}, hash: "" };
|
|
51
|
+
config = {
|
|
52
|
+
features: ((_a = payload.config) == null ? void 0 : _a.features) || {},
|
|
53
|
+
app: ((_b = payload.config) == null ? void 0 : _b.app) || {}
|
|
54
|
+
};
|
|
55
|
+
entities = payload.entities || [];
|
|
56
|
+
if (!isReady) {
|
|
57
|
+
isReady = true;
|
|
58
|
+
readyResolve == null ? void 0 : readyResolve();
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if ((message == null ? void 0 : message.type) === "THEME_CHANGED") {
|
|
63
|
+
theme = message.data;
|
|
64
|
+
themeListeners.forEach((fn) => {
|
|
65
|
+
try {
|
|
66
|
+
fn(theme);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if ((message == null ? void 0 : message.type) === "AUTH_CHANGED") {
|
|
73
|
+
user = ((_c = message.data) == null ? void 0 : _c.user) || null;
|
|
74
|
+
authListeners.forEach((fn) => {
|
|
75
|
+
try {
|
|
76
|
+
fn(user);
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if ((message == null ? void 0 : message.type) === "ROUTER_CHANGED") {
|
|
83
|
+
router = message.data;
|
|
84
|
+
routerListeners.forEach((fn) => {
|
|
85
|
+
try {
|
|
86
|
+
fn(router);
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if ((message == null ? void 0 : message.type) === "ENTITY_CHANGED") {
|
|
93
|
+
const event2 = message.data;
|
|
94
|
+
entityListeners.forEach((fn) => {
|
|
95
|
+
try {
|
|
96
|
+
fn(event2);
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (typeof (message == null ? void 0 : message.id) === "number" && pendingRequests.has(message.id)) {
|
|
103
|
+
const { resolve, reject } = pendingRequests.get(message.id);
|
|
104
|
+
pendingRequests.delete(message.id);
|
|
105
|
+
const response = message;
|
|
106
|
+
if (response.success) {
|
|
107
|
+
resolve(response.data);
|
|
108
|
+
} else {
|
|
109
|
+
reject(new Error(response.error || "Unknown error"));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
window.addEventListener("message", handleMessage);
|
|
114
|
+
const authService = {
|
|
115
|
+
get user() {
|
|
116
|
+
return user;
|
|
117
|
+
},
|
|
118
|
+
get isAuthenticated() {
|
|
119
|
+
return !!user;
|
|
120
|
+
},
|
|
121
|
+
getToken: () => send("auth", "getToken"),
|
|
122
|
+
login: () => send("auth", "login"),
|
|
123
|
+
logout: () => send("auth", "logout"),
|
|
124
|
+
onChange(callback) {
|
|
125
|
+
authListeners.push(callback);
|
|
126
|
+
return () => {
|
|
127
|
+
const idx = authListeners.indexOf(callback);
|
|
128
|
+
if (idx > -1) authListeners.splice(idx, 1);
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const themeService = {
|
|
133
|
+
get isDark() {
|
|
134
|
+
return theme.isDark;
|
|
135
|
+
},
|
|
136
|
+
get mode() {
|
|
137
|
+
return theme.mode;
|
|
138
|
+
},
|
|
139
|
+
setTheme: (mode) => send("ui", "setTheme", { mode }),
|
|
140
|
+
toggle: () => send("ui", "toggleTheme", {}),
|
|
141
|
+
onChange(callback) {
|
|
142
|
+
themeListeners.push(callback);
|
|
143
|
+
return () => {
|
|
144
|
+
const idx = themeListeners.indexOf(callback);
|
|
145
|
+
if (idx > -1) themeListeners.splice(idx, 1);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const routerService = {
|
|
150
|
+
get path() {
|
|
151
|
+
return router.path;
|
|
152
|
+
},
|
|
153
|
+
get query() {
|
|
154
|
+
return router.query;
|
|
155
|
+
},
|
|
156
|
+
get hash() {
|
|
157
|
+
return router.hash;
|
|
158
|
+
},
|
|
159
|
+
push: (path, options = {}) => send("router", "push", { path, ...options }),
|
|
160
|
+
replace: (path, options = {}) => send("router", "replace", { path, ...options }),
|
|
161
|
+
setQuery: (params, options = {}) => send("router", "setQuery", { params, ...options }),
|
|
162
|
+
onChange(callback) {
|
|
163
|
+
routerListeners.push(callback);
|
|
164
|
+
return () => {
|
|
165
|
+
const idx = routerListeners.indexOf(callback);
|
|
166
|
+
if (idx > -1) routerListeners.splice(idx, 1);
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const dbService = {
|
|
171
|
+
list: (entity, options = {}) => send("db", "list", { entity, ...options }),
|
|
172
|
+
get: (entity, id) => send("db", "get", { entity, itemId: id }),
|
|
173
|
+
create: (entity, item) => send("db", "create", { entity, item }),
|
|
174
|
+
update: (entity, id, updates) => send("db", "update", { entity, itemId: id, updates }),
|
|
175
|
+
delete: (entity, id) => send("db", "delete", { entity, itemId: id })
|
|
176
|
+
};
|
|
177
|
+
const uiService = {
|
|
178
|
+
toast: (message, type = "info") => send("ui", "toast", { message, toastType: type }),
|
|
179
|
+
confirm: (message) => send("ui", "confirm", { message }),
|
|
180
|
+
loading: {
|
|
181
|
+
show: (message) => send("ui", "loading.show", { message }),
|
|
182
|
+
hide: () => send("ui", "loading.hide", {})
|
|
183
|
+
},
|
|
184
|
+
banner: {
|
|
185
|
+
show: (message, options = {}) => send("ui", "banner.show", { message, ...options }),
|
|
186
|
+
hide: (bannerId) => send("ui", "banner.hide", { bannerId })
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
const storageService = {
|
|
190
|
+
upload: (options) => send("storage", "upload", options),
|
|
191
|
+
get: (fileId) => send("storage", "get", { fileId }),
|
|
192
|
+
delete: (fileId) => send("storage", "delete", { fileId }),
|
|
193
|
+
list: (options = {}) => send("storage", "list", options)
|
|
194
|
+
};
|
|
195
|
+
const filesService = {
|
|
196
|
+
initiate: (options) => send("files", "initiate", options),
|
|
197
|
+
get: (fileId) => send("files", "get", { fileId }),
|
|
198
|
+
delete: (fileId) => send("files", "delete", { fileId }),
|
|
199
|
+
list: (options = {}) => send("files", "list", options)
|
|
200
|
+
};
|
|
201
|
+
const logService = {
|
|
202
|
+
info: (message, data) => {
|
|
203
|
+
send("log", "info", { message, data }).catch(() => {
|
|
204
|
+
});
|
|
205
|
+
},
|
|
206
|
+
warn: (message, data) => {
|
|
207
|
+
send("log", "warn", { message, data }).catch(() => {
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
error: (message, data) => {
|
|
211
|
+
send("log", "error", { message, data }).catch(() => {
|
|
212
|
+
});
|
|
213
|
+
},
|
|
214
|
+
event: (name, properties) => {
|
|
215
|
+
send("log", "event", { name, properties }).catch(() => {
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
const configService = {
|
|
220
|
+
get features() {
|
|
221
|
+
return config.features;
|
|
222
|
+
},
|
|
223
|
+
get app() {
|
|
224
|
+
return config.app;
|
|
225
|
+
},
|
|
226
|
+
get: (key) => send("config", "get", { key })
|
|
227
|
+
};
|
|
228
|
+
clientInstance = {
|
|
229
|
+
get ready() {
|
|
230
|
+
return readyPromise;
|
|
231
|
+
},
|
|
232
|
+
get isReady() {
|
|
233
|
+
return isReady;
|
|
234
|
+
},
|
|
235
|
+
auth: authService,
|
|
236
|
+
// only logout - this is problematic - provides user and account
|
|
237
|
+
theme: themeService,
|
|
238
|
+
// only useful for themed tailwind projects - still useful anyway
|
|
239
|
+
router: routerService,
|
|
240
|
+
// once you're in app - external or container-ui level routing it just not very useful.
|
|
241
|
+
db: dbService,
|
|
242
|
+
ui: uiService,
|
|
243
|
+
storage: storageService,
|
|
244
|
+
files: filesService,
|
|
245
|
+
log: logService,
|
|
246
|
+
config: configService,
|
|
247
|
+
onEntityChange(callback) {
|
|
248
|
+
entityListeners.push(callback);
|
|
249
|
+
return () => {
|
|
250
|
+
const idx = entityListeners.indexOf(callback);
|
|
251
|
+
if (idx > -1) entityListeners.splice(idx, 1);
|
|
252
|
+
};
|
|
253
|
+
},
|
|
254
|
+
get entities() {
|
|
255
|
+
return entities;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
return clientInstance;
|
|
259
|
+
}
|
|
260
|
+
function resetFoundationClient() {
|
|
261
|
+
clientInstance = null;
|
|
262
|
+
}
|
|
263
|
+
export {
|
|
264
|
+
createFoundationClient,
|
|
265
|
+
resetFoundationClient
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/client.ts"],"sourcesContent":["import type {\n FoundationClient,\n User,\n Theme,\n RouterState,\n EntityDefinition,\n EntityChangeEvent,\n SDKReadyPayload,\n SDKResponse,\n AuthService,\n ThemeService,\n RouterService,\n DbService,\n UIService,\n StorageService,\n FilesService,\n LogService,\n ConfigService\n} from './types'\n\nlet clientInstance: FoundationClient | null = null\n\nexport function createFoundationClient(): FoundationClient {\n if (clientInstance) {\n return clientInstance\n }\n\n let isReady = false\n let readyResolve: (() => void) | null = null\n let messageId = 0\n const pendingRequests = new Map<number, { resolve: (data: unknown) => void; reject: (error: Error) => void }>()\n\n let user: User | null = null\n let theme: Theme = { isDark: false, mode: 'system' }\n let router: RouterState = { path: '/', query: {}, hash: '' }\n let config: { features: Record<string, unknown>; app: { id?: string; name?: string; environment?: string } } = { features: {}, app: {} }\n let entities: EntityDefinition[] = []\n\n const themeListeners: Array<(theme: Theme) => void> = []\n const authListeners: Array<(user: User | null) => void> = []\n const routerListeners: Array<(route: RouterState) => void> = []\n const entityListeners: Array<(event: EntityChangeEvent) => void> = []\n\n const readyPromise = new Promise<void>((resolve) => {\n readyResolve = resolve\n })\n\n function send<T = unknown>(namespace: string, type: string, data: Record<string, unknown> = {}): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = ++messageId\n pendingRequests.set(id, {\n resolve: resolve as (data: unknown) => void,\n reject\n })\n\n window.parent.postMessage({\n id,\n namespace,\n type: `${namespace}.${type}`,\n data\n }, '*')\n\n setTimeout(() => {\n if (pendingRequests.has(id)) {\n pendingRequests.delete(id)\n reject(new Error(`Request timeout: ${namespace}.${type}`))\n }\n }, 30000)\n })\n }\n\n function handleMessage(event: MessageEvent) {\n const message = event.data\n\n if (message?.type === 'SDK_READY') {\n const payload = message.data as SDKReadyPayload\n user = payload.user || null\n theme = payload.theme || { isDark: false, mode: 'system' }\n router = payload.router || { path: '/', query: {}, hash: '' }\n config = {\n features: payload.config?.features || {},\n app: payload.config?.app || {}\n }\n entities = payload.entities || []\n\n if (!isReady) {\n isReady = true\n readyResolve?.()\n }\n return\n }\n\n if (message?.type === 'THEME_CHANGED') {\n theme = message.data as Theme\n themeListeners.forEach(fn => {\n try { fn(theme) } catch { /* ignore */ }\n })\n return\n }\n\n if (message?.type === 'AUTH_CHANGED') {\n user = message.data?.user || null\n authListeners.forEach(fn => {\n try { fn(user) } catch { /* ignore */ }\n })\n return\n }\n\n if (message?.type === 'ROUTER_CHANGED') {\n router = message.data as RouterState\n routerListeners.forEach(fn => {\n try { fn(router) } catch { /* ignore */ }\n })\n return\n }\n\n if (message?.type === 'ENTITY_CHANGED') {\n const event = message.data as EntityChangeEvent\n entityListeners.forEach(fn => {\n try { fn(event) } catch { /* ignore */ }\n })\n return\n }\n\n if (typeof message?.id === 'number' && pendingRequests.has(message.id)) {\n const { resolve, reject } = pendingRequests.get(message.id)!\n pendingRequests.delete(message.id)\n\n const response = message as SDKResponse\n if (response.success) {\n resolve(response.data)\n } else {\n reject(new Error(response.error || 'Unknown error'))\n }\n }\n }\n\n window.addEventListener('message', handleMessage)\n\n const authService: AuthService = {\n get user() { return user },\n get isAuthenticated() { return !!user },\n getToken: () => send<string>('auth', 'getToken'),\n login: () => send<void>('auth', 'login'),\n logout: () => send<void>('auth', 'logout'),\n onChange(callback) {\n authListeners.push(callback)\n return () => {\n const idx = authListeners.indexOf(callback)\n if (idx > -1) authListeners.splice(idx, 1)\n }\n }\n }\n\n const themeService: ThemeService = {\n get isDark() { return theme.isDark },\n get mode() { return theme.mode },\n setTheme: (mode) => send<void>('ui', 'setTheme', { mode }),\n toggle: () => send<void>('ui', 'toggleTheme', {}),\n onChange(callback) {\n themeListeners.push(callback)\n return () => {\n const idx = themeListeners.indexOf(callback)\n if (idx > -1) themeListeners.splice(idx, 1)\n }\n }\n }\n\n const routerService: RouterService = {\n get path() { return router.path },\n get query() { return router.query },\n get hash() { return router.hash },\n push: (path, options = {}) => send<void>('router', 'push', { path, ...options }),\n replace: (path, options = {}) => send<void>('router', 'replace', { path, ...options }),\n setQuery: (params, options = {}) => send<void>('router', 'setQuery', { params, ...options }),\n onChange(callback) {\n routerListeners.push(callback)\n return () => {\n const idx = routerListeners.indexOf(callback)\n if (idx > -1) routerListeners.splice(idx, 1)\n }\n }\n }\n\n const dbService: DbService = {\n list: (entity, options = {}) => send('db', 'list', { entity, ...options }),\n get: (entity, id) => send('db', 'get', { entity, itemId: id }),\n create: (entity, item) => send('db', 'create', { entity, item }),\n update: (entity, id, updates) => send('db', 'update', { entity, itemId: id, updates }),\n delete: (entity, id) => send('db', 'delete', { entity, itemId: id })\n }\n\n const uiService: UIService = {\n toast: (message, type = 'info') => send('ui', 'toast', { message, toastType: type }),\n confirm: (message) => send('ui', 'confirm', { message }),\n loading: {\n show: (message) => send('ui', 'loading.show', { message }),\n hide: () => send('ui', 'loading.hide', {})\n },\n banner: {\n show: (message, options = {}) => send('ui', 'banner.show', { message, ...options }),\n hide: (bannerId) => send('ui', 'banner.hide', { bannerId })\n }\n }\n\n const storageService: StorageService = {\n upload: (options) => send('storage', 'upload', options),\n get: (fileId) => send('storage', 'get', { fileId }),\n delete: (fileId) => send('storage', 'delete', { fileId }),\n list: (options = {}) => send('storage', 'list', options)\n }\n\n const filesService: FilesService = {\n initiate: (options) => send('files', 'initiate', options),\n get: (fileId) => send('files', 'get', { fileId }),\n delete: (fileId) => send('files', 'delete', { fileId }),\n list: (options = {}) => send('files', 'list', options)\n }\n\n const logService: LogService = {\n info: (message, data) => { send('log', 'info', { message, data }).catch(() => {}) },\n warn: (message, data) => { send('log', 'warn', { message, data }).catch(() => {}) },\n error: (message, data) => { send('log', 'error', { message, data }).catch(() => {}) },\n event: (name, properties) => { send('log', 'event', { name, properties }).catch(() => {}) }\n }\n\n const configService: ConfigService = {\n get features() { return config.features },\n get app() { return config.app },\n get: (key) => send('config', 'get', { key })\n }\n\n clientInstance = {\n get ready() { return readyPromise },\n get isReady() { return isReady },\n\n auth: authService, // only logout - this is problematic - provides user and account\n theme: themeService, // only useful for themed tailwind projects - still useful anyway\n router: routerService, // once you're in app - external or container-ui level routing it just not very useful.\n db: dbService,\n ui: uiService,\n storage: storageService,\n files: filesService,\n log: logService,\n config: configService,\n\n onEntityChange(callback) {\n entityListeners.push(callback)\n return () => {\n const idx = entityListeners.indexOf(callback)\n if (idx > -1) entityListeners.splice(idx, 1)\n }\n },\n\n get entities() { return entities }\n }\n\n return clientInstance\n}\n\nexport function resetFoundationClient(): void {\n clientInstance = null\n}\n"],"names":["event"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "foundation-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SDK for apps embedded in the Foundation container iframe",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "vite build",
|
|
26
|
+
"dev": "vite build --watch",
|
|
27
|
+
"prepublishOnly": "npm run build",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"foundation",
|
|
32
|
+
"sdk",
|
|
33
|
+
"iframe",
|
|
34
|
+
"postmessage",
|
|
35
|
+
"embedded"
|
|
36
|
+
],
|
|
37
|
+
"author": "",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"typescript": "^5.0.0",
|
|
41
|
+
"vite": "^6.0.0",
|
|
42
|
+
"vite-plugin-dts": "^4.0.0"
|
|
43
|
+
},
|
|
44
|
+
"sideEffects": false
|
|
45
|
+
}
|