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 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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"}
@@ -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
+ }