@airstore/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 +341 -0
- package/dist/cjs/airstore.js +127 -0
- package/dist/cjs/airstore.js.map +1 -0
- package/dist/cjs/client.js +214 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/errors.js +129 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.js +40 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/resources/connections.js +74 -0
- package/dist/cjs/resources/connections.js.map +1 -0
- package/dist/cjs/resources/filesystem.js +101 -0
- package/dist/cjs/resources/filesystem.js.map +1 -0
- package/dist/cjs/resources/index.js +18 -0
- package/dist/cjs/resources/index.js.map +1 -0
- package/dist/cjs/resources/members.js +63 -0
- package/dist/cjs/resources/members.js.map +1 -0
- package/dist/cjs/resources/oauth.js +85 -0
- package/dist/cjs/resources/oauth.js.map +1 -0
- package/dist/cjs/resources/smart-folders.js +102 -0
- package/dist/cjs/resources/smart-folders.js.map +1 -0
- package/dist/cjs/resources/tokens.js +73 -0
- package/dist/cjs/resources/tokens.js.map +1 -0
- package/dist/cjs/resources/workspaces.js +75 -0
- package/dist/cjs/resources/workspaces.js.map +1 -0
- package/dist/cjs/types/connections.js +3 -0
- package/dist/cjs/types/connections.js.map +1 -0
- package/dist/cjs/types/filesystem.js +3 -0
- package/dist/cjs/types/filesystem.js.map +1 -0
- package/dist/cjs/types/index.js +25 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/members.js +3 -0
- package/dist/cjs/types/members.js.map +1 -0
- package/dist/cjs/types/oauth.js +3 -0
- package/dist/cjs/types/oauth.js.map +1 -0
- package/dist/cjs/types/shared.js +3 -0
- package/dist/cjs/types/shared.js.map +1 -0
- package/dist/cjs/types/smart-folders.js +3 -0
- package/dist/cjs/types/smart-folders.js.map +1 -0
- package/dist/cjs/types/tokens.js +3 -0
- package/dist/cjs/types/tokens.js.map +1 -0
- package/dist/cjs/types/workspaces.js +3 -0
- package/dist/cjs/types/workspaces.js.map +1 -0
- package/dist/cjs/version.js +6 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/esm/airstore.js +123 -0
- package/dist/esm/airstore.js.map +1 -0
- package/dist/esm/client.js +209 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.js +115 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/resources/connections.js +70 -0
- package/dist/esm/resources/connections.js.map +1 -0
- package/dist/esm/resources/filesystem.js +97 -0
- package/dist/esm/resources/filesystem.js.map +1 -0
- package/dist/esm/resources/index.js +8 -0
- package/dist/esm/resources/index.js.map +1 -0
- package/dist/esm/resources/members.js +59 -0
- package/dist/esm/resources/members.js.map +1 -0
- package/dist/esm/resources/oauth.js +81 -0
- package/dist/esm/resources/oauth.js.map +1 -0
- package/dist/esm/resources/smart-folders.js +98 -0
- package/dist/esm/resources/smart-folders.js.map +1 -0
- package/dist/esm/resources/tokens.js +69 -0
- package/dist/esm/resources/tokens.js.map +1 -0
- package/dist/esm/resources/workspaces.js +71 -0
- package/dist/esm/resources/workspaces.js.map +1 -0
- package/dist/esm/types/connections.js +2 -0
- package/dist/esm/types/connections.js.map +1 -0
- package/dist/esm/types/filesystem.js +2 -0
- package/dist/esm/types/filesystem.js.map +1 -0
- package/dist/esm/types/index.js +9 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/members.js +2 -0
- package/dist/esm/types/members.js.map +1 -0
- package/dist/esm/types/oauth.js +2 -0
- package/dist/esm/types/oauth.js.map +1 -0
- package/dist/esm/types/shared.js +2 -0
- package/dist/esm/types/shared.js.map +1 -0
- package/dist/esm/types/smart-folders.js +2 -0
- package/dist/esm/types/smart-folders.js.map +1 -0
- package/dist/esm/types/tokens.js +2 -0
- package/dist/esm/types/tokens.js.map +1 -0
- package/dist/esm/types/workspaces.js +2 -0
- package/dist/esm/types/workspaces.js.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/types/airstore.d.ts +114 -0
- package/dist/types/airstore.d.ts.map +1 -0
- package/dist/types/client.d.ts +86 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/errors.d.ts +61 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/resources/connections.d.ts +50 -0
- package/dist/types/resources/connections.d.ts.map +1 -0
- package/dist/types/resources/filesystem.d.ts +81 -0
- package/dist/types/resources/filesystem.d.ts.map +1 -0
- package/dist/types/resources/index.d.ts +8 -0
- package/dist/types/resources/index.d.ts.map +1 -0
- package/dist/types/resources/members.d.ts +49 -0
- package/dist/types/resources/members.d.ts.map +1 -0
- package/dist/types/resources/oauth.d.ts +57 -0
- package/dist/types/resources/oauth.d.ts.map +1 -0
- package/dist/types/resources/smart-folders.d.ts +70 -0
- package/dist/types/resources/smart-folders.d.ts.map +1 -0
- package/dist/types/resources/tokens.d.ts +54 -0
- package/dist/types/resources/tokens.d.ts.map +1 -0
- package/dist/types/resources/workspaces.d.ts +63 -0
- package/dist/types/resources/workspaces.d.ts.map +1 -0
- package/dist/types/types/connections.d.ts +41 -0
- package/dist/types/types/connections.d.ts.map +1 -0
- package/dist/types/types/filesystem.d.ts +39 -0
- package/dist/types/types/filesystem.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +9 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/members.d.ts +30 -0
- package/dist/types/types/members.d.ts.map +1 -0
- package/dist/types/types/oauth.d.ts +40 -0
- package/dist/types/types/oauth.d.ts.map +1 -0
- package/dist/types/types/shared.d.ts +27 -0
- package/dist/types/types/shared.d.ts.map +1 -0
- package/dist/types/types/smart-folders.d.ts +45 -0
- package/dist/types/types/smart-folders.d.ts.map +1 -0
- package/dist/types/types/tokens.d.ts +40 -0
- package/dist/types/types/tokens.d.ts.map +1 -0
- package/dist/types/types/workspaces.d.ts +26 -0
- package/dist/types/types/workspaces.d.ts.map +1 -0
- package/dist/types/version.d.ts +3 -0
- package/dist/types/version.d.ts.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# @airstore/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the [Airstore](https://airstore.ai) API. Provision workspaces, manage connections, configure smart folders, and generate mount tokens — all from your backend.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @airstore/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import Airstore from '@airstore/sdk';
|
|
15
|
+
|
|
16
|
+
const airstore = new Airstore({
|
|
17
|
+
apiKey: 'org_...', // or set AIRSTORE_API_KEY env var
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const workspace = await airstore.workspaces.create({ name: 'user-123' });
|
|
21
|
+
console.log(workspace.external_id);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Full Provisioning Flow
|
|
25
|
+
|
|
26
|
+
This is the typical flow when a new user signs up on your platform:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import Airstore from '@airstore/sdk';
|
|
30
|
+
|
|
31
|
+
const airstore = new Airstore({ apiKey: process.env.AIRSTORE_API_KEY });
|
|
32
|
+
|
|
33
|
+
async function provisionUser(
|
|
34
|
+
userId: string,
|
|
35
|
+
gmailTokens: { accessToken: string; refreshToken: string },
|
|
36
|
+
) {
|
|
37
|
+
// 1. Create a workspace
|
|
38
|
+
const ws = await airstore.workspaces.create({ name: `user-${userId}` });
|
|
39
|
+
|
|
40
|
+
// 2. Add a member (so we can create a scoped token)
|
|
41
|
+
const member = await airstore.members.create(ws.external_id, {
|
|
42
|
+
email: `${userId}@internal`,
|
|
43
|
+
name: userId,
|
|
44
|
+
role: 'member',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// 3. Connect Gmail with existing OAuth tokens
|
|
48
|
+
await airstore.connections.create(ws.external_id, {
|
|
49
|
+
integrationType: 'gmail',
|
|
50
|
+
accessToken: gmailTokens.accessToken,
|
|
51
|
+
refreshToken: gmailTokens.refreshToken,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// 4. Set up smart folders for what the agent should see
|
|
55
|
+
await airstore.smartFolders.create(ws.external_id, {
|
|
56
|
+
integration: 'gmail',
|
|
57
|
+
name: 'Recent Emails',
|
|
58
|
+
guidance: 'Last 7 days of emails from the inbox',
|
|
59
|
+
outputFormat: 'folder',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// 5. Generate a mount token for the user's VM
|
|
63
|
+
const token = await airstore.tokens.create(ws.external_id, {
|
|
64
|
+
email: `${userId}@internal`,
|
|
65
|
+
name: 'vm-mount',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 6. Pass this to the VM:
|
|
69
|
+
// airstore start --token <token.token>
|
|
70
|
+
return {
|
|
71
|
+
workspaceId: ws.external_id,
|
|
72
|
+
mountToken: token.token,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Configuration
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const airstore = new Airstore({
|
|
81
|
+
// Required — org token or cluster admin token
|
|
82
|
+
apiKey: 'org_...',
|
|
83
|
+
|
|
84
|
+
// Override the base URL (default: https://api.airstore.ai/api/v1)
|
|
85
|
+
baseURL: 'https://api.airstore.ai/api/v1',
|
|
86
|
+
|
|
87
|
+
// Request timeout in ms (default: 60000)
|
|
88
|
+
timeout: 30_000,
|
|
89
|
+
|
|
90
|
+
// Max retries for 429/5xx errors (default: 2)
|
|
91
|
+
maxRetries: 3,
|
|
92
|
+
|
|
93
|
+
// Default headers for every request
|
|
94
|
+
defaultHeaders: { 'X-Custom-Header': 'value' },
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Environment Variables
|
|
99
|
+
|
|
100
|
+
| Variable | Description |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `AIRSTORE_API_KEY` | Default API key if not passed to constructor |
|
|
103
|
+
| `AIRSTORE_BASE_URL` | Default base URL if not passed to constructor |
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
### Workspaces
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// Create
|
|
111
|
+
const ws = await airstore.workspaces.create({ name: 'my-workspace' });
|
|
112
|
+
|
|
113
|
+
// List all (org tokens only see their tenant's workspaces)
|
|
114
|
+
const workspaces = await airstore.workspaces.list();
|
|
115
|
+
|
|
116
|
+
// Retrieve by ID
|
|
117
|
+
const ws = await airstore.workspaces.retrieve('ws_abc123');
|
|
118
|
+
|
|
119
|
+
// Delete
|
|
120
|
+
await airstore.workspaces.del('ws_abc123');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Connections
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// Create with existing OAuth tokens
|
|
127
|
+
const conn = await airstore.connections.create('ws_abc123', {
|
|
128
|
+
integrationType: 'gmail',
|
|
129
|
+
accessToken: '...',
|
|
130
|
+
refreshToken: '...',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Create with API key
|
|
134
|
+
const conn = await airstore.connections.create('ws_abc123', {
|
|
135
|
+
integrationType: 'github',
|
|
136
|
+
apiKey: 'ghp_...',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// List
|
|
140
|
+
const connections = await airstore.connections.list('ws_abc123');
|
|
141
|
+
|
|
142
|
+
// Delete
|
|
143
|
+
await airstore.connections.del('ws_abc123', 'conn_abc123');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Smart Folders
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// Create
|
|
150
|
+
const folder = await airstore.smartFolders.create('ws_abc123', {
|
|
151
|
+
integration: 'gmail',
|
|
152
|
+
name: 'Important Emails',
|
|
153
|
+
guidance: 'Emails marked as important from the last month',
|
|
154
|
+
outputFormat: 'folder', // or 'file'
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// List all
|
|
158
|
+
const folders = await airstore.smartFolders.list('ws_abc123');
|
|
159
|
+
|
|
160
|
+
// Retrieve by path
|
|
161
|
+
const folder = await airstore.smartFolders.retrieve('ws_abc123', '/Sources/gmail/Important Emails');
|
|
162
|
+
|
|
163
|
+
// Update
|
|
164
|
+
const updated = await airstore.smartFolders.update('ws_abc123', 'query_abc', {
|
|
165
|
+
guidance: 'Updated guidance text',
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Delete
|
|
169
|
+
await airstore.smartFolders.del('ws_abc123', 'query_abc');
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Tokens
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// Create a workspace-scoped token (for CLI mounting)
|
|
176
|
+
const token = await airstore.tokens.create('ws_abc123', {
|
|
177
|
+
email: 'agent@internal',
|
|
178
|
+
name: 'vm-mount',
|
|
179
|
+
expiresIn: 86400, // optional, seconds
|
|
180
|
+
});
|
|
181
|
+
console.log(token.token); // raw value — only shown once
|
|
182
|
+
|
|
183
|
+
// List tokens (values are never returned)
|
|
184
|
+
const tokens = await airstore.tokens.list('ws_abc123');
|
|
185
|
+
|
|
186
|
+
// Revoke
|
|
187
|
+
await airstore.tokens.revoke('ws_abc123', 'tok_abc123');
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Members
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Add a member
|
|
194
|
+
const member = await airstore.members.create('ws_abc123', {
|
|
195
|
+
email: 'user@example.com',
|
|
196
|
+
name: 'Jane Doe',
|
|
197
|
+
role: 'member', // 'admin' | 'member' | 'viewer'
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// List
|
|
201
|
+
const members = await airstore.members.list('ws_abc123');
|
|
202
|
+
|
|
203
|
+
// Remove
|
|
204
|
+
await airstore.members.del('ws_abc123', 'mem_abc123');
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### OAuth Sessions
|
|
208
|
+
|
|
209
|
+
For interactive connection setup where users authorize via browser redirect:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Create an OAuth session
|
|
213
|
+
const session = await airstore.oauth.createSession({
|
|
214
|
+
integrationType: 'gmail',
|
|
215
|
+
returnTo: 'https://myapp.com/callback',
|
|
216
|
+
});
|
|
217
|
+
console.log(session.authorize_url); // redirect user here
|
|
218
|
+
|
|
219
|
+
// Check status
|
|
220
|
+
const status = await airstore.oauth.getSession(session.session_id);
|
|
221
|
+
|
|
222
|
+
// Or poll until completion (default: 5 min timeout, 2s interval)
|
|
223
|
+
const completed = await airstore.oauth.poll(session.session_id, {
|
|
224
|
+
timeout: 120_000,
|
|
225
|
+
interval: 3_000,
|
|
226
|
+
});
|
|
227
|
+
console.log(completed.connection_id);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Filesystem
|
|
231
|
+
|
|
232
|
+
Read-only access to the virtual filesystem:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// List directory contents
|
|
236
|
+
const entries = await airstore.fs.list('ws_abc123', { path: '/' });
|
|
237
|
+
|
|
238
|
+
// Read file contents
|
|
239
|
+
const content = await airstore.fs.read('ws_abc123', {
|
|
240
|
+
path: '/Sources/gmail/inbox/email.txt',
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Get directory tree
|
|
244
|
+
const tree = await airstore.fs.tree('ws_abc123', {
|
|
245
|
+
path: '/',
|
|
246
|
+
maxKeys: 100,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Stat a file
|
|
250
|
+
const meta = await airstore.fs.stat('ws_abc123', '/Sources/gmail/inbox/email.txt');
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Per-Request Options
|
|
254
|
+
|
|
255
|
+
Every method accepts an optional last argument for per-request overrides:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
const ws = await airstore.workspaces.list({
|
|
259
|
+
timeout: 10_000,
|
|
260
|
+
maxRetries: 5,
|
|
261
|
+
signal: controller.signal,
|
|
262
|
+
headers: { 'X-Trace-Id': 'abc' },
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Error Handling
|
|
267
|
+
|
|
268
|
+
The SDK throws typed errors for easy programmatic handling:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import {
|
|
272
|
+
AuthenticationError,
|
|
273
|
+
NotFoundError,
|
|
274
|
+
RateLimitError,
|
|
275
|
+
} from '@airstore/sdk';
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
await airstore.workspaces.retrieve('ws_nonexistent');
|
|
279
|
+
} catch (err) {
|
|
280
|
+
if (err instanceof NotFoundError) {
|
|
281
|
+
console.log('Workspace not found');
|
|
282
|
+
} else if (err instanceof AuthenticationError) {
|
|
283
|
+
console.log('Invalid API key');
|
|
284
|
+
} else if (err instanceof RateLimitError) {
|
|
285
|
+
console.log('Rate limited, retry after:', err.headers.get('retry-after'));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Error Hierarchy
|
|
291
|
+
|
|
292
|
+
| Class | Status | Description |
|
|
293
|
+
|---|---|---|
|
|
294
|
+
| `AirstoreError` | — | Base error for all SDK errors |
|
|
295
|
+
| `APIError` | varies | Base for HTTP errors |
|
|
296
|
+
| `AuthenticationError` | 401 | Invalid or missing API key |
|
|
297
|
+
| `PermissionDeniedError` | 403 | Token lacks permission |
|
|
298
|
+
| `NotFoundError` | 404 | Resource not found |
|
|
299
|
+
| `ConflictError` | 409 | Conflicting operation |
|
|
300
|
+
| `UnprocessableEntityError` | 422 | Validation failed |
|
|
301
|
+
| `RateLimitError` | 429 | Rate limit exceeded |
|
|
302
|
+
| `InternalServerError` | 5xx | Server error (retried automatically) |
|
|
303
|
+
| `APIConnectionError` | — | Network failure |
|
|
304
|
+
| `APIConnectionTimeoutError` | — | Request timed out |
|
|
305
|
+
|
|
306
|
+
## Response Metadata
|
|
307
|
+
|
|
308
|
+
Every response object includes a non-enumerable `lastResponse` property:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const ws = await airstore.workspaces.create({ name: 'test' });
|
|
312
|
+
console.log(ws.lastResponse.statusCode); // 200
|
|
313
|
+
console.log(ws.lastResponse.requestId); // 'req_abc123'
|
|
314
|
+
console.log(ws.lastResponse.headers); // Headers object
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Automatic Retries
|
|
318
|
+
|
|
319
|
+
The SDK automatically retries on transient errors (408, 409, 429, 500, 502, 503, 504) with exponential backoff and jitter. The `Retry-After` header is respected when present.
|
|
320
|
+
|
|
321
|
+
## Raw Requests
|
|
322
|
+
|
|
323
|
+
For endpoints not yet covered by the SDK, use the escape hatch:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
const response = await airstore.rawRequest('POST', '/some/new/endpoint', {
|
|
327
|
+
body: { key: 'value' },
|
|
328
|
+
timeout: 5_000,
|
|
329
|
+
});
|
|
330
|
+
const data = await response.json();
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Requirements
|
|
334
|
+
|
|
335
|
+
- Node.js 18+ (uses native `fetch`)
|
|
336
|
+
- TypeScript 5.0+ (for type-only imports)
|
|
337
|
+
- Zero runtime dependencies
|
|
338
|
+
|
|
339
|
+
## License
|
|
340
|
+
|
|
341
|
+
Apache-2.0
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Airstore = void 0;
|
|
4
|
+
const client_js_1 = require("./client.js");
|
|
5
|
+
const workspaces_js_1 = require("./resources/workspaces.js");
|
|
6
|
+
const connections_js_1 = require("./resources/connections.js");
|
|
7
|
+
const smart_folders_js_1 = require("./resources/smart-folders.js");
|
|
8
|
+
const tokens_js_1 = require("./resources/tokens.js");
|
|
9
|
+
const members_js_1 = require("./resources/members.js");
|
|
10
|
+
const oauth_js_1 = require("./resources/oauth.js");
|
|
11
|
+
const filesystem_js_1 = require("./resources/filesystem.js");
|
|
12
|
+
/**
|
|
13
|
+
* The Airstore SDK client.
|
|
14
|
+
*
|
|
15
|
+
* Create an instance with your API key to interact with workspaces,
|
|
16
|
+
* connections, smart folders, tokens, members, the virtual filesystem,
|
|
17
|
+
* and OAuth sessions.
|
|
18
|
+
*
|
|
19
|
+
* @example Basic provisioning flow
|
|
20
|
+
* ```ts
|
|
21
|
+
* import Airstore from '@airstore/sdk';
|
|
22
|
+
*
|
|
23
|
+
* const airstore = new Airstore({ apiKey: 'org_...' });
|
|
24
|
+
*
|
|
25
|
+
* // 1. Create a workspace for a new user
|
|
26
|
+
* const ws = await airstore.workspaces.create({ name: 'user-123' });
|
|
27
|
+
*
|
|
28
|
+
* // 2. Connect their Gmail with existing OAuth tokens
|
|
29
|
+
* await airstore.connections.create(ws.external_id, {
|
|
30
|
+
* integrationType: 'gmail',
|
|
31
|
+
* accessToken: existingAccessToken,
|
|
32
|
+
* refreshToken: existingRefreshToken,
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // 3. Set up a smart folder
|
|
36
|
+
* await airstore.smartFolders.create(ws.external_id, {
|
|
37
|
+
* integration: 'gmail',
|
|
38
|
+
* name: 'Recent Emails',
|
|
39
|
+
* guidance: 'Last 7 days of emails from the inbox',
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // 4. Generate a mount token for the user's VM
|
|
43
|
+
* const token = await airstore.tokens.create(ws.external_id, {
|
|
44
|
+
* email: 'agent@internal',
|
|
45
|
+
* name: 'vm-mount',
|
|
46
|
+
* });
|
|
47
|
+
* // Pass token.token to: airstore start --token <token>
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Per-request options
|
|
51
|
+
* ```ts
|
|
52
|
+
* const ws = await airstore.workspaces.list({
|
|
53
|
+
* timeout: 10_000,
|
|
54
|
+
* maxRetries: 5,
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
class Airstore extends client_js_1.CoreClient {
|
|
59
|
+
/**
|
|
60
|
+
* Manage workspaces.
|
|
61
|
+
*
|
|
62
|
+
* Workspaces are the top-level container for connections, smart folders,
|
|
63
|
+
* members, and the virtual filesystem.
|
|
64
|
+
*/
|
|
65
|
+
workspaces;
|
|
66
|
+
/**
|
|
67
|
+
* Manage connections (integrations) within a workspace.
|
|
68
|
+
*
|
|
69
|
+
* Pass existing OAuth tokens or API keys to connect external services
|
|
70
|
+
* like Gmail, GitHub, Notion, etc.
|
|
71
|
+
*/
|
|
72
|
+
connections;
|
|
73
|
+
/**
|
|
74
|
+
* Manage smart folders (filesystem queries).
|
|
75
|
+
*
|
|
76
|
+
* Smart folders use LLM inference to automatically organize and filter
|
|
77
|
+
* data from connected integrations into virtual folders or files.
|
|
78
|
+
*/
|
|
79
|
+
smartFolders;
|
|
80
|
+
/**
|
|
81
|
+
* Manage workspace-scoped authentication tokens.
|
|
82
|
+
*
|
|
83
|
+
* Tokens are used for CLI mounting and per-workspace programmatic access.
|
|
84
|
+
*/
|
|
85
|
+
tokens;
|
|
86
|
+
/**
|
|
87
|
+
* Manage workspace members.
|
|
88
|
+
*
|
|
89
|
+
* Members are users with roles (admin, member, viewer) in a workspace.
|
|
90
|
+
*/
|
|
91
|
+
members;
|
|
92
|
+
/**
|
|
93
|
+
* OAuth session management for interactive connection setup.
|
|
94
|
+
*
|
|
95
|
+
* Use this for browser-redirect flows where users authorize
|
|
96
|
+
* integrations themselves.
|
|
97
|
+
*/
|
|
98
|
+
oauth;
|
|
99
|
+
/**
|
|
100
|
+
* Read-only access to the workspace virtual filesystem.
|
|
101
|
+
*
|
|
102
|
+
* Browse directories, read files, and inspect metadata across
|
|
103
|
+
* all connected integrations.
|
|
104
|
+
*/
|
|
105
|
+
fs;
|
|
106
|
+
/**
|
|
107
|
+
* Create a new Airstore SDK client.
|
|
108
|
+
*
|
|
109
|
+
* @param opts - Client configuration. At minimum, provide an `apiKey`
|
|
110
|
+
* or set the `AIRSTORE_API_KEY` environment variable.
|
|
111
|
+
*
|
|
112
|
+
* @throws {AirstoreError} If no API key is provided.
|
|
113
|
+
*/
|
|
114
|
+
constructor(opts) {
|
|
115
|
+
super(opts);
|
|
116
|
+
this.workspaces = new workspaces_js_1.Workspaces(this);
|
|
117
|
+
this.connections = new connections_js_1.Connections(this);
|
|
118
|
+
this.smartFolders = new smart_folders_js_1.SmartFolders(this);
|
|
119
|
+
this.tokens = new tokens_js_1.Tokens(this);
|
|
120
|
+
this.members = new members_js_1.Members(this);
|
|
121
|
+
this.oauth = new oauth_js_1.OAuth(this);
|
|
122
|
+
this.fs = new filesystem_js_1.Filesystem(this);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.Airstore = Airstore;
|
|
126
|
+
exports.default = Airstore;
|
|
127
|
+
//# sourceMappingURL=airstore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airstore.js","sourceRoot":"","sources":["../../src/airstore.ts"],"names":[],"mappings":";;;AAAA,2CAA6D;AAC7D,6DAAuD;AACvD,+DAAyD;AACzD,mEAA4D;AAC5D,qDAA+C;AAC/C,uDAAiD;AACjD,mDAA6C;AAC7C,6DAAuD;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAa,QAAS,SAAQ,sBAAU;IACtC;;;;;OAKG;IACM,UAAU,CAAa;IAEhC;;;;;OAKG;IACM,WAAW,CAAc;IAElC;;;;;OAKG;IACM,YAAY,CAAe;IAEpC;;;;OAIG;IACM,MAAM,CAAS;IAExB;;;;OAIG;IACM,OAAO,CAAU;IAE1B;;;;;OAKG;IACM,KAAK,CAAQ;IAEtB;;;;;OAKG;IACM,EAAE,CAAa;IAExB;;;;;;;OAOG;IACH,YAAY,IAAoB;QAC9B,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,UAAU,GAAG,IAAI,0BAAU,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,IAAI,4BAAW,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,IAAI,+BAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,IAAI,gBAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,GAAG,IAAI,0BAAU,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;CACF;AAzED,4BAyEC;AAED,kBAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CoreClient = void 0;
|
|
4
|
+
exports.attachResponseMeta = attachResponseMeta;
|
|
5
|
+
const version_js_1 = require("./version.js");
|
|
6
|
+
const errors_js_1 = require("./errors.js");
|
|
7
|
+
function attachResponseMeta(obj, meta) {
|
|
8
|
+
Object.defineProperty(obj, 'lastResponse', {
|
|
9
|
+
value: meta,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
configurable: true,
|
|
12
|
+
});
|
|
13
|
+
return obj;
|
|
14
|
+
}
|
|
15
|
+
/** Retryable status codes. */
|
|
16
|
+
const RETRYABLE_STATUS_CODES = new Set([408, 409, 429, 500, 502, 503, 504]);
|
|
17
|
+
/** Base backoff in ms. */
|
|
18
|
+
const BASE_BACKOFF_MS = 500;
|
|
19
|
+
/** Max backoff in ms. */
|
|
20
|
+
const MAX_BACKOFF_MS = 8000;
|
|
21
|
+
/**
|
|
22
|
+
* Core HTTP client for the Airstore API.
|
|
23
|
+
*
|
|
24
|
+
* Handles authentication, automatic retries with exponential backoff,
|
|
25
|
+
* timeout, and per-request option overrides.
|
|
26
|
+
*/
|
|
27
|
+
class CoreClient {
|
|
28
|
+
apiKey;
|
|
29
|
+
baseURL;
|
|
30
|
+
timeout;
|
|
31
|
+
maxRetries;
|
|
32
|
+
defaultHeaders;
|
|
33
|
+
constructor(opts = {}) {
|
|
34
|
+
this.apiKey =
|
|
35
|
+
opts.apiKey ??
|
|
36
|
+
(typeof process !== 'undefined' ? process.env?.['AIRSTORE_API_KEY'] ?? '' : '');
|
|
37
|
+
if (!this.apiKey) {
|
|
38
|
+
throw new errors_js_1.AirstoreError('API key is required. Pass it via the `apiKey` option or set the AIRSTORE_API_KEY environment variable.');
|
|
39
|
+
}
|
|
40
|
+
const envBaseURL = typeof process !== 'undefined'
|
|
41
|
+
? (process.env?.['AIRSTORE_BASE_URL'] ?? '')
|
|
42
|
+
: '';
|
|
43
|
+
this.baseURL = (opts.baseURL ?? (envBaseURL || 'https://api.airstore.ai/api/v1')).replace(/\/+$/, '');
|
|
44
|
+
this.timeout = opts.timeout ?? 60_000;
|
|
45
|
+
this.maxRetries = opts.maxRetries ?? 2;
|
|
46
|
+
this.defaultHeaders = opts.defaultHeaders ?? {};
|
|
47
|
+
}
|
|
48
|
+
/** Make an API request with retry and timeout. */
|
|
49
|
+
async request(method, path, body, params, reqOpts) {
|
|
50
|
+
const url = this._buildURL(path, params);
|
|
51
|
+
const timeout = reqOpts?.timeout ?? this.timeout;
|
|
52
|
+
const maxRetries = reqOpts?.maxRetries ?? this.maxRetries;
|
|
53
|
+
const headers = this._buildHeaders(reqOpts?.headers);
|
|
54
|
+
let lastError;
|
|
55
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
56
|
+
if (attempt > 0) {
|
|
57
|
+
await this._sleep(this._backoffMs(attempt, lastError));
|
|
58
|
+
}
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
if (reqOpts?.signal) {
|
|
61
|
+
reqOpts.signal.addEventListener('abort', () => controller.abort(), { once: true });
|
|
62
|
+
}
|
|
63
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
64
|
+
try {
|
|
65
|
+
const fetchOpts = {
|
|
66
|
+
method,
|
|
67
|
+
headers,
|
|
68
|
+
signal: controller.signal,
|
|
69
|
+
};
|
|
70
|
+
if (body !== undefined && method !== 'GET' && method !== 'HEAD') {
|
|
71
|
+
fetchOpts.body = JSON.stringify(body);
|
|
72
|
+
}
|
|
73
|
+
const response = await fetch(url, fetchOpts);
|
|
74
|
+
clearTimeout(timeoutId);
|
|
75
|
+
const meta = {
|
|
76
|
+
statusCode: response.status,
|
|
77
|
+
headers: response.headers,
|
|
78
|
+
requestId: response.headers.get('x-request-id') ??
|
|
79
|
+
response.headers.get('X-Request-Id') ??
|
|
80
|
+
undefined,
|
|
81
|
+
};
|
|
82
|
+
if (response.ok) {
|
|
83
|
+
const data = (await response.json());
|
|
84
|
+
// Airstore API wraps responses in { success, data }
|
|
85
|
+
const result = (data.data ?? data);
|
|
86
|
+
return attachResponseMeta(result, meta);
|
|
87
|
+
}
|
|
88
|
+
// Non-retryable error
|
|
89
|
+
if (!RETRYABLE_STATUS_CODES.has(response.status) || attempt === maxRetries) {
|
|
90
|
+
let errorMessage = `Request failed with status ${response.status}`;
|
|
91
|
+
try {
|
|
92
|
+
const errBody = await response.json();
|
|
93
|
+
errorMessage = errBody?.error ?? errBody?.message ?? errorMessage;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// ignore parse errors
|
|
97
|
+
}
|
|
98
|
+
throw errors_js_1.APIError.generate(response.status, null, errorMessage, response.headers);
|
|
99
|
+
}
|
|
100
|
+
// Retryable — store error and continue
|
|
101
|
+
lastError = errors_js_1.APIError.generate(response.status, null, `Retryable error (${response.status})`, response.headers);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
clearTimeout(timeoutId);
|
|
105
|
+
if (err instanceof errors_js_1.APIError) {
|
|
106
|
+
if (!RETRYABLE_STATUS_CODES.has(err.status) || attempt === maxRetries) {
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
lastError = err;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
113
|
+
if (reqOpts?.signal?.aborted) {
|
|
114
|
+
throw new errors_js_1.AirstoreError('Request was cancelled');
|
|
115
|
+
}
|
|
116
|
+
throw new errors_js_1.APIConnectionTimeoutError();
|
|
117
|
+
}
|
|
118
|
+
if (attempt === maxRetries) {
|
|
119
|
+
throw new errors_js_1.APIConnectionError(`Connection error: ${err instanceof Error ? err.message : String(err)}`, err);
|
|
120
|
+
}
|
|
121
|
+
lastError = err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
throw lastError ?? new errors_js_1.AirstoreError('Request failed after retries');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build full URL with query params.
|
|
128
|
+
*
|
|
129
|
+
* Uses string concatenation to preserve the base path prefix (e.g. `/api/v1`).
|
|
130
|
+
* `new URL(path, base)` would resolve absolute paths against the origin,
|
|
131
|
+
* dropping the base path — so we avoid it.
|
|
132
|
+
*/
|
|
133
|
+
_buildURL(path, params) {
|
|
134
|
+
const suffix = path.startsWith('/') ? path : `/${path}`;
|
|
135
|
+
const url = new URL(`${this.baseURL}${suffix}`);
|
|
136
|
+
if (params) {
|
|
137
|
+
for (const [key, value] of Object.entries(params)) {
|
|
138
|
+
if (value !== undefined && value !== '') {
|
|
139
|
+
url.searchParams.set(key, value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return url.toString();
|
|
144
|
+
}
|
|
145
|
+
/** Build request headers. */
|
|
146
|
+
_buildHeaders(extra) {
|
|
147
|
+
return {
|
|
148
|
+
'Content-Type': 'application/json',
|
|
149
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
150
|
+
'User-Agent': `airstore-sdk-typescript/${version_js_1.VERSION}`,
|
|
151
|
+
...this.defaultHeaders,
|
|
152
|
+
...extra,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/** Calculate backoff with jitter. */
|
|
156
|
+
_backoffMs(attempt, lastError) {
|
|
157
|
+
// Respect Retry-After headers if present.
|
|
158
|
+
// retry-after-ms is already in milliseconds; retry-after is in seconds.
|
|
159
|
+
if (lastError instanceof errors_js_1.APIError) {
|
|
160
|
+
const retryAfterMs = lastError.headers.get('retry-after-ms');
|
|
161
|
+
if (retryAfterMs) {
|
|
162
|
+
const ms = Number(retryAfterMs);
|
|
163
|
+
if (!isNaN(ms))
|
|
164
|
+
return ms;
|
|
165
|
+
}
|
|
166
|
+
const retryAfter = lastError.headers.get('retry-after');
|
|
167
|
+
if (retryAfter) {
|
|
168
|
+
const seconds = Number(retryAfter);
|
|
169
|
+
if (!isNaN(seconds))
|
|
170
|
+
return seconds * 1000;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const base = BASE_BACKOFF_MS * Math.pow(2, attempt - 1);
|
|
174
|
+
const jitter = Math.random() * base * 0.5;
|
|
175
|
+
return Math.min(base + jitter, MAX_BACKOFF_MS);
|
|
176
|
+
}
|
|
177
|
+
/** Sleep helper. */
|
|
178
|
+
_sleep(ms) {
|
|
179
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Make a raw HTTP request to any API path.
|
|
183
|
+
* Escape hatch for endpoints not yet covered by the SDK.
|
|
184
|
+
*/
|
|
185
|
+
async rawRequest(method, path, opts) {
|
|
186
|
+
const url = this._buildURL(path, opts?.params);
|
|
187
|
+
const headers = this._buildHeaders(opts?.headers);
|
|
188
|
+
const controller = new AbortController();
|
|
189
|
+
if (opts?.signal) {
|
|
190
|
+
opts.signal.addEventListener('abort', () => controller.abort(), { once: true });
|
|
191
|
+
}
|
|
192
|
+
const timeoutMs = opts?.timeout ?? this.timeout;
|
|
193
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
194
|
+
try {
|
|
195
|
+
const fetchOpts = {
|
|
196
|
+
method,
|
|
197
|
+
headers,
|
|
198
|
+
signal: controller.signal,
|
|
199
|
+
};
|
|
200
|
+
if (opts?.body !== undefined) {
|
|
201
|
+
fetchOpts.body = JSON.stringify(opts.body);
|
|
202
|
+
}
|
|
203
|
+
const resp = await fetch(url, fetchOpts);
|
|
204
|
+
clearTimeout(timeoutId);
|
|
205
|
+
return resp;
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
clearTimeout(timeoutId);
|
|
209
|
+
throw new errors_js_1.APIConnectionError(`Raw request failed: ${err instanceof Error ? err.message : String(err)}`, err);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.CoreClient = CoreClient;
|
|
214
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";;;AAyDA,gDAUC;AAnED,6CAAuC;AACvC,2CAKqB;AAmDrB,SAAgB,kBAAkB,CAChC,GAAM,EACN,IAAkB;IAElB,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE;QACzC,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IACH,OAAO,GAAyC,CAAC;AACnD,CAAC;AAED,8BAA8B;AAC9B,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAE5E,0BAA0B;AAC1B,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,yBAAyB;AACzB,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B;;;;;GAKG;AACH,MAAa,UAAU;IACZ,MAAM,CAAS;IACf,OAAO,CAAS;IAChB,OAAO,CAAS;IAChB,UAAU,CAAS;IACnB,cAAc,CAAyB;IAEhD,YAAY,OAAsB,EAAE;QAClC,IAAI,CAAC,MAAM;YACT,IAAI,CAAC,MAAM;gBACX,CAAC,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,yBAAa,CACrB,wGAAwG,CACzG,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GACd,OAAO,OAAO,KAAK,WAAW;YAC5B,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;YAC5C,CAAC,CAAC,EAAE,CAAC;QACT,IAAI,CAAC,OAAO,GAAG,CACb,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,IAAI,gCAAgC,CAAC,CACjE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAEtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC;IAClD,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,OAAO,CACX,MAAc,EACd,IAAY,EACZ,IAAc,EACd,MAA+B,EAC/B,OAAwB;QAExB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;QACjD,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAErD,IAAI,SAAkB,CAAC;QAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACrF,CAAC;YAED,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;YAEhE,IAAI,CAAC;gBACH,MAAM,SAAS,GAA2B;oBACxC,MAAM;oBACN,OAAO;oBACP,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC;gBAEF,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;oBAChE,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACxC,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAC7C,YAAY,CAAC,SAAS,CAAC,CAAC;gBAExB,MAAM,IAAI,GAAiB;oBACzB,UAAU,EAAE,QAAQ,CAAC,MAAM;oBAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,SAAS,EACP,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;wBACpC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;wBACpC,SAAS;iBACZ,CAAC;gBAEF,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;oBAChB,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAoC,CAAC;oBACxE,oDAAoD;oBACpD,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAe,CAAC;oBACjD,OAAO,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC1C,CAAC;gBAED,sBAAsB;gBACtB,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC3E,IAAI,YAAY,GAAG,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACnE,IAAI,CAAC;wBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;wBACtC,YAAY,GAAI,OAAe,EAAE,KAAK,IAAK,OAAe,EAAE,OAAO,IAAI,YAAY,CAAC;oBACtF,CAAC;oBAAC,MAAM,CAAC;wBACP,sBAAsB;oBACxB,CAAC;oBACD,MAAM,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACjF,CAAC;gBAED,uCAAuC;gBACvC,SAAS,GAAG,oBAAQ,CAAC,QAAQ,CAC3B,QAAQ,CAAC,MAAM,EACf,IAAI,EACJ,oBAAoB,QAAQ,CAAC,MAAM,GAAG,EACtC,QAAQ,CAAC,OAAO,CACjB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,YAAY,CAAC,SAAS,CAAC,CAAC;gBAExB,IAAI,GAAG,YAAY,oBAAQ,EAAE,CAAC;oBAC5B,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;wBACtE,MAAM,GAAG,CAAC;oBACZ,CAAC;oBACD,SAAS,GAAG,GAAG,CAAC;oBAChB,SAAS;gBACX,CAAC;gBAED,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC7D,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;wBAC7B,MAAM,IAAI,yBAAa,CAAC,uBAAuB,CAAC,CAAC;oBACnD,CAAC;oBACD,MAAM,IAAI,qCAAyB,EAAE,CAAC;gBACxC,CAAC;gBAED,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC3B,MAAM,IAAI,8BAAkB,CAC1B,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACvE,GAAG,CACJ,CAAC;gBACJ,CAAC;gBAED,SAAS,GAAG,GAAG,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,SAAS,IAAI,IAAI,yBAAa,CAAC,8BAA8B,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;OAMG;IACK,SAAS,CAAC,IAAY,EAAE,MAA+B;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;oBACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED,6BAA6B;IACrB,aAAa,CAAC,KAA8B;QAClD,OAAO;YACL,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;YACtC,YAAY,EAAE,2BAA2B,oBAAO,EAAE;YAClD,GAAG,IAAI,CAAC,cAAc;YACtB,GAAG,KAAK;SACT,CAAC;IACJ,CAAC;IAED,qCAAqC;IAC7B,UAAU,CAAC,OAAe,EAAE,SAAkB;QACpD,0CAA0C;QAC1C,wEAAwE;QACxE,IAAI,SAAS,YAAY,oBAAQ,EAAE,CAAC;YAClC,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC7D,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;gBAChC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAAE,OAAO,EAAE,CAAC;YAC5B,CAAC;YAED,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACxD,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;gBACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;oBAAE,OAAO,OAAO,GAAG,IAAI,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;IACjD,CAAC;IAED,oBAAoB;IACZ,MAAM,CAAC,EAAU;QACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CACd,MAAc,EACd,IAAY,EACZ,IAA2E;QAE3E,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;QAChD,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QAElE,IAAI,CAAC;YACH,MAAM,SAAS,GAA2B;gBACxC,MAAM;gBACN,OAAO;gBACP,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC;YACF,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7B,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACzC,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,IAAI,8BAAkB,CAC1B,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACzE,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AA5OD,gCA4OC"}
|