@superatomai/sdk-web 0.0.5
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 +526 -0
- package/dist/index.cjs +1611 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1550 -0
- package/dist/index.d.ts +1550 -0
- package/dist/index.js +1570 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
# @superatomai/sdk-web
|
|
2
|
+
|
|
3
|
+
SuperAtom Web SDK - TypeScript SDK for browser-based WebSocket communication with the SuperAtom platform.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔌 WebSocket client with automatic reconnection and exponential backoff
|
|
8
|
+
- 🔒 Type-safe message validation using Zod v4
|
|
9
|
+
- 🎯 Request/response pattern with timeout support
|
|
10
|
+
- 📦 Bundle management with chunked transfer
|
|
11
|
+
- 🧩 Component registration system
|
|
12
|
+
- 🔐 Authentication (login and token verification)
|
|
13
|
+
- 👥 User management (CRUD operations)
|
|
14
|
+
- 📊 Dashboard management (CRUD operations)
|
|
15
|
+
- 📈 Report management (CRUD operations)
|
|
16
|
+
- 🤖 AI component suggestions
|
|
17
|
+
- 💾 Data collection queries
|
|
18
|
+
- 📝 UI logging support
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add @superatomai/sdk-web
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { SuperatomClient, setup } from '@superatomai/sdk-web';
|
|
30
|
+
|
|
31
|
+
// 1. Create and connect client
|
|
32
|
+
const client = new SuperatomClient({
|
|
33
|
+
userId: 'your-user-id',
|
|
34
|
+
projectId: 'your-project-id',
|
|
35
|
+
type: 'runtime', // Connection type (default: 'runtime')
|
|
36
|
+
debug: true, // Enable debug logging
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await client.connect();
|
|
40
|
+
|
|
41
|
+
// 2. Setup components (optional - for component rendering)
|
|
42
|
+
setup({
|
|
43
|
+
MyComponent: MyReactComponent,
|
|
44
|
+
AnotherComponent: AnotherReactComponent,
|
|
45
|
+
mount: (Component, container, props) => {
|
|
46
|
+
const root = createRoot(container);
|
|
47
|
+
root.render(createElement(Component, props));
|
|
48
|
+
return { unmount: () => root.unmount() };
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// 3. Authenticate (optional)
|
|
53
|
+
const loginResponse = await client.sendAuthLoginRequest(
|
|
54
|
+
loginDataBase64, // Base64 encoded login data
|
|
55
|
+
10000 // timeout in ms
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// 4. Get AI component suggestions
|
|
59
|
+
const result = await client.sendUserPromptSuggestionsRequest(
|
|
60
|
+
'show me a calendar component',
|
|
61
|
+
5 // limit
|
|
62
|
+
);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### SuperatomClient
|
|
68
|
+
|
|
69
|
+
Main WebSocket client for communication.
|
|
70
|
+
|
|
71
|
+
#### Configuration
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const client = new SuperatomClient({
|
|
75
|
+
userId: string, // Required: User ID
|
|
76
|
+
projectId: string, // Required: Project ID
|
|
77
|
+
type?: string, // Default: 'runtime'
|
|
78
|
+
baseUrl?: string, // Default: 'wss://ws.superatom.ai/websocket'
|
|
79
|
+
maxReconnectAttempts?: number, // Default: Infinity
|
|
80
|
+
initialReconnectDelay?: number, // Default: 1000ms
|
|
81
|
+
maxReconnectDelay?: number, // Default: 30000ms
|
|
82
|
+
defaultTimeout?: number, // Default: 30000ms
|
|
83
|
+
debug?: boolean, // Default: false
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Core Methods
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Connection management
|
|
91
|
+
await client.connect(); // Returns Promise<void>
|
|
92
|
+
client.disconnect();
|
|
93
|
+
client.isConnected(); // Returns boolean
|
|
94
|
+
await client.reconnectWithConfig(partialConfig); // Reconnect with updated config
|
|
95
|
+
|
|
96
|
+
// Messaging
|
|
97
|
+
client.send(message); // Send message without waiting for response
|
|
98
|
+
await client.sendWithResponse(message, timeout); // Send and wait for response
|
|
99
|
+
await client.ask(message, { timeout }); // Alias for sendWithResponse
|
|
100
|
+
|
|
101
|
+
// Event handlers
|
|
102
|
+
client.onMessage((message) => { ... }); // Returns unsubscribe function
|
|
103
|
+
client.onConnect(() => { ... }); // Returns unsubscribe function
|
|
104
|
+
client.onDisconnect(() => { ... }); // Returns unsubscribe function
|
|
105
|
+
client.onError((error) => { ... }); // Returns unsubscribe function
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Service Methods
|
|
109
|
+
|
|
110
|
+
#### Authentication
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Login with credentials
|
|
114
|
+
const loginResponse = await client.sendAuthLoginRequest(
|
|
115
|
+
loginDataBase64, // Base64 encoded: username + SHA-1 hashed password
|
|
116
|
+
timeout // Optional timeout in ms
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Verify authentication token
|
|
120
|
+
const verifyResponse = await client.sendAuthVerifyRequest(
|
|
121
|
+
token, // Base64 encoded auth token
|
|
122
|
+
timeout // Optional timeout in ms
|
|
123
|
+
);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### User Management
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// Create a new user
|
|
130
|
+
const result = await client.createUser(username, password, timeout);
|
|
131
|
+
|
|
132
|
+
// Update an existing user
|
|
133
|
+
const result = await client.updateUser(username, password, timeout);
|
|
134
|
+
|
|
135
|
+
// Delete a user
|
|
136
|
+
const result = await client.deleteUser(username, timeout);
|
|
137
|
+
|
|
138
|
+
// Get all users
|
|
139
|
+
const result = await client.getAllUsers(timeout);
|
|
140
|
+
// Returns: { success, users, count, error?, message? }
|
|
141
|
+
|
|
142
|
+
// Get a specific user
|
|
143
|
+
const result = await client.getUser(username, timeout);
|
|
144
|
+
// Returns: { success, user, error?, message? }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Dashboard Management
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Create a new dashboard
|
|
151
|
+
const result = await client.createDashboard(
|
|
152
|
+
dashboardId,
|
|
153
|
+
dashboardConfig, // DSLRendererProps
|
|
154
|
+
timeout
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Update an existing dashboard
|
|
158
|
+
const result = await client.updateDashboard(
|
|
159
|
+
dashboardId,
|
|
160
|
+
dashboardConfig,
|
|
161
|
+
timeout
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Delete a dashboard
|
|
165
|
+
const result = await client.deleteDashboard(dashboardId, timeout);
|
|
166
|
+
|
|
167
|
+
// Get all dashboards
|
|
168
|
+
const result = await client.getAllDashboards(timeout);
|
|
169
|
+
// Returns: { success, dashboards, count, error?, message? }
|
|
170
|
+
|
|
171
|
+
// Get a specific dashboard
|
|
172
|
+
const result = await client.getDashboard(dashboardId, timeout);
|
|
173
|
+
// Returns: { success, dashboardId, dashboard, error?, message? }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### Report Management
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Create a new report
|
|
180
|
+
const result = await client.createReport(
|
|
181
|
+
reportId,
|
|
182
|
+
reportConfig, // ReportDSLRendererProps
|
|
183
|
+
timeout
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// Update an existing report
|
|
187
|
+
const result = await client.updateReport(
|
|
188
|
+
reportId,
|
|
189
|
+
reportConfig,
|
|
190
|
+
timeout
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// Delete a report
|
|
194
|
+
const result = await client.deleteReport(reportId, timeout);
|
|
195
|
+
|
|
196
|
+
// Get all reports
|
|
197
|
+
const result = await client.getAllReports(timeout);
|
|
198
|
+
// Returns: { success, reports, count, error?, message? }
|
|
199
|
+
|
|
200
|
+
// Get a specific report
|
|
201
|
+
const result = await client.getReport(reportId, timeout);
|
|
202
|
+
// Returns: { success, reportId, report, error?, message? }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### User Prompts & AI Suggestions
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// Send a user prompt request
|
|
209
|
+
const response = await client.sendUserPromptRequest(
|
|
210
|
+
prompt,
|
|
211
|
+
threadId,
|
|
212
|
+
uiBlockId,
|
|
213
|
+
timeout
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
// Get AI component suggestions
|
|
217
|
+
const result = await client.sendUserPromptSuggestionsRequest(
|
|
218
|
+
'show me a form to collect user data',
|
|
219
|
+
5, // limit (default: 5)
|
|
220
|
+
timeout // optional timeout
|
|
221
|
+
);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### Bundle & Data
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// Request bundle with progress tracking
|
|
228
|
+
const bundle = await client.requestBundle({
|
|
229
|
+
timeout: 60000,
|
|
230
|
+
onProgress: (progress) => {
|
|
231
|
+
console.log(`Download progress: ${progress}%`);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Query data collections
|
|
236
|
+
const result = await client.requestData({
|
|
237
|
+
collection: 'users',
|
|
238
|
+
operation: 'getMany',
|
|
239
|
+
params: { limit: 10 },
|
|
240
|
+
timeout: 10000
|
|
241
|
+
});
|
|
242
|
+
// Returns: { data?, error? }
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Component Setup
|
|
246
|
+
|
|
247
|
+
Register your components with SuperAtom for dynamic rendering.
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { setup } from '@superatomai/sdk-web';
|
|
251
|
+
import { createRoot } from 'react-dom/client';
|
|
252
|
+
import { createElement } from 'react';
|
|
253
|
+
|
|
254
|
+
setup({
|
|
255
|
+
// Your components
|
|
256
|
+
DemoCard: DemoCard,
|
|
257
|
+
Calendar: Calendar,
|
|
258
|
+
Form: ComplexForm,
|
|
259
|
+
|
|
260
|
+
// Mount function (required)
|
|
261
|
+
mount: (Component, container, props) => {
|
|
262
|
+
const root = createRoot(container);
|
|
263
|
+
root.render(createElement(Component, props));
|
|
264
|
+
return { unmount: () => root.unmount() };
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Message Types
|
|
270
|
+
|
|
271
|
+
The SDK supports the following message types (all validated with Zod schemas):
|
|
272
|
+
|
|
273
|
+
**Authentication**
|
|
274
|
+
- `AUTH_LOGIN_REQ` / `AUTH_LOGIN_RES` - User login
|
|
275
|
+
- `AUTH_VERIFY_REQ` / `AUTH_VERIFY_RES` - Token verification
|
|
276
|
+
|
|
277
|
+
**User Prompts & AI**
|
|
278
|
+
- `USER_PROMPT_REQ` / `USER_PROMPT_RES` - User prompt processing
|
|
279
|
+
- `USER_PROMPT_SUGGESTIONS_REQ` / `USER_PROMPT_SUGGESTIONS_RES` - Component suggestions
|
|
280
|
+
|
|
281
|
+
**Bundle & Data**
|
|
282
|
+
- `BUNDLE_REQ` / `BUNDLE_CHUNK` - Bundle transfer with chunking
|
|
283
|
+
- `DATA_REQ` / `DATA_RES` - Data collection queries
|
|
284
|
+
|
|
285
|
+
**Management Operations**
|
|
286
|
+
- `USERS` / `USERS_RES` - User CRUD operations
|
|
287
|
+
- `DASHBOARDS` / `DASHBOARDS_RES` - Dashboard CRUD operations
|
|
288
|
+
- `REPORTS` / `REPORTS_RES` - Report CRUD operations
|
|
289
|
+
|
|
290
|
+
**Logging**
|
|
291
|
+
- `UI_LOGS` - UI logging messages
|
|
292
|
+
|
|
293
|
+
All message types are fully typed and validated using Zod v4 schemas.
|
|
294
|
+
|
|
295
|
+
## Type Safety
|
|
296
|
+
|
|
297
|
+
All messages are validated using Zod v4 schemas. The SDK exports comprehensive type definitions and schemas:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import {
|
|
301
|
+
MessageSchema,
|
|
302
|
+
DataRequestMessageSchema,
|
|
303
|
+
AuthLoginRequestMessageSchema,
|
|
304
|
+
UserPromptSuggestionsRequestMessageSchema,
|
|
305
|
+
// ... and many more
|
|
306
|
+
} from '@superatomai/sdk-web';
|
|
307
|
+
|
|
308
|
+
// Validate any message
|
|
309
|
+
const validMessage = MessageSchema.parse(incomingData);
|
|
310
|
+
|
|
311
|
+
// Validate specific message types
|
|
312
|
+
const dataRequest = DataRequestMessageSchema.parse(requestData);
|
|
313
|
+
|
|
314
|
+
// TypeScript types are automatically inferred
|
|
315
|
+
import type {
|
|
316
|
+
Message,
|
|
317
|
+
DataRequestMessage,
|
|
318
|
+
AuthLoginResponseMessage,
|
|
319
|
+
Component,
|
|
320
|
+
DSLRendererProps,
|
|
321
|
+
ReportDSLRendererProps,
|
|
322
|
+
} from '@superatomai/sdk-web';
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Examples
|
|
326
|
+
|
|
327
|
+
### Complete React Integration
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
import { SuperatomClient, setup } from '@superatomai/sdk-web';
|
|
331
|
+
import { createRoot } from 'react-dom/client';
|
|
332
|
+
import { createElement } from 'react';
|
|
333
|
+
import MyComponent from './components/MyComponent';
|
|
334
|
+
|
|
335
|
+
// Initialize client
|
|
336
|
+
const client = new SuperatomClient({
|
|
337
|
+
userId: 'user_123',
|
|
338
|
+
projectId: 'project_456',
|
|
339
|
+
type: 'runtime',
|
|
340
|
+
debug: true,
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// Setup components
|
|
344
|
+
setup({
|
|
345
|
+
MyComponent,
|
|
346
|
+
mount: (Component, container, props) => {
|
|
347
|
+
const root = createRoot(container);
|
|
348
|
+
root.render(createElement(Component, props));
|
|
349
|
+
return { unmount: () => root.unmount() };
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// Connect and authenticate
|
|
354
|
+
await client.connect();
|
|
355
|
+
|
|
356
|
+
// Listen for messages
|
|
357
|
+
client.onMessage((message) => {
|
|
358
|
+
console.log('Received:', message);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Get component suggestions
|
|
362
|
+
async function handleUserQuery(query: string) {
|
|
363
|
+
const result = await client.sendUserPromptSuggestionsRequest(query, 5);
|
|
364
|
+
|
|
365
|
+
if (result?.payload?.data?.suggestions) {
|
|
366
|
+
console.log('Suggestions:', result.payload.data.suggestions);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### User Management Example
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
import { SuperatomClient } from '@superatomai/sdk-web';
|
|
375
|
+
|
|
376
|
+
const client = new SuperatomClient({
|
|
377
|
+
userId: 'admin_123',
|
|
378
|
+
projectId: 'project_456',
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
await client.connect();
|
|
382
|
+
|
|
383
|
+
// Create a new user
|
|
384
|
+
const createResult = await client.createUser('newuser', 'password123');
|
|
385
|
+
if (createResult.success) {
|
|
386
|
+
console.log('User created:', createResult.username);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Get all users
|
|
390
|
+
const usersResult = await client.getAllUsers();
|
|
391
|
+
if (usersResult.success && usersResult.users) {
|
|
392
|
+
console.log(`Found ${usersResult.count} users`);
|
|
393
|
+
usersResult.users.forEach(user => {
|
|
394
|
+
console.log(`- ${user.username} (${user.wsIds.length} connections)`);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Update a user
|
|
399
|
+
await client.updateUser('newuser', 'newpassword456');
|
|
400
|
+
|
|
401
|
+
// Delete a user
|
|
402
|
+
await client.deleteUser('newuser');
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Dashboard Management Example
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { SuperatomClient } from '@superatomai/sdk-web';
|
|
409
|
+
import type { DSLRendererProps } from '@superatomai/sdk-web';
|
|
410
|
+
|
|
411
|
+
const client = new SuperatomClient({
|
|
412
|
+
userId: 'admin_123',
|
|
413
|
+
projectId: 'project_456',
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
await client.connect();
|
|
417
|
+
|
|
418
|
+
// Create a dashboard
|
|
419
|
+
const dashboardConfig: DSLRendererProps = {
|
|
420
|
+
// Your dashboard configuration
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const result = await client.createDashboard(
|
|
424
|
+
'dashboard_001',
|
|
425
|
+
dashboardConfig
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
if (result.success) {
|
|
429
|
+
console.log('Dashboard created:', result.dashboardId);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Get all dashboards
|
|
433
|
+
const dashboards = await client.getAllDashboards();
|
|
434
|
+
if (dashboards.success && dashboards.dashboards) {
|
|
435
|
+
console.log(`Total dashboards: ${dashboards.count}`);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Get specific dashboard
|
|
439
|
+
const dashboard = await client.getDashboard('dashboard_001');
|
|
440
|
+
if (dashboard.success && dashboard.dashboard) {
|
|
441
|
+
console.log('Dashboard config:', dashboard.dashboard);
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Data Query Example
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import { SuperatomClient } from '@superatomai/sdk-web';
|
|
449
|
+
|
|
450
|
+
const client = new SuperatomClient({
|
|
451
|
+
userId: 'user_123',
|
|
452
|
+
projectId: 'project_456',
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
await client.connect();
|
|
456
|
+
|
|
457
|
+
// Query data from a collection
|
|
458
|
+
const result = await client.requestData({
|
|
459
|
+
collection: 'products',
|
|
460
|
+
operation: 'getMany',
|
|
461
|
+
params: {
|
|
462
|
+
filter: { category: 'electronics' },
|
|
463
|
+
limit: 20,
|
|
464
|
+
offset: 0
|
|
465
|
+
},
|
|
466
|
+
timeout: 10000
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
if (!result.error && result.data) {
|
|
470
|
+
console.log('Products:', result.data);
|
|
471
|
+
} else {
|
|
472
|
+
console.error('Error:', result.error);
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## Advanced Usage
|
|
477
|
+
|
|
478
|
+
### Direct Service Access
|
|
479
|
+
|
|
480
|
+
All service functions can be imported and used directly for advanced use cases:
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
import { SuperatomClient, services } from '@superatomai/sdk-web';
|
|
484
|
+
|
|
485
|
+
const client = new SuperatomClient({ /* ... */ });
|
|
486
|
+
|
|
487
|
+
// Use service functions directly
|
|
488
|
+
const result = await services.requestData(client, {
|
|
489
|
+
collection: 'users',
|
|
490
|
+
operation: 'getMany',
|
|
491
|
+
params: {},
|
|
492
|
+
timeout: 10000
|
|
493
|
+
});
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Event Unsubscription
|
|
497
|
+
|
|
498
|
+
All event handlers return an unsubscribe function:
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
const unsubscribe = client.onMessage((message) => {
|
|
502
|
+
console.log('Message:', message);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Later, when you want to stop listening
|
|
506
|
+
unsubscribe();
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Reconnection with Updated Config
|
|
510
|
+
|
|
511
|
+
You can reconnect with updated configuration without creating a new client:
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
await client.reconnectWithConfig({
|
|
515
|
+
userId: 'new_user_id',
|
|
516
|
+
debug: true
|
|
517
|
+
});
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
## License
|
|
521
|
+
|
|
522
|
+
MIT
|
|
523
|
+
|
|
524
|
+
## Support
|
|
525
|
+
|
|
526
|
+
For issues and questions, please contact the SuperAtom team or refer to the SuperAtom platform documentation.
|