cosmos-cloud-sdk 0.22.0-unstable04

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,139 @@
1
+ # cosmos-cloud-sdk
2
+
3
+ JavaScript/TypeScript SDK for the [Cosmos Server](https://github.com/azukaar/cosmos-server) API.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install cosmos-cloud-sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```js
14
+ const { createClient } = require('cosmos-cloud-sdk');
15
+ // or: import { createClient } from 'cosmos-cloud-sdk';
16
+
17
+ const cosmos = createClient({
18
+ baseUrl: 'https://my-cosmos.example.com',
19
+ token: 'cosmos_abc123...',
20
+ });
21
+
22
+ // List containers
23
+ const containers = await cosmos.docker.list();
24
+ console.log(containers.data);
25
+
26
+ // List users
27
+ const users = await cosmos.users.list();
28
+
29
+ // Get server status
30
+ const status = await cosmos.getStatus();
31
+ ```
32
+
33
+ ## API Reference
34
+
35
+ ### `createClient({ baseUrl, token })`
36
+
37
+ Creates a Cosmos API client.
38
+
39
+ - `baseUrl` — Your Cosmos server URL (e.g. `https://my-cosmos.example.com`)
40
+ - `token` — API token (starts with `cosmos_`)
41
+
42
+ Returns an object with namespaced API methods:
43
+
44
+ ### Namespaces
45
+
46
+ | Namespace | Description |
47
+ |-----------|-------------|
48
+ | `cosmos.docker` | Containers, volumes, networks, images |
49
+ | `cosmos.users` | User management, 2FA, notifications |
50
+ | `cosmos.config` | Server configuration, routes, DNS |
51
+ | `cosmos.storage` | Disks, mounts, RAID, SnapRAID |
52
+ | `cosmos.constellation` | VPN devices, tunnels |
53
+ | `cosmos.cron` | Job management |
54
+ | `cosmos.backups` | Backup & restore |
55
+ | `cosmos.metrics` | Metrics & events |
56
+ | `cosmos.market` | Marketplace |
57
+ | `cosmos.rclone` | Cloud storage (rclone) |
58
+ | `cosmos.apiTokens` | API token management |
59
+ | `cosmos.auth` | Login, logout, sudo |
60
+
61
+ ### Top-level methods
62
+
63
+ | Method | Description |
64
+ |--------|-------------|
65
+ | `cosmos.getStatus()` | Server status |
66
+ | `cosmos.isOnline()` | Check connectivity |
67
+ | `cosmos.restartServer()` | Restart server |
68
+ | `cosmos.forceAutoUpdate()` | Force update |
69
+ | `cosmos.terminal(cmd?)` | Host terminal (WebSocket) |
70
+ | `cosmos.uploadImage(file, name)` | Upload image |
71
+ | `cosmos.checkHost(host)` | DNS check |
72
+ | `cosmos.getDNS(host)` | DNS lookup |
73
+
74
+ ### Examples
75
+
76
+ ```js
77
+ // Docker
78
+ const containers = await cosmos.docker.list();
79
+ await cosmos.docker.manageContainer('my-app', 'stop');
80
+ await cosmos.docker.manageContainer('my-app', 'start');
81
+ const logs = await cosmos.docker.getContainerLogs('my-app', 'error', 100);
82
+
83
+ // Streaming (image pull with progress)
84
+ await cosmos.docker.pullImage('nginx:latest', (line) => {
85
+ console.log('Progress:', line);
86
+ });
87
+
88
+ // Users
89
+ await cosmos.users.create({ nickname: 'bob', password: '...' });
90
+ const user = await cosmos.users.get('bob');
91
+
92
+ // Config
93
+ const config = await cosmos.config.get();
94
+ await cosmos.config.set(config.data);
95
+ await cosmos.config.updateDNS({ dnsPort: '53' });
96
+
97
+ // API tokens
98
+ const tokens = await cosmos.apiTokens.list();
99
+ const newToken = await cosmos.apiTokens.create({
100
+ name: 'my-automation',
101
+ readOnly: true,
102
+ });
103
+
104
+ // Backups
105
+ const snapshots = await cosmos.backups.listSnapshots('daily');
106
+ await cosmos.backups.restoreBackup('daily', { snapshotId: 'abc', target: '/data' });
107
+
108
+ // WebSocket (terminal)
109
+ const ws = cosmos.docker.attachTerminal('my-container');
110
+ ws.onmessage = (e) => console.log(e.data);
111
+ ```
112
+
113
+ ## More Examples
114
+
115
+ See the [examples directory](./examples/index.md) for full, runnable scripts covering dashboards, CI/CD deployments, container management, and backups.
116
+
117
+ ## Response Format
118
+
119
+ All methods return the raw API response:
120
+
121
+ ```js
122
+ {
123
+ status: 'OK',
124
+ data: { /* endpoint-specific data */ },
125
+ message: '...'
126
+ }
127
+ ```
128
+
129
+ On error, a `CosmosError` is thrown with `message`, `status`, and `code` properties.
130
+
131
+ ## Requirements
132
+
133
+ - Node.js 18+ (uses built-in `fetch`)
134
+ - Works in browsers too (bundled as ESM and CJS)
135
+ - WebSocket support requires `ws` package in Node.js < 22
136
+
137
+ ## Version
138
+
139
+ The SDK version is synced with the Cosmos Server version.
@@ -0,0 +1,437 @@
1
+ interface ApiResponse<T = any> {
2
+ status: string;
3
+ data: T;
4
+ message?: string;
5
+ code?: string;
6
+ }
7
+ type ApiFetch = (path: string, options?: RequestInit) => Promise<Response>;
8
+
9
+ declare function createApiClient(baseUrl?: string, token?: string | null): {
10
+ apiFetch: ApiFetch;
11
+ createWs: (path: string) => WebSocket;
12
+ };
13
+
14
+ interface LoginRequest {
15
+ username: string;
16
+ password: string;
17
+ }
18
+ interface UserMe {
19
+ Nickname: string;
20
+ Email: string;
21
+ Role: number;
22
+ MFAState: number;
23
+ }
24
+
25
+ interface User {
26
+ Nickname: string;
27
+ Email: string;
28
+ Role: number;
29
+ RegisterKey: string;
30
+ RegisterKeyExp: string;
31
+ RegisteredAt: string;
32
+ LastPasswordChangedAt: string;
33
+ CreatedAt: string;
34
+ LastLogin: string;
35
+ MFAState: number;
36
+ Link?: string;
37
+ }
38
+
39
+ interface Route {
40
+ Name: string;
41
+ }
42
+ type Operation = 'replace' | 'move_up' | 'move_down' | 'delete' | 'add';
43
+
44
+ interface ContainerState {
45
+ Status: string;
46
+ Running: boolean;
47
+ Paused: boolean;
48
+ Restarting: boolean;
49
+ Dead: boolean;
50
+ Pid: number;
51
+ ExitCode: number;
52
+ StartedAt: string;
53
+ FinishedAt: string;
54
+ [key: string]: any;
55
+ }
56
+ interface Container {
57
+ ID: string;
58
+ Name: string;
59
+ Image: string;
60
+ Created: string;
61
+ State: ContainerState;
62
+ Config: {
63
+ Hostname: string;
64
+ Image: string;
65
+ Env: string[];
66
+ Cmd: string[];
67
+ Labels: Record<string, string>;
68
+ ExposedPorts: Record<string, object>;
69
+ [key: string]: any;
70
+ };
71
+ HostConfig: any;
72
+ NetworkSettings: any;
73
+ Mounts: any[];
74
+ [key: string]: any;
75
+ }
76
+ interface DockerNetwork {
77
+ ID: string;
78
+ Name: string;
79
+ Driver: string;
80
+ Scope: string;
81
+ Internal: boolean;
82
+ Attachable: boolean;
83
+ Labels: Record<string, string>;
84
+ [key: string]: any;
85
+ }
86
+ interface DockerVolume {
87
+ Name: string;
88
+ Driver: string;
89
+ Mountpoint: string;
90
+ Labels: Record<string, string>;
91
+ Scope: string;
92
+ Options: Record<string, string>;
93
+ [key: string]: any;
94
+ }
95
+
96
+ interface MarketApp {
97
+ Name: string;
98
+ Description: string;
99
+ Url: string;
100
+ LongDescription: string;
101
+ Tags: string[];
102
+ Repository: string;
103
+ Image: string;
104
+ Screenshots: string[];
105
+ Icon: string;
106
+ Compose: string;
107
+ SupportedArchitectures: string[];
108
+ [key: string]: any;
109
+ }
110
+ interface MarketResult {
111
+ Showcase: MarketApp[];
112
+ All: Record<string, MarketApp[]>;
113
+ }
114
+
115
+ interface CreateAPITokenRequest {
116
+ name: string;
117
+ description?: string;
118
+ readOnly?: boolean;
119
+ ipWhitelist?: string[];
120
+ restrictToConstellation?: boolean;
121
+ }
122
+ interface CreateAPITokenResponse {
123
+ token: string;
124
+ name: string;
125
+ }
126
+ interface APITokenConfig {
127
+ Name: string;
128
+ Description?: string;
129
+ Owner?: string;
130
+ TokenHash: string;
131
+ Permissions: number[];
132
+ IPWhitelist?: string[];
133
+ RestrictToConstellation: boolean;
134
+ CreatedAt: string;
135
+ }
136
+
137
+ interface ConstellationDevice {
138
+ Nickname: string;
139
+ DeviceName: string;
140
+ PublicKey: string;
141
+ IP: string;
142
+ IsLighthouse: boolean;
143
+ IsRelay: boolean;
144
+ Blocked: boolean;
145
+ Fingerprint: string;
146
+ PublicHostname: string;
147
+ Port: string;
148
+ [key: string]: any;
149
+ }
150
+
151
+ interface CronJob {
152
+ Disabled: boolean;
153
+ Scheduler: string;
154
+ Cancellable: boolean;
155
+ Name: string;
156
+ Crontab: string;
157
+ Running: boolean;
158
+ LastStarted: string;
159
+ LastRun: string;
160
+ LastRunSuccess: boolean;
161
+ Container: string;
162
+ Resource: string;
163
+ }
164
+
165
+ interface DiskInfo {
166
+ Path: string;
167
+ Name: string;
168
+ Size: number;
169
+ Used: number;
170
+ [key: string]: any;
171
+ }
172
+ interface MountRequest {
173
+ path: string;
174
+ mountPoint: string;
175
+ permanent: boolean;
176
+ netDisk?: boolean;
177
+ chown?: string;
178
+ }
179
+ interface UnmountRequest {
180
+ mountPoint: string;
181
+ permanent: boolean;
182
+ chown?: string;
183
+ }
184
+ interface MergeRequest {
185
+ Branches: string[];
186
+ MountPoint: string;
187
+ Permanent: boolean;
188
+ Chown?: string;
189
+ Opts?: string;
190
+ }
191
+ interface SnapRAIDConfig {
192
+ Name: string;
193
+ Enabled: boolean;
194
+ Data: Record<string, string>;
195
+ Parity: string[];
196
+ SyncCrontab: string;
197
+ ScrubCrontab: string;
198
+ CheckOnFix: boolean;
199
+ }
200
+ interface RaidCreateRequest {
201
+ name: string;
202
+ level: string;
203
+ devices: string[];
204
+ spares?: string[];
205
+ metadata?: string;
206
+ }
207
+
208
+ interface BackupConfig {
209
+ name: string;
210
+ source: string;
211
+ repository: string;
212
+ password: string;
213
+ crontab?: string;
214
+ tags?: string[];
215
+ exclude?: string[];
216
+ autoStopContainers?: boolean;
217
+ }
218
+ interface RestoreConfig {
219
+ snapshotId: string;
220
+ target: string;
221
+ include?: string[];
222
+ }
223
+
224
+ declare function createClient({ baseUrl, token }: {
225
+ baseUrl: string;
226
+ token: string;
227
+ }): {
228
+ auth: {
229
+ login: (values: LoginRequest) => Promise<ApiResponse>;
230
+ logout: () => Promise<ApiResponse>;
231
+ me: () => Promise<UserMe>;
232
+ sudo: (values: {
233
+ password: string;
234
+ }) => Promise<ApiResponse>;
235
+ };
236
+ users: {
237
+ list: () => Promise<ApiResponse<User[]>>;
238
+ create: (values: Partial<User> & {
239
+ password?: string;
240
+ }) => Promise<ApiResponse>;
241
+ register: (values: {
242
+ nickname: string;
243
+ password: string;
244
+ registerKey?: string;
245
+ }) => Promise<ApiResponse>;
246
+ invite: (values: {
247
+ nickname: string;
248
+ email?: string;
249
+ }) => Promise<ApiResponse>;
250
+ edit: (nickname: string, values: Partial<User>) => Promise<ApiResponse>;
251
+ get: (nickname: string) => Promise<ApiResponse<User>>;
252
+ deleteUser: (nickname: string) => Promise<ApiResponse>;
253
+ new2FA: (nickname: string) => Promise<ApiResponse>;
254
+ check2FA: (values: string) => Promise<ApiResponse>;
255
+ reset2FA: (values: string) => Promise<ApiResponse>;
256
+ resetPassword: (values: {
257
+ nickname: string;
258
+ password?: string;
259
+ }) => Promise<ApiResponse>;
260
+ getNotifs: () => Promise<ApiResponse>;
261
+ readNotifs: (notifs: string[]) => Promise<ApiResponse>;
262
+ };
263
+ config: {
264
+ get: () => Promise<ApiResponse<any>>;
265
+ set: (values: any) => Promise<ApiResponse<any>>;
266
+ restart: () => Promise<Response>;
267
+ rawUpdateRoute: (routeName: string, operation: Operation, newRoute?: Route) => Promise<ApiResponse>;
268
+ replaceRoute: (routeName: string, newRoute: Route) => Promise<ApiResponse>;
269
+ moveRouteUp: (routeName: string) => Promise<ApiResponse>;
270
+ moveRouteDown: (routeName: string) => Promise<ApiResponse>;
271
+ deleteRoute: (routeName: string) => Promise<ApiResponse>;
272
+ addRoute: (newRoute: Route) => Promise<ApiResponse>;
273
+ canSendEmail: () => Promise<any>;
274
+ getBackup: () => Promise<ApiResponse<any>>;
275
+ getDashboard: () => Promise<ApiResponse<any>>;
276
+ updateDNS: (dnsConfig: {
277
+ dnsPort?: string;
278
+ dnsFallback?: string;
279
+ dnsBlockBlacklist?: boolean;
280
+ dnsAdditionalBlocklists?: string[];
281
+ customDNSEntries?: {
282
+ Type: string;
283
+ Key: string;
284
+ Value: string;
285
+ }[];
286
+ }) => Promise<ApiResponse<any>>;
287
+ };
288
+ docker: {
289
+ list: () => Promise<ApiResponse<Container[]>>;
290
+ get: (containerName: string) => Promise<ApiResponse<Container>>;
291
+ newDB: () => Promise<ApiResponse>;
292
+ secure: (id: string, res: string) => Promise<ApiResponse>;
293
+ manageContainer: (containerId: string, action: string) => Promise<ApiResponse>;
294
+ volumeList: () => Promise<ApiResponse<DockerVolume[]>>;
295
+ volumeDelete: (name: string) => Promise<ApiResponse>;
296
+ networkList: () => Promise<ApiResponse<DockerNetwork[]>>;
297
+ networkDelete: (name: string) => Promise<ApiResponse>;
298
+ getContainerLogs: (containerId: string, searchQuery?: string, limit?: number, lastReceivedLogs?: string, errorOnly?: string) => Promise<ApiResponse>;
299
+ updateContainer: (containerId: string, values: any) => Promise<ApiResponse>;
300
+ listContainerNetworks: (containerId: string) => Promise<ApiResponse<DockerNetwork[]>>;
301
+ createNetwork: (values: {
302
+ Name: string;
303
+ Driver?: string;
304
+ [key: string]: any;
305
+ }) => Promise<ApiResponse>;
306
+ attachNetwork: (containerId: string, networkId: string) => Promise<ApiResponse>;
307
+ detachNetwork: (containerId: string, networkId: string) => Promise<ApiResponse>;
308
+ createVolume: (values: {
309
+ Name: string;
310
+ Driver?: string;
311
+ [key: string]: any;
312
+ }) => Promise<ApiResponse>;
313
+ attachTerminal: (containerId: string, readonly?: boolean) => WebSocket;
314
+ createTerminal: (containerId: string) => WebSocket;
315
+ createService: (serviceData: any, onProgress: (line: string) => void) => Promise<ReadableStream>;
316
+ pullImage: (imageName: string, onProgress: (line: string) => void, ifMissing?: boolean) => Promise<ReadableStream>;
317
+ autoUpdate: (id: string, toggle: string) => Promise<ApiResponse>;
318
+ updateContainerImage: (containerName: string, onProgress: (line: string) => void) => Promise<ReadableStream>;
319
+ exportContainer: (containerId: string, values: any) => Promise<ApiResponse>;
320
+ migrateHost: (values: any) => Promise<ApiResponse>;
321
+ };
322
+ market: {
323
+ list: () => Promise<ApiResponse<MarketResult>>;
324
+ };
325
+ constellation: {
326
+ list: () => Promise<ApiResponse<any>>;
327
+ addDevice: (device: any) => Promise<ApiResponse<any>>;
328
+ resyncDevice: (device: any) => Promise<ApiResponse<any>>;
329
+ restart: () => Promise<ApiResponse<any>>;
330
+ getConfig: () => Promise<ApiResponse<any>>;
331
+ getLogs: () => Promise<ApiResponse<any>>;
332
+ reset: () => Promise<ApiResponse<any>>;
333
+ connect: (file: any) => Promise<unknown>;
334
+ block: (nickname: any, devicename: any, block: any) => Promise<ApiResponse<any>>;
335
+ ping: () => Promise<ApiResponse<any>>;
336
+ create: (deviceName: any, isLighthouse: any, hostname: any, ipRange: any) => Promise<ApiResponse<any>>;
337
+ pingDevice: (deviceId: any) => Promise<ApiResponse<any>>;
338
+ tunnels: () => Promise<ApiResponse<any>>;
339
+ editDevice: (device: any) => Promise<ApiResponse<any>>;
340
+ getNextIP: () => Promise<ApiResponse<any>>;
341
+ };
342
+ metrics: {
343
+ get: (metarr: string[]) => Promise<ApiResponse>;
344
+ reset: () => Promise<ApiResponse>;
345
+ list: () => Promise<ApiResponse<Record<string, string>>>;
346
+ events: (from: string, to: string, search?: string, query?: string, page?: string, logLevel?: string) => Promise<ApiResponse>;
347
+ };
348
+ storage: {
349
+ mounts: {
350
+ list: () => Promise<ApiResponse>;
351
+ mount: ({ path, mountPoint, permanent, netDisk, chown }: MountRequest) => Promise<ApiResponse>;
352
+ unmount: ({ mountPoint, permanent, chown }: UnmountRequest) => Promise<ApiResponse>;
353
+ merge: (args: MergeRequest) => Promise<ApiResponse>;
354
+ };
355
+ disks: {
356
+ list: () => Promise<ApiResponse<DiskInfo[]>>;
357
+ smartDef: () => Promise<ApiResponse>;
358
+ format({ disk, format, password }: {
359
+ disk: string;
360
+ format: string;
361
+ password?: string;
362
+ }, onProgress: (line: string) => void): Promise<ReadableStream>;
363
+ };
364
+ snapRAID: {
365
+ create: (args: Partial<SnapRAIDConfig>) => Promise<ApiResponse>;
366
+ update: (name: string, args: Partial<SnapRAIDConfig>) => Promise<ApiResponse>;
367
+ delete: (name: string) => Promise<ApiResponse>;
368
+ list: (args?: any) => Promise<ApiResponse<SnapRAIDConfig[]>>;
369
+ sync: (name: string) => Promise<ApiResponse>;
370
+ fix: (name: string) => Promise<ApiResponse>;
371
+ enable: (name: string, enable: boolean) => Promise<ApiResponse>;
372
+ scrub: (name: string) => Promise<ApiResponse>;
373
+ };
374
+ raid: {
375
+ list: () => Promise<ApiResponse>;
376
+ create: ({ name, level, devices, spares, metadata }: RaidCreateRequest) => Promise<ApiResponse>;
377
+ delete: (name: string) => Promise<ApiResponse>;
378
+ status: (name: string) => Promise<ApiResponse>;
379
+ addDevice: (name: string, device: string) => Promise<ApiResponse>;
380
+ replaceDevice: (name: string, oldDevice: string, newDevice: string) => Promise<ApiResponse>;
381
+ resize: (name: string) => Promise<ApiResponse>;
382
+ };
383
+ newFolder: (storage: string, path: string, folder: string) => Promise<ApiResponse>;
384
+ listDir: (storage: string, path: string) => Promise<ApiResponse>;
385
+ };
386
+ cron: {
387
+ listen: () => WebSocket;
388
+ list: () => Promise<ApiResponse<Record<string, Record<string, CronJob>>>>;
389
+ run: (scheduler: string, name: string) => Promise<ApiResponse>;
390
+ stop: (scheduler: string, name: string) => Promise<ApiResponse>;
391
+ get: (scheduler: string, name: string) => Promise<ApiResponse<CronJob>>;
392
+ deleteJob: (name: string) => Promise<ApiResponse>;
393
+ runningJobs: () => Promise<ApiResponse>;
394
+ };
395
+ rclone: {
396
+ create: (data: any) => Promise<any>;
397
+ list: () => Promise<any>;
398
+ listRemotes: () => Promise<any>;
399
+ deleteRemote: (remoteName: string) => Promise<any>;
400
+ update: (data: any) => Promise<any>;
401
+ coreStats: (remoteName: string, remotePath?: string) => Promise<any>;
402
+ stats: (remoteName: string) => Promise<any>;
403
+ pingStorage: (remoteName: string) => Promise<any>;
404
+ restart: () => Promise<ApiResponse>;
405
+ };
406
+ backups: {
407
+ listSnapshots: (name: string) => Promise<ApiResponse<any>>;
408
+ listFolders: (name: string, snapshot: string, path?: string) => Promise<ApiResponse<any>>;
409
+ restoreBackup: (name: string, config: RestoreConfig) => Promise<ApiResponse<any>>;
410
+ addBackup: (config: BackupConfig) => Promise<ApiResponse<any>>;
411
+ removeBackup: (name: string, deleteRepo?: boolean) => Promise<ApiResponse<any>>;
412
+ listRepo: () => Promise<ApiResponse<any>>;
413
+ listSnapshotsFromRepo: (name: string) => Promise<ApiResponse<any>>;
414
+ forgetSnapshot: (name: string, snapshot: string, deleteRepo?: boolean) => Promise<ApiResponse<any>>;
415
+ editBackup: (config: BackupConfig) => Promise<ApiResponse<any>>;
416
+ backupNow: (name: string) => Promise<ApiResponse<any>>;
417
+ forgetNow: (name: string) => Promise<ApiResponse<any>>;
418
+ subfolderRestoreSize: (name: string, snapshot: string, path: string) => Promise<ApiResponse<any>>;
419
+ unlockRepository: (name: string) => Promise<ApiResponse<any>>;
420
+ repoStats: (name: string) => Promise<ApiResponse<any>>;
421
+ };
422
+ apiTokens: {
423
+ list: () => Promise<ApiResponse<Record<string, APITokenConfig>>>;
424
+ create: (request: CreateAPITokenRequest) => Promise<ApiResponse<CreateAPITokenResponse>>;
425
+ remove: (name: string) => Promise<ApiResponse>;
426
+ };
427
+ getStatus: () => Promise<ApiResponse<any>>;
428
+ isOnline: () => Promise<any>;
429
+ uploadImage: (file: any, name: string) => Promise<ApiResponse<any>>;
430
+ restartServer: () => Promise<ApiResponse<any>>;
431
+ terminal: (startCmd?: string) => WebSocket;
432
+ forceAutoUpdate: () => Promise<ApiResponse<any>>;
433
+ checkHost: (host: string) => Promise<any>;
434
+ getDNS: (host: string) => Promise<any>;
435
+ };
436
+
437
+ export { type APITokenConfig, type ApiFetch, type ApiResponse, type BackupConfig, type ConstellationDevice, type Container, type ContainerState, type CreateAPITokenRequest, type CreateAPITokenResponse, type CronJob, type DiskInfo, type DockerNetwork, type DockerVolume, type LoginRequest, type MarketApp, type MarketResult, type MergeRequest, type MountRequest, type Operation, type RaidCreateRequest, type RestoreConfig, type Route, type SnapRAIDConfig, type UnmountRequest, type User, type UserMe, createApiClient, createClient };