@miosa/sdk 0.3.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.
Files changed (81) hide show
  1. package/README.md +181 -0
  2. package/dist/index.d.ts +4689 -0
  3. package/dist/index.js +6045 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +63 -0
  6. package/src/client.ts +249 -0
  7. package/src/errors.ts +136 -0
  8. package/src/http.test.ts +374 -0
  9. package/src/http.ts +390 -0
  10. package/src/index.ts +452 -0
  11. package/src/resources/admin.ts +348 -0
  12. package/src/resources/analytics.ts +60 -0
  13. package/src/resources/api-keys.ts +119 -0
  14. package/src/resources/audit-log.ts +64 -0
  15. package/src/resources/benchmarks.ts +104 -0
  16. package/src/resources/builder-sessions.ts +75 -0
  17. package/src/resources/channels.ts +143 -0
  18. package/src/resources/checkpoints.ts +225 -0
  19. package/src/resources/command-center.ts +73 -0
  20. package/src/resources/community.ts +103 -0
  21. package/src/resources/completions.ts +104 -0
  22. package/src/resources/computer-auto-stop.ts +43 -0
  23. package/src/resources/computer-env.ts +76 -0
  24. package/src/resources/computer-logs.ts +50 -0
  25. package/src/resources/computer-osa.ts +76 -0
  26. package/src/resources/computer-ports.ts +91 -0
  27. package/src/resources/computer-terminal.ts +61 -0
  28. package/src/resources/computer-volumes.ts +64 -0
  29. package/src/resources/computer.ts +530 -0
  30. package/src/resources/computers.ts +75 -0
  31. package/src/resources/credits.ts +43 -0
  32. package/src/resources/cron-jobs.ts +191 -0
  33. package/src/resources/custom_domains.ts +123 -0
  34. package/src/resources/dashboard.ts +49 -0
  35. package/src/resources/databases.ts +218 -0
  36. package/src/resources/deployments.ts +777 -0
  37. package/src/resources/desktop.ts +134 -0
  38. package/src/resources/email.ts +212 -0
  39. package/src/resources/embeddings.ts +36 -0
  40. package/src/resources/events.ts +296 -0
  41. package/src/resources/exec.ts +319 -0
  42. package/src/resources/external-keys.ts +79 -0
  43. package/src/resources/files.test.ts +339 -0
  44. package/src/resources/files.ts +220 -0
  45. package/src/resources/flat-custom-domains.ts +127 -0
  46. package/src/resources/functions.ts +178 -0
  47. package/src/resources/health-checks.ts +165 -0
  48. package/src/resources/integrations.ts +183 -0
  49. package/src/resources/mcp.ts +70 -0
  50. package/src/resources/models.ts +45 -0
  51. package/src/resources/network_policy.ts +73 -0
  52. package/src/resources/open-computers/agents.ts +91 -0
  53. package/src/resources/open-computers/apps.ts +102 -0
  54. package/src/resources/open-computers/clusters.ts +88 -0
  55. package/src/resources/open-computers/desktop.ts +34 -0
  56. package/src/resources/open-computers/files.ts +97 -0
  57. package/src/resources/open-computers/hosts.ts +85 -0
  58. package/src/resources/open-computers/index.ts +98 -0
  59. package/src/resources/open-computers/jobs.ts +75 -0
  60. package/src/resources/open-computers/open_computers.test.ts +288 -0
  61. package/src/resources/open-computers/secrets.ts +115 -0
  62. package/src/resources/open-computers/terminal.ts +33 -0
  63. package/src/resources/open-computers/tunnels.ts +87 -0
  64. package/src/resources/open-computers/types.ts +343 -0
  65. package/src/resources/open-computers/workspaces.ts +135 -0
  66. package/src/resources/project-auth.ts +142 -0
  67. package/src/resources/project-integrations.ts +133 -0
  68. package/src/resources/provider-defaults.ts +89 -0
  69. package/src/resources/regions.ts +94 -0
  70. package/src/resources/sandbox-templates.ts +195 -0
  71. package/src/resources/sandboxes.live.test.ts +92 -0
  72. package/src/resources/sandboxes.test.ts +624 -0
  73. package/src/resources/sandboxes.ts +1173 -0
  74. package/src/resources/settings.ts +143 -0
  75. package/src/resources/snapshots-standalone.ts +51 -0
  76. package/src/resources/storage.ts +221 -0
  77. package/src/resources/tenant.ts +39 -0
  78. package/src/resources/usage.ts +85 -0
  79. package/src/resources/volumes.ts +117 -0
  80. package/src/resources/webhooks.ts +171 -0
  81. package/src/types.ts +460 -0
@@ -0,0 +1,777 @@
1
+ /**
2
+ * Deployments resource — sandbox→production publishing surface.
3
+ *
4
+ * Backend phase status:
5
+ * - list / get / create / update / delete / env: repo deployment surface.
6
+ * - publish / versions.* / releases.* / rollback / domains.*: live release surface.
7
+ * - runtimeInstances.*: dynamic runtime status/log inspection.
8
+ * - publishFromSandbox: direct sandbox -> deployment bridge.
9
+ *
10
+ * See docs/deploy/* for the conceptual model.
11
+ */
12
+
13
+ import { randomUUID } from "node:crypto";
14
+
15
+ import type { HttpClient } from "../http.js";
16
+
17
+ // ── Branded IDs ─────────────────────────────────────────────────────────────
18
+
19
+ export type DeploymentId = string & { readonly __brand: "DeploymentId" };
20
+ export type DeploymentVersionId = string & {
21
+ readonly __brand: "DeploymentVersionId";
22
+ };
23
+ export type DeploymentReleaseId = string & {
24
+ readonly __brand: "DeploymentReleaseId";
25
+ };
26
+ export type DeploymentServiceId = string & {
27
+ readonly __brand: "DeploymentServiceId";
28
+ };
29
+ export type RuntimeInstanceId = string & {
30
+ readonly __brand: "RuntimeInstanceId";
31
+ };
32
+
33
+ // ── States / enums ──────────────────────────────────────────────────────────
34
+
35
+ export type DeploymentState =
36
+ | "pending"
37
+ | "building"
38
+ | "running"
39
+ | "stopped"
40
+ | "failed";
41
+
42
+ export type DeploymentVersionKind = "static" | "dynamic" | "sandbox_backed";
43
+
44
+ export type DeploymentVersionState =
45
+ | "created"
46
+ | "building"
47
+ | "ready"
48
+ | "failed"
49
+ | "archived";
50
+
51
+ export type DeploymentSourceType = "repo" | "sandbox" | "upload";
52
+
53
+ export type DeploymentServiceType =
54
+ | "static_web"
55
+ | "web"
56
+ | "api"
57
+ | "function"
58
+ | "worker"
59
+ | "cron"
60
+ | "postgres"
61
+ | "redis"
62
+ | "bucket"
63
+ | "volume";
64
+
65
+ export type RuntimeInstanceState =
66
+ | "provisioning"
67
+ | "starting"
68
+ | "healthy"
69
+ | "unhealthy"
70
+ | "error"
71
+ | "stopped"
72
+ | "destroyed";
73
+
74
+ // ── Shared attribution ──────────────────────────────────────────────────────
75
+
76
+ export interface ExternalAttribution {
77
+ externalWorkspaceId?: string;
78
+ external_workspace_id?: string;
79
+ externalUserId?: string;
80
+ external_user_id?: string;
81
+ externalProjectId?: string;
82
+ external_project_id?: string;
83
+ }
84
+
85
+ // ── Resource shapes ─────────────────────────────────────────────────────────
86
+
87
+ export interface DeploymentData {
88
+ id: DeploymentId;
89
+ tenant_id: string;
90
+ owner_id?: string;
91
+ name: string;
92
+ slug: string;
93
+ /**
94
+ * @deprecated — repo-based model. New deployments use source_type: "sandbox"
95
+ * with `source_sandbox_id` on the version row. Will become nullable.
96
+ */
97
+ repo_url?: string;
98
+ repo_provider?: "github";
99
+ branch?: string;
100
+ build_command?: string | null;
101
+ run_command?: string | null;
102
+ runtime_image?: string | null;
103
+ current_build_id?: string | null;
104
+ active_version_id?: string | null;
105
+ source_type?: DeploymentSourceType;
106
+ state: DeploymentState;
107
+ auto_deploy?: boolean;
108
+ custom_domain_id?: string | null;
109
+ linked_database_id?: string | null;
110
+ metadata?: Record<string, unknown>;
111
+ external_workspace_id?: string | null;
112
+ external_user_id?: string | null;
113
+ external_project_id?: string | null;
114
+ public_url?: string | null;
115
+ created_at?: string;
116
+ updated_at?: string;
117
+ }
118
+
119
+ export type DeploymentDatabaseRequest =
120
+ | boolean
121
+ | {
122
+ engine?: "postgresql" | "mysql" | "redis";
123
+ size?: "xs" | "small" | "medium" | "large";
124
+ storage_mb?: number;
125
+ region?: string;
126
+ };
127
+
128
+ export interface DeploymentVersionData {
129
+ id: DeploymentVersionId;
130
+ deployment_id: DeploymentId;
131
+ tenant_id: string;
132
+ created_by?: string | null;
133
+ source_sandbox_id?: string | null;
134
+ build_id?: string | null;
135
+ version_number: number;
136
+ kind: DeploymentVersionKind;
137
+ state: DeploymentVersionState;
138
+ artifact_uri?: string | null;
139
+ artifact_manifest?: Record<string, unknown>;
140
+ artifact_sha256?: string | null;
141
+ runtime_image?: string | null;
142
+ runtime_command?: string | null;
143
+ runtime_port?: number | null;
144
+ health_check_path?: string | null;
145
+ build_log_uri?: string | null;
146
+ metadata?: Record<string, unknown>;
147
+ promoted_at?: string | null;
148
+ archived_at?: string | null;
149
+ external_workspace_id?: string | null;
150
+ external_user_id?: string | null;
151
+ external_project_id?: string | null;
152
+ created_at?: string;
153
+ updated_at?: string;
154
+ }
155
+
156
+ export interface DeploymentReleaseData {
157
+ id: DeploymentReleaseId;
158
+ deployment_id?: DeploymentId;
159
+ environment_id?: string | null;
160
+ deployment_version_id: DeploymentVersionId;
161
+ service_id?: DeploymentServiceId | null;
162
+ tenant_id: string;
163
+ external_workspace_id?: string | null;
164
+ external_user_id?: string | null;
165
+ external_project_id?: string | null;
166
+ source_sandbox_id?: string | null;
167
+ build_id?: string | null;
168
+ kind: "static" | "oci" | "rootfs" | string;
169
+ state?: string;
170
+ artifact_uri?: string | null;
171
+ artifact_sha256?: string | null;
172
+ artifact_manifest?: Record<string, unknown>;
173
+ storage_backend?: string | null;
174
+ storage_uri?: string;
175
+ sha256?: string;
176
+ size_bytes?: number;
177
+ start_command?: string | null;
178
+ port?: number | null;
179
+ health_check_path?: string | null;
180
+ build_log_uri?: string | null;
181
+ metadata?: Record<string, unknown>;
182
+ ready_at?: string | null;
183
+ archived_at?: string | null;
184
+ created_at?: string;
185
+ updated_at?: string;
186
+ }
187
+
188
+ export interface DeploymentServiceData {
189
+ id: DeploymentServiceId;
190
+ deployment_id: DeploymentId;
191
+ environment_id?: string | null;
192
+ tenant_id: string;
193
+ type: DeploymentServiceType;
194
+ name?: string | null;
195
+ desired_replicas?: number;
196
+ state: string;
197
+ metadata?: Record<string, unknown>;
198
+ }
199
+
200
+ export interface RuntimeInstanceData {
201
+ id: RuntimeInstanceId;
202
+ deployment_id?: DeploymentId;
203
+ environment_id?: string | null;
204
+ service_id?: DeploymentServiceId | null;
205
+ release_id?: DeploymentReleaseId;
206
+ tenant_id: string;
207
+ external_workspace_id?: string | null;
208
+ external_user_id?: string | null;
209
+ external_project_id?: string | null;
210
+ host_id?: string | null;
211
+ node_id?: string | null;
212
+ vm_id?: string | null;
213
+ desired_state?: string | null;
214
+ state: RuntimeInstanceState;
215
+ ip_address?: string | null;
216
+ port?: number | null;
217
+ health_check_path?: string | null;
218
+ last_health_check_at?: string | null;
219
+ last_heartbeat_at?: string | null;
220
+ started_at?: string | null;
221
+ stopped_at?: string | null;
222
+ error_message?: string | null;
223
+ restart_count?: number;
224
+ cpu_limit_millicores?: number | null;
225
+ memory_limit_mb?: number | null;
226
+ runtime_log_path?: string | null;
227
+ metadata?: Record<string, unknown>;
228
+ created_at?: string;
229
+ updated_at?: string;
230
+ }
231
+
232
+ export interface DeploymentBuildData {
233
+ id: string;
234
+ deployment_id: DeploymentId;
235
+ commit_sha?: string | null;
236
+ commit_message?: string | null;
237
+ triggered_by?: string;
238
+ state: string;
239
+ started_at?: string | null;
240
+ finished_at?: string | null;
241
+ duration_ms?: number | null;
242
+ log_url?: string | null;
243
+ image_digest?: string | null;
244
+ error_message?: string | null;
245
+ external_workspace_id?: string | null;
246
+ external_user_id?: string | null;
247
+ external_project_id?: string | null;
248
+ created_at?: string;
249
+ }
250
+
251
+ // ── Request / response payloads ─────────────────────────────────────────────
252
+
253
+ export interface DeploymentListParams extends ExternalAttribution {
254
+ project_id?: string;
255
+ projectId?: string;
256
+ state?: DeploymentState | string;
257
+ limit?: number;
258
+ cursor?: string;
259
+ }
260
+
261
+ export interface DeploymentCreateParams extends ExternalAttribution {
262
+ name: string;
263
+ /** Current backend create route is repo-backed; project IDs are attribution, not route ownership. */
264
+ project_id?: string;
265
+ projectId?: string;
266
+ /** @deprecated Ignored by the backend create route. Use sandbox.deploy() for sandbox-backed deployments. */
267
+ source_type?: DeploymentSourceType;
268
+ /** @deprecated Ignored by the backend create route. Use sandbox.deploy() for sandbox-backed deployments. */
269
+ sourceType?: DeploymentSourceType;
270
+ repo_url?: string;
271
+ repoUrl?: string;
272
+ branch?: string;
273
+ build_command?: string;
274
+ buildCommand?: string;
275
+ run_command?: string;
276
+ runCommand?: string;
277
+ auto_deploy?: boolean;
278
+ autoDeploy?: boolean;
279
+ database?: DeploymentDatabaseRequest;
280
+ metadata?: Record<string, unknown>;
281
+ idempotencyKey?: string;
282
+ }
283
+
284
+ export interface DeploymentUpdateParams {
285
+ name?: string;
286
+ branch?: string;
287
+ build_command?: string;
288
+ buildCommand?: string;
289
+ run_command?: string;
290
+ runCommand?: string;
291
+ auto_deploy?: boolean;
292
+ autoDeploy?: boolean;
293
+ }
294
+
295
+ export interface PublishParams extends ExternalAttribution {
296
+ sourceSandboxId: string;
297
+ source_sandbox_id?: string;
298
+ name?: string;
299
+ deploymentId?: string;
300
+ deployment_id?: string;
301
+ /** @deprecated Reserved for dynamic runtime publish; ignored by current static publish route. */
302
+ kind?: "auto" | "static" | "dynamic";
303
+ /** @deprecated Reserved for deployment environments; ignored by current static publish route. */
304
+ environment?: "production" | "staging" | string;
305
+ outputPath?: string;
306
+ output_path?: string;
307
+ /** @deprecated Current /deployments/:id/publish snapshots /workspace internally. */
308
+ sourceSnapshotPath?: string;
309
+ /** @deprecated Current /deployments/:id/publish snapshots /workspace internally. */
310
+ source_snapshot_path?: string;
311
+ entrypoint?: string;
312
+ promote?: boolean;
313
+ domain?: string;
314
+ customDomain?: string;
315
+ custom_domain?: string;
316
+ /** @deprecated Reserved for dynamic runtime publish. */
317
+ buildCommand?: string;
318
+ /** @deprecated Reserved for dynamic runtime publish. */
319
+ build_command?: string;
320
+ /** @deprecated Reserved for dynamic runtime publish. */
321
+ runCommand?: string;
322
+ /** @deprecated Reserved for dynamic runtime publish. */
323
+ run_command?: string;
324
+ /** @deprecated Reserved for dynamic runtime publish. */
325
+ port?: number;
326
+ /** @deprecated Reserved for dynamic runtime publish. */
327
+ healthCheckPath?: string;
328
+ /** @deprecated Reserved for dynamic runtime publish. */
329
+ health_check_path?: string;
330
+ /** @deprecated Reserved for managed data-service binding. */
331
+ dataServices?: string[];
332
+ /** @deprecated Reserved for managed data-service binding. */
333
+ data_services?: string[];
334
+ idempotencyKey?: string;
335
+ }
336
+
337
+ export interface PublishResult {
338
+ deployment: DeploymentData;
339
+ version: DeploymentVersionData;
340
+ release?: DeploymentReleaseData;
341
+ services?: DeploymentServiceData[];
342
+ promoted: boolean;
343
+ }
344
+
345
+ export type PublishFromSandboxParams = Omit<
346
+ PublishParams,
347
+ "sourceSandboxId" | "source_sandbox_id"
348
+ > & {
349
+ sourceSandboxId?: string;
350
+ source_sandbox_id?: string;
351
+ };
352
+
353
+ export interface RollbackParams {
354
+ versionId?: string;
355
+ version_id?: string;
356
+ idempotencyKey?: string;
357
+ }
358
+
359
+ export interface VersionListParams extends ExternalAttribution {
360
+ state?: DeploymentVersionState | string;
361
+ limit?: number;
362
+ cursor?: string;
363
+ }
364
+
365
+ export interface RuntimeLogsResult {
366
+ runtime_instance_id?: string;
367
+ deployment_id?: string;
368
+ log_path?: string;
369
+ logs: string;
370
+ }
371
+
372
+ export interface AddDomainParams extends ExternalAttribution {
373
+ redirectPolicy?: "none" | "www_to_apex" | "apex_to_www";
374
+ redirect_policy?: "none" | "www_to_apex" | "apex_to_www";
375
+ idempotencyKey?: string;
376
+ }
377
+
378
+ // ── Helpers ────────────────────────────────────────────────────────────────
379
+
380
+ function attributionBody(p: ExternalAttribution): Record<string, unknown> {
381
+ const out: Record<string, unknown> = {};
382
+ const ws = p.externalWorkspaceId ?? p.external_workspace_id;
383
+ const usr = p.externalUserId ?? p.external_user_id;
384
+ const proj = p.externalProjectId ?? p.external_project_id;
385
+ if (ws !== undefined) out.external_workspace_id = ws;
386
+ if (usr !== undefined) out.external_user_id = usr;
387
+ if (proj !== undefined) out.external_project_id = proj;
388
+ return out;
389
+ }
390
+
391
+ function idempotencyKey(key?: string): string {
392
+ return key ?? randomUUID();
393
+ }
394
+
395
+ function unwrap<T>(payload: { data?: T } | T): T {
396
+ if (payload && typeof payload === "object" && "data" in (payload as object)) {
397
+ return (payload as { data: T }).data;
398
+ }
399
+ return payload as T;
400
+ }
401
+
402
+ function listItems<T>(
403
+ payload: { data?: T[] } | { items?: T[] } | T[] | unknown,
404
+ candidateKeys: string[] = ["items", "deployments", "versions", "domains"],
405
+ ): T[] {
406
+ if (Array.isArray(payload)) return payload;
407
+ if (!payload || typeof payload !== "object") return [];
408
+ const p = payload as Record<string, unknown>;
409
+ if (Array.isArray(p.data)) return p.data as T[];
410
+ for (const key of candidateKeys) {
411
+ if (Array.isArray(p[key])) return p[key] as T[];
412
+ }
413
+ return [];
414
+ }
415
+
416
+ function stripUndefined(
417
+ input: Record<string, unknown>,
418
+ ): Record<string, unknown> {
419
+ return Object.fromEntries(
420
+ Object.entries(input).filter(([, v]) => v !== undefined),
421
+ );
422
+ }
423
+
424
+ // ── Sub-resources ──────────────────────────────────────────────────────────
425
+
426
+ export class DeploymentVersions {
427
+ constructor(
428
+ private readonly http: HttpClient,
429
+ private readonly deploymentId: string,
430
+ ) {}
431
+
432
+ async list(params: VersionListParams = {}): Promise<DeploymentVersionData[]> {
433
+ const query = stripUndefined({
434
+ state: params.state,
435
+ limit: params.limit,
436
+ cursor: params.cursor,
437
+ ...attributionBody(params),
438
+ });
439
+ const data = await this.http.get<unknown>(
440
+ `/deployments/${this.deploymentId}/versions`,
441
+ query as Record<string, string | number | boolean | undefined>,
442
+ );
443
+ return listItems<DeploymentVersionData>(data);
444
+ }
445
+
446
+ async get(versionId: string): Promise<DeploymentVersionData> {
447
+ const data = await this.http.get<unknown>(
448
+ `/deployments/${this.deploymentId}/versions/${versionId}`,
449
+ );
450
+ return unwrap(data) as DeploymentVersionData;
451
+ }
452
+
453
+ async promote(
454
+ versionId: string,
455
+ opts: { environment?: string; idempotencyKey?: string } = {},
456
+ ): Promise<DeploymentData> {
457
+ const body = stripUndefined({ environment: opts.environment });
458
+ const data = await this.http.request<unknown>(
459
+ `/deployments/${this.deploymentId}/versions/${versionId}/promote`,
460
+ {
461
+ method: "POST",
462
+ body,
463
+ headers: { "Idempotency-Key": idempotencyKey(opts.idempotencyKey) },
464
+ },
465
+ );
466
+ return unwrap(data) as DeploymentData;
467
+ }
468
+ }
469
+
470
+ export class DeploymentReleases {
471
+ constructor(
472
+ private readonly http: HttpClient,
473
+ private readonly deploymentId: string,
474
+ ) {}
475
+
476
+ async list(): Promise<DeploymentReleaseData[]> {
477
+ const data = await this.http.get<unknown>(
478
+ `/deployments/${this.deploymentId}/releases`,
479
+ );
480
+ return listItems<DeploymentReleaseData>(data, ["releases"]);
481
+ }
482
+
483
+ async get(releaseId: string): Promise<DeploymentReleaseData> {
484
+ const data = await this.http.get<unknown>(
485
+ `/deployments/${this.deploymentId}/releases/${releaseId}`,
486
+ );
487
+ return unwrap(data) as DeploymentReleaseData;
488
+ }
489
+ }
490
+
491
+ export class DeploymentRuntimeInstances {
492
+ constructor(
493
+ private readonly http: HttpClient,
494
+ private readonly deploymentId: string,
495
+ ) {}
496
+
497
+ async list(): Promise<RuntimeInstanceData[]> {
498
+ const data = await this.http.get<unknown>(
499
+ `/deployments/${this.deploymentId}/runtime-instances`,
500
+ );
501
+ return listItems<RuntimeInstanceData>(data, ["runtime_instances"]);
502
+ }
503
+
504
+ async get(instanceId: string): Promise<RuntimeInstanceData> {
505
+ const data = await this.http.get<unknown>(
506
+ `/deployments/${this.deploymentId}/runtime-instances/${instanceId}`,
507
+ );
508
+ return unwrap(data) as RuntimeInstanceData;
509
+ }
510
+
511
+ async logs(instanceId: string, lines = 100): Promise<RuntimeLogsResult> {
512
+ const data = await this.http.get<unknown>(
513
+ `/deployments/${this.deploymentId}/runtime-instances/${instanceId}/logs`,
514
+ { lines },
515
+ );
516
+ const unwrapped = unwrap(data) as Record<string, unknown>;
517
+ const result: RuntimeLogsResult = { logs: String(unwrapped.logs ?? "") };
518
+ if (typeof unwrapped.runtime_instance_id === "string") {
519
+ result.runtime_instance_id = unwrapped.runtime_instance_id;
520
+ }
521
+ if (typeof unwrapped.deployment_id === "string") {
522
+ result.deployment_id = unwrapped.deployment_id;
523
+ }
524
+ if (typeof unwrapped.log_path === "string") {
525
+ result.log_path = unwrapped.log_path;
526
+ }
527
+ return result;
528
+ }
529
+ }
530
+
531
+ export class DeploymentDomains {
532
+ constructor(
533
+ private readonly http: HttpClient,
534
+ private readonly deploymentId: string,
535
+ ) {}
536
+
537
+ async add(
538
+ domain: string,
539
+ params: AddDomainParams = {},
540
+ ): Promise<Record<string, unknown>> {
541
+ const body = {
542
+ domain,
543
+ redirect_policy: params.redirectPolicy ?? params.redirect_policy,
544
+ ...attributionBody(params),
545
+ };
546
+ const data = await this.http.request<unknown>(
547
+ `/deployments/${this.deploymentId}/domains`,
548
+ {
549
+ method: "POST",
550
+ body: stripUndefined(body),
551
+ headers: { "Idempotency-Key": idempotencyKey(params.idempotencyKey) },
552
+ },
553
+ );
554
+ return unwrap(data) as Record<string, unknown>;
555
+ }
556
+
557
+ async list(
558
+ filters: ExternalAttribution = {},
559
+ ): Promise<Record<string, unknown>[]> {
560
+ const data = await this.http.get<unknown>(
561
+ `/deployments/${this.deploymentId}/domains`,
562
+ attributionBody(filters) as Record<
563
+ string,
564
+ string | number | boolean | undefined
565
+ >,
566
+ );
567
+ return listItems<Record<string, unknown>>(data);
568
+ }
569
+
570
+ async verify(domainId: string): Promise<Record<string, unknown>> {
571
+ const data = await this.http.post<unknown>(
572
+ `/deployments/${this.deploymentId}/domains/${domainId}/verify`,
573
+ );
574
+ return unwrap(data) as Record<string, unknown>;
575
+ }
576
+
577
+ async delete(domainId: string): Promise<void> {
578
+ await this.http.delete<unknown>(
579
+ `/deployments/${this.deploymentId}/domains/${domainId}`,
580
+ );
581
+ }
582
+ }
583
+
584
+ // ── Main resource ──────────────────────────────────────────────────────────
585
+
586
+ export class Deployments {
587
+ constructor(private readonly http: HttpClient) {}
588
+
589
+ async list(params: DeploymentListParams = {}): Promise<DeploymentData[]> {
590
+ const projectId = params.projectId ?? params.project_id;
591
+ const query = stripUndefined({
592
+ project_id: projectId,
593
+ state: params.state,
594
+ limit: params.limit,
595
+ cursor: params.cursor,
596
+ ...attributionBody(params),
597
+ });
598
+ const data = await this.http.get<unknown>(
599
+ "/deployments",
600
+ query as Record<string, string | number | boolean | undefined>,
601
+ );
602
+ return listItems<DeploymentData>(data);
603
+ }
604
+
605
+ async get(deploymentId: string): Promise<DeploymentData> {
606
+ const data = await this.http.get<unknown>(`/deployments/${deploymentId}`);
607
+ return unwrap(data) as DeploymentData;
608
+ }
609
+
610
+ async create(params: DeploymentCreateParams): Promise<DeploymentData> {
611
+ const body = stripUndefined({
612
+ name: params.name,
613
+ repo_url: params.repoUrl ?? params.repo_url,
614
+ branch: params.branch,
615
+ build_command: params.buildCommand ?? params.build_command,
616
+ run_command: params.runCommand ?? params.run_command,
617
+ auto_deploy: params.autoDeploy ?? params.auto_deploy,
618
+ database: params.database,
619
+ metadata: params.metadata,
620
+ ...attributionBody(params),
621
+ });
622
+ const data = await this.http.request<unknown>("/deployments", {
623
+ method: "POST",
624
+ body,
625
+ headers: { "Idempotency-Key": idempotencyKey(params.idempotencyKey) },
626
+ });
627
+ return unwrap(data) as DeploymentData;
628
+ }
629
+
630
+ async update(
631
+ deploymentId: string,
632
+ params: DeploymentUpdateParams,
633
+ ): Promise<DeploymentData> {
634
+ const body = stripUndefined({
635
+ name: params.name,
636
+ branch: params.branch,
637
+ build_command: params.buildCommand ?? params.build_command,
638
+ run_command: params.runCommand ?? params.run_command,
639
+ auto_deploy: params.autoDeploy ?? params.auto_deploy,
640
+ });
641
+ const data = await this.http.patch<unknown>(
642
+ `/deployments/${deploymentId}`,
643
+ body,
644
+ );
645
+ return unwrap(data) as DeploymentData;
646
+ }
647
+
648
+ async delete(deploymentId: string): Promise<void> {
649
+ await this.http.delete<unknown>(`/deployments/${deploymentId}`);
650
+ }
651
+
652
+ async publish(
653
+ deploymentId: string,
654
+ params: PublishParams,
655
+ ): Promise<PublishResult> {
656
+ const body = stripUndefined({
657
+ source_sandbox_id: params.sourceSandboxId ?? params.source_sandbox_id,
658
+ output_path: params.outputPath ?? params.output_path,
659
+ entrypoint: params.entrypoint,
660
+ promote: params.promote,
661
+ });
662
+ const data = await this.http.request<unknown>(
663
+ `/deployments/${deploymentId}/publish`,
664
+ {
665
+ method: "POST",
666
+ body,
667
+ headers: { "Idempotency-Key": idempotencyKey(params.idempotencyKey) },
668
+ },
669
+ );
670
+ return unwrap(data) as PublishResult;
671
+ }
672
+
673
+ /**
674
+ * Backward-compatible bridge: POST /sandboxes/:id/deploy. Works today;
675
+ * returns either release-backed or sandbox-backed depending on backend
676
+ * phase. Prefer `publish()` once Phase 2B/3 lands.
677
+ */
678
+ async publishFromSandbox(
679
+ sandboxId: string,
680
+ params: PublishFromSandboxParams = {},
681
+ ): Promise<Record<string, unknown>> {
682
+ const body = stripUndefined({
683
+ name: params.name,
684
+ deployment_id: params.deploymentId ?? params.deployment_id,
685
+ output_path: params.outputPath ?? params.output_path,
686
+ source_snapshot_path:
687
+ params.sourceSnapshotPath ?? params.source_snapshot_path,
688
+ entrypoint: params.entrypoint,
689
+ domain: params.domain,
690
+ custom_domain: params.customDomain ?? params.custom_domain,
691
+ });
692
+ const data = await this.http.request<unknown>(
693
+ `/sandboxes/${sandboxId}/deploy`,
694
+ {
695
+ method: "POST",
696
+ body,
697
+ headers: { "Idempotency-Key": idempotencyKey(params.idempotencyKey) },
698
+ },
699
+ );
700
+ return unwrap(data) as Record<string, unknown>;
701
+ }
702
+
703
+ async rollback(
704
+ deploymentId: string,
705
+ params: RollbackParams = {},
706
+ ): Promise<DeploymentData> {
707
+ const body = stripUndefined({
708
+ version_id: params.versionId ?? params.version_id,
709
+ });
710
+ const data = await this.http.request<unknown>(
711
+ `/deployments/${deploymentId}/rollback`,
712
+ {
713
+ method: "POST",
714
+ body,
715
+ headers: { "Idempotency-Key": idempotencyKey(params.idempotencyKey) },
716
+ },
717
+ );
718
+ return unwrap(data) as DeploymentData;
719
+ }
720
+
721
+ async listBuilds(deploymentId: string): Promise<DeploymentBuildData[]> {
722
+ const data = await this.http.get<unknown>(
723
+ `/deployments/${deploymentId}/builds`,
724
+ );
725
+ return listItems<DeploymentBuildData>(data);
726
+ }
727
+
728
+ async getBuild(
729
+ deploymentId: string,
730
+ buildId: string,
731
+ ): Promise<DeploymentBuildData> {
732
+ const data = await this.http.get<unknown>(
733
+ `/deployments/${deploymentId}/builds/${buildId}`,
734
+ );
735
+ return unwrap(data) as DeploymentBuildData;
736
+ }
737
+
738
+ async listEnv(deploymentId: string): Promise<Record<string, unknown>[]> {
739
+ const data = await this.http.get<unknown>(
740
+ `/deployments/${deploymentId}/env`,
741
+ );
742
+ return listItems<Record<string, unknown>>(data);
743
+ }
744
+
745
+ async setEnv(
746
+ deploymentId: string,
747
+ vars: Record<string, string>,
748
+ opts: { environment?: string } = {},
749
+ ): Promise<Record<string, unknown>[]> {
750
+ const body = stripUndefined({ env: vars, environment: opts.environment });
751
+ const data = await this.http.post<unknown>(
752
+ `/deployments/${deploymentId}/env`,
753
+ body,
754
+ );
755
+ return listItems<Record<string, unknown>>(data);
756
+ }
757
+
758
+ versions(deploymentId: string): DeploymentVersions {
759
+ return new DeploymentVersions(this.http, deploymentId);
760
+ }
761
+
762
+ releases(deploymentId: string): DeploymentReleases {
763
+ return new DeploymentReleases(this.http, deploymentId);
764
+ }
765
+
766
+ runtimeInstances(deploymentId: string): DeploymentRuntimeInstances {
767
+ return new DeploymentRuntimeInstances(this.http, deploymentId);
768
+ }
769
+
770
+ runtime_instances(deploymentId: string): DeploymentRuntimeInstances {
771
+ return this.runtimeInstances(deploymentId);
772
+ }
773
+
774
+ domains(deploymentId: string): DeploymentDomains {
775
+ return new DeploymentDomains(this.http, deploymentId);
776
+ }
777
+ }