@miosa/sdk 1.2.0 → 1.2.2

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.
@@ -1,77 +0,0 @@
1
- /**
2
- * Quotas — per-external_user_id resource limits.
3
- * Corresponds to: GET/PUT/DELETE /api/v1/quotas/external/{external_user_id}
4
- */
5
-
6
- import type { HttpClient } from "../http.js";
7
-
8
- // ── Resource shapes ──────────────────────────────────────────────────────────
9
-
10
- export interface QuotaData {
11
- external_user_id: string;
12
- max_sandboxes?: number | null;
13
- max_concurrent?: number | null;
14
- max_storage_gb?: number | null;
15
- max_credit_cents?: number | null;
16
- usage?: {
17
- sandbox_count?: number;
18
- concurrent_count?: number;
19
- storage_gb?: number;
20
- credit_cents?: number;
21
- [key: string]: unknown;
22
- };
23
- [key: string]: unknown;
24
- }
25
-
26
- export interface QuotaSetParams {
27
- max_sandboxes?: number;
28
- max_concurrent?: number;
29
- max_storage_gb?: number;
30
- max_credit_cents?: number;
31
- }
32
-
33
- // ── Helpers ───────────────────────────────────────────────────────────────────
34
-
35
- function unwrap<T>(payload: unknown): T {
36
- if (payload && typeof payload === "object" && "data" in (payload as object)) {
37
- return (payload as { data: T }).data;
38
- }
39
- return payload as T;
40
- }
41
-
42
- function stripUndefined(
43
- input: Record<string, unknown>,
44
- ): Record<string, unknown> {
45
- return Object.fromEntries(
46
- Object.entries(input).filter(([, v]) => v !== undefined),
47
- );
48
- }
49
-
50
- // ── Main resource ─────────────────────────────────────────────────────────────
51
-
52
- export class Quotas {
53
- constructor(private readonly http: HttpClient) {}
54
-
55
- /** GET /api/v1/quotas/external/{external_user_id} — current limits + usage. */
56
- async get(externalUserId: string): Promise<QuotaData> {
57
- return unwrap(
58
- await this.http.get<unknown>(`/quotas/external/${externalUserId}`),
59
- );
60
- }
61
-
62
- /** PUT /api/v1/quotas/external/{external_user_id} — set per-user limits. */
63
- async set(
64
- externalUserId: string,
65
- params: QuotaSetParams,
66
- ): Promise<QuotaData> {
67
- const body = stripUndefined(params as Record<string, unknown>);
68
- return unwrap(
69
- await this.http.put<unknown>(`/quotas/external/${externalUserId}`, body),
70
- );
71
- }
72
-
73
- /** DELETE /api/v1/quotas/external/{external_user_id} — revert to tenant default. */
74
- async delete(externalUserId: string): Promise<void> {
75
- await this.http.delete<unknown>(`/quotas/external/${externalUserId}`);
76
- }
77
- }
@@ -1,112 +0,0 @@
1
- /**
2
- * SandboxProcesses — long-running process management inside a sandbox.
3
- * Corresponds to: POST/GET/DELETE /api/v1/sandboxes/{id}/processes
4
- */
5
-
6
- import type { HttpClient } from "../http.js";
7
-
8
- // ── Resource shapes ──────────────────────────────────────────────────────────
9
-
10
- export interface SandboxProcessData {
11
- pid: number;
12
- name?: string;
13
- command: string;
14
- status: "running" | "stopped" | "failed" | string;
15
- started_at?: string;
16
- exit_code?: number | null;
17
- [key: string]: unknown;
18
- }
19
-
20
- export interface SandboxProcessStartParams {
21
- command: string;
22
- env?: Record<string, string>;
23
- name?: string;
24
- }
25
-
26
- export interface SandboxProcessStreamEvent {
27
- stream: "stdout" | "stderr";
28
- line: string;
29
- }
30
-
31
- // ── Helpers ───────────────────────────────────────────────────────────────────
32
-
33
- function unwrap<T>(payload: unknown): T {
34
- if (payload && typeof payload === "object" && "data" in (payload as object)) {
35
- return (payload as { data: T }).data;
36
- }
37
- return payload as T;
38
- }
39
-
40
- function listItems<T>(payload: unknown): T[] {
41
- if (Array.isArray(payload)) return payload;
42
- if (!payload || typeof payload !== "object") return [];
43
- const p = payload as Record<string, unknown>;
44
- for (const k of ["data", "processes", "items"]) {
45
- if (Array.isArray(p[k])) return p[k] as T[];
46
- }
47
- return [];
48
- }
49
-
50
- function stripUndefined(
51
- input: Record<string, unknown>,
52
- ): Record<string, unknown> {
53
- return Object.fromEntries(
54
- Object.entries(input).filter(([, v]) => v !== undefined),
55
- );
56
- }
57
-
58
- // ── Main resource ─────────────────────────────────────────────────────────────
59
-
60
- export class SandboxProcesses {
61
- constructor(
62
- private readonly http: HttpClient,
63
- private readonly sandboxId: string,
64
- ) {}
65
-
66
- private base(): string {
67
- return `/sandboxes/${this.sandboxId}/processes`;
68
- }
69
-
70
- /** POST /api/v1/sandboxes/{id}/processes — start a long-running process. */
71
- async start(params: SandboxProcessStartParams): Promise<SandboxProcessData> {
72
- const body = stripUndefined({
73
- command: params.command,
74
- env: params.env,
75
- name: params.name,
76
- });
77
- return unwrap(await this.http.post<unknown>(this.base(), body));
78
- }
79
-
80
- /** GET /api/v1/sandboxes/{id}/processes — list all processes. */
81
- async list(): Promise<SandboxProcessData[]> {
82
- const data = await this.http.get<unknown>(this.base());
83
- return listItems<SandboxProcessData>(data);
84
- }
85
-
86
- /** GET /api/v1/sandboxes/{id}/processes/{pid} — get a single process. */
87
- async get(pid: number): Promise<SandboxProcessData> {
88
- return unwrap(await this.http.get<unknown>(`${this.base()}/${pid}`));
89
- }
90
-
91
- /** DELETE /api/v1/sandboxes/{id}/processes/{pid} — SIGTERM then SIGKILL after 5s. */
92
- async stop(pid: number): Promise<void> {
93
- await this.http.delete<unknown>(`${this.base()}/${pid}`);
94
- }
95
-
96
- /** GET /api/v1/sandboxes/{id}/processes/{pid}/logs?tail=N — tail log text. */
97
- async logs(pid: number, tail = 200): Promise<string> {
98
- const data = await this.http.get<unknown>(`${this.base()}/${pid}/logs`, {
99
- tail,
100
- });
101
- if (typeof data === "string") return data;
102
- const d = data as Record<string, unknown>;
103
- return String(d.logs ?? d.output ?? d.data ?? "");
104
- }
105
-
106
- /** GET /api/v1/sandboxes/{id}/processes/{pid}/stream (SSE) — live output. */
107
- stream(pid: number): AsyncIterableIterator<SandboxProcessStreamEvent> {
108
- return this.http.stream<SandboxProcessStreamEvent>(
109
- `${this.base()}/${pid}/stream`,
110
- );
111
- }
112
- }
@@ -1,83 +0,0 @@
1
- /**
2
- * SandboxShares — public read-only share URLs for a sandbox.
3
- * Corresponds to: POST/GET/DELETE /api/v1/sandboxes/{id}/shares
4
- */
5
-
6
- import type { HttpClient } from "../http.js";
7
-
8
- // ── Resource shapes ──────────────────────────────────────────────────────────
9
-
10
- export interface SandboxShareData {
11
- share_id: string;
12
- share_url: string;
13
- expires_at?: string | null;
14
- scope: string;
15
- [key: string]: unknown;
16
- }
17
-
18
- export interface SandboxShareCreateParams {
19
- expires_in?: number;
20
- scope?: "read";
21
- }
22
-
23
- // ── Helpers ───────────────────────────────────────────────────────────────────
24
-
25
- function unwrap<T>(payload: unknown): T {
26
- if (payload && typeof payload === "object" && "data" in (payload as object)) {
27
- return (payload as { data: T }).data;
28
- }
29
- return payload as T;
30
- }
31
-
32
- function listItems<T>(payload: unknown): T[] {
33
- if (Array.isArray(payload)) return payload;
34
- if (!payload || typeof payload !== "object") return [];
35
- const p = payload as Record<string, unknown>;
36
- for (const k of ["data", "shares", "items"]) {
37
- if (Array.isArray(p[k])) return p[k] as T[];
38
- }
39
- return [];
40
- }
41
-
42
- function stripUndefined(
43
- input: Record<string, unknown>,
44
- ): Record<string, unknown> {
45
- return Object.fromEntries(
46
- Object.entries(input).filter(([, v]) => v !== undefined),
47
- );
48
- }
49
-
50
- // ── Main resource ─────────────────────────────────────────────────────────────
51
-
52
- export class SandboxShares {
53
- constructor(
54
- private readonly http: HttpClient,
55
- private readonly sandboxId: string,
56
- ) {}
57
-
58
- private base(): string {
59
- return `/sandboxes/${this.sandboxId}/shares`;
60
- }
61
-
62
- /** POST /api/v1/sandboxes/{id}/shares — create a public share URL. */
63
- async create(
64
- params: SandboxShareCreateParams = {},
65
- ): Promise<SandboxShareData> {
66
- const body = stripUndefined({
67
- expires_in: params.expires_in,
68
- scope: params.scope ?? "read",
69
- });
70
- return unwrap(await this.http.post<unknown>(this.base(), body));
71
- }
72
-
73
- /** GET /api/v1/sandboxes/{id}/shares — list all active shares. */
74
- async list(): Promise<SandboxShareData[]> {
75
- const data = await this.http.get<unknown>(this.base());
76
- return listItems<SandboxShareData>(data);
77
- }
78
-
79
- /** DELETE /api/v1/sandboxes/{id}/shares/{share_id} — revoke a share. */
80
- async revoke(shareId: string): Promise<void> {
81
- await this.http.delete<unknown>(`${this.base()}/${shareId}`);
82
- }
83
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * TenantEvents — tenant-scoped SSE event stream.
3
- * Corresponds to: GET /api/v1/events/stream?types=sandbox.*,webhook.delivered
4
- */
5
-
6
- import type { HttpClient } from "../http.js";
7
-
8
- // ── Resource shapes ──────────────────────────────────────────────────────────
9
-
10
- export interface TenantStreamEvent {
11
- type: string;
12
- [key: string]: unknown;
13
- }
14
-
15
- // ── Main resource ─────────────────────────────────────────────────────────────
16
-
17
- export class TenantEvents {
18
- constructor(private readonly http: HttpClient) {}
19
-
20
- /**
21
- * GET /api/v1/events/stream — tenant-scoped SSE event stream.
22
- *
23
- * @param types - Event type globs to filter. Accepts a comma-separated string
24
- * or an array, e.g. `["sandbox.*", "webhook.delivered"]`.
25
- * Omit to receive all event types.
26
- */
27
- stream(types?: string | string[]): AsyncIterableIterator<TenantStreamEvent> {
28
- const typesParam = Array.isArray(types) ? types.join(",") : types;
29
- const query = typesParam ? `?types=${encodeURIComponent(typesParam)}` : "";
30
- return this.http.stream<TenantStreamEvent>(`/events/stream${query}`);
31
- }
32
- }
@@ -1,285 +0,0 @@
1
- /**
2
- * Workspaces resource — top-level tenant workspaces grouping computers.
3
- *
4
- * A workspace is a logical bucket of computers (handy for teams / projects).
5
- * Accessed via `miosa.workspaces` on the top-level client.
6
- *
7
- * @example
8
- * ```ts
9
- * const ws = await miosa.workspaces.create({ name: "prod" });
10
- * const computers = await miosa.workspaces.listComputers(ws.id);
11
- * ```
12
- */
13
-
14
- import type { HttpClient } from "../http.js";
15
- import type { ComputerData } from "../types.js";
16
- import { Computer } from "./computer.js";
17
-
18
- // ── Branded IDs ──────────────────────────────────────────────────────────────
19
-
20
- export type WorkspaceId = string & { readonly __brand: "WorkspaceId" };
21
-
22
- // ── Resource shapes ──────────────────────────────────────────────────────────
23
-
24
- export interface WorkspaceData {
25
- id: WorkspaceId;
26
- tenant_id: string;
27
- name: string;
28
- slug?: string | null;
29
- description?: string | null;
30
- metadata?: Record<string, unknown> | null;
31
- settings?: Record<string, unknown> | null;
32
- created_at?: string;
33
- updated_at?: string;
34
- [key: string]: unknown;
35
- }
36
-
37
- // ── Request payloads ─────────────────────────────────────────────────────────
38
-
39
- export interface WorkspaceCreateParams {
40
- name: string;
41
- slug?: string;
42
- description?: string;
43
- metadata?: Record<string, unknown>;
44
- }
45
-
46
- export interface WorkspaceUpdateParams {
47
- name?: string;
48
- description?: string;
49
- metadata?: Record<string, unknown>;
50
- }
51
-
52
- export interface WorkspaceComputerTemplateCreateParams {
53
- name: string;
54
- templateType?: string;
55
- template_type?: string;
56
- description?: string;
57
- [key: string]: unknown;
58
- }
59
-
60
- // ── Helpers ───────────────────────────────────────────────────────────────────
61
-
62
- function unwrap<T>(payload: unknown): T {
63
- if (payload && typeof payload === "object" && "data" in (payload as object)) {
64
- return (payload as { data: T }).data;
65
- }
66
- return payload as T;
67
- }
68
-
69
- function listItems<T>(
70
- payload: unknown,
71
- candidateKeys: string[] = ["data", "items"],
72
- ): T[] {
73
- if (Array.isArray(payload)) return payload;
74
- if (!payload || typeof payload !== "object") return [];
75
- const p = payload as Record<string, unknown>;
76
- if (Array.isArray(p.data)) return p.data as T[];
77
- for (const key of candidateKeys) {
78
- if (Array.isArray(p[key])) return p[key] as T[];
79
- }
80
- return [];
81
- }
82
-
83
- // ── Workspaces resource ───────────────────────────────────────────────────────
84
-
85
- export class Workspaces {
86
- private readonly http: HttpClient;
87
-
88
- constructor(http: HttpClient) {
89
- this.http = http;
90
- }
91
-
92
- /**
93
- * Create a new workspace.
94
- */
95
- async create(params: WorkspaceCreateParams): Promise<WorkspaceData> {
96
- const payload = await this.http.post<unknown>("/workspaces", params);
97
- return unwrap<WorkspaceData>(payload);
98
- }
99
-
100
- /**
101
- * List all workspaces visible to the current credential.
102
- */
103
- async list(): Promise<WorkspaceData[]> {
104
- const payload = await this.http.get<unknown>("/workspaces");
105
- if (
106
- payload &&
107
- typeof payload === "object" &&
108
- "workspaces" in (payload as object)
109
- ) {
110
- const p = payload as Record<string, unknown>;
111
- return (p["workspaces"] as WorkspaceData[]) ?? [];
112
- }
113
- return listItems<WorkspaceData>(payload, ["data", "workspaces", "items"]);
114
- }
115
-
116
- /**
117
- * Get a single workspace by ID.
118
- */
119
- async get(id: WorkspaceId | string): Promise<WorkspaceData> {
120
- const payload = await this.http.get<unknown>(`/workspaces/${id}`);
121
- return unwrap<WorkspaceData>(payload);
122
- }
123
-
124
- /**
125
- * Update a workspace's metadata.
126
- */
127
- async update(
128
- id: WorkspaceId | string,
129
- params: WorkspaceUpdateParams,
130
- ): Promise<WorkspaceData> {
131
- const payload = await this.http.patch<unknown>(`/workspaces/${id}`, params);
132
- return unwrap<WorkspaceData>(payload);
133
- }
134
-
135
- /**
136
- * Delete a workspace. Does not delete member computers.
137
- */
138
- async delete(id: WorkspaceId | string): Promise<void> {
139
- await this.http.delete<void>(`/workspaces/${id}`);
140
- }
141
-
142
- /**
143
- * Update workspace-level settings.
144
- */
145
- async updateSettings(
146
- id: WorkspaceId | string,
147
- settings: Record<string, unknown>,
148
- ): Promise<WorkspaceData> {
149
- const payload = await this.http.put<unknown>(
150
- `/workspaces/${id}/settings`,
151
- settings,
152
- );
153
- return unwrap<WorkspaceData>(payload);
154
- }
155
-
156
- /**
157
- * List all computers that belong to the given workspace.
158
- */
159
- async listComputers(id: WorkspaceId | string): Promise<Computer[]> {
160
- const payload = await this.http.get<unknown>(`/workspaces/${id}/computers`);
161
- const items = listItems<ComputerData>(payload, [
162
- "data",
163
- "computers",
164
- "items",
165
- ]);
166
- return items.map((d) => new Computer(this.http, d));
167
- }
168
-
169
- /**
170
- * List all sandboxes that belong to this workspace.
171
- */
172
- async listSandboxes(
173
- id: WorkspaceId | string,
174
- ): Promise<Record<string, unknown>[]> {
175
- const payload = await this.http.get<unknown>(`/workspaces/${id}/sandboxes`);
176
- return listItems<Record<string, unknown>>(payload, [
177
- "data",
178
- "sandboxes",
179
- "items",
180
- ]);
181
- }
182
-
183
- /**
184
- * List all deployments that belong to this workspace.
185
- */
186
- async listDeployments(
187
- id: WorkspaceId | string,
188
- ): Promise<Record<string, unknown>[]> {
189
- const payload = await this.http.get<unknown>(
190
- `/workspaces/${id}/deployments`,
191
- );
192
- return listItems<Record<string, unknown>>(payload, [
193
- "data",
194
- "deployments",
195
- "items",
196
- ]);
197
- }
198
-
199
- /**
200
- * List all managed databases that belong to this workspace.
201
- */
202
- async listDatabases(
203
- id: WorkspaceId | string,
204
- ): Promise<Record<string, unknown>[]> {
205
- const payload = await this.http.get<unknown>(`/workspaces/${id}/databases`);
206
- return listItems<Record<string, unknown>>(payload, [
207
- "data",
208
- "databases",
209
- "items",
210
- ]);
211
- }
212
-
213
- /**
214
- * List all projects that belong to this workspace.
215
- */
216
- async listProjects(
217
- id: WorkspaceId | string,
218
- ): Promise<Record<string, unknown>[]> {
219
- const payload = await this.http.get<unknown>(`/workspaces/${id}/projects`);
220
- return listItems<Record<string, unknown>>(payload, [
221
- "data",
222
- "projects",
223
- "items",
224
- ]);
225
- }
226
-
227
- /**
228
- * Return aggregate resource stats for this workspace.
229
- */
230
- async stats(id: WorkspaceId | string): Promise<Record<string, unknown>> {
231
- const payload = await this.http.get<unknown>(`/workspaces/${id}/stats`);
232
- return unwrap<Record<string, unknown>>(payload);
233
- }
234
-
235
- /**
236
- * Return metered usage data for this workspace.
237
- */
238
- async usage(id: WorkspaceId | string): Promise<Record<string, unknown>> {
239
- const payload = await this.http.get<unknown>(`/workspaces/${id}/usage`);
240
- return unwrap<Record<string, unknown>>(payload);
241
- }
242
-
243
- /**
244
- * Return activity feed for this workspace.
245
- */
246
- async activity(id: WorkspaceId | string): Promise<Record<string, unknown>[]> {
247
- const payload = await this.http.get<unknown>(`/workspaces/${id}/activity`);
248
- return listItems<Record<string, unknown>>(payload, [
249
- "data",
250
- "activity",
251
- "events",
252
- "items",
253
- ]);
254
- }
255
-
256
- /**
257
- * List computer templates available in this workspace.
258
- */
259
- async listComputerTemplates(
260
- id: WorkspaceId | string,
261
- ): Promise<Record<string, unknown>[]> {
262
- const payload = await this.http.get<unknown>(
263
- `/workspaces/${id}/computer-templates`,
264
- );
265
- return listItems<Record<string, unknown>>(payload, [
266
- "data",
267
- "templates",
268
- "items",
269
- ]);
270
- }
271
-
272
- /**
273
- * Create a computer template scoped to this workspace.
274
- */
275
- async createComputerTemplate(
276
- id: WorkspaceId | string,
277
- params: WorkspaceComputerTemplateCreateParams,
278
- ): Promise<Record<string, unknown>> {
279
- const payload = await this.http.post<unknown>(
280
- `/workspaces/${id}/computer-templates`,
281
- params,
282
- );
283
- return unwrap<Record<string, unknown>>(payload);
284
- }
285
- }