@buddy-works/sandbox-sdk 0.1.4-rc.0 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,6 +45,34 @@ export BUDDY_PROJECT="your-project"
45
45
  export BUDDY_REGION="US" # Optional: US (default), EU, or AP
46
46
  ```
47
47
 
48
+ ## Apps
49
+
50
+ Sandboxes can run multiple apps simultaneously. Each app is a long-running process defined by a command string.
51
+
52
+ ```typescript
53
+ const sandbox = await Sandbox.create({
54
+ identifier: "my-sandbox",
55
+ name: "My Sandbox",
56
+ os: "ubuntu:24.04",
57
+ first_boot_commands: "apt-get update && apt-get install -y curl",
58
+ apps: ["node server.js", "python worker.py"],
59
+ });
60
+
61
+ // List apps
62
+ for (const app of sandbox.data.apps ?? []) {
63
+ console.log(`${app.id}: "${app.command}" -> ${app.app_status}`);
64
+ }
65
+
66
+ // Control individual apps
67
+ const appId = sandbox.data.apps![0].id!;
68
+
69
+ await sandbox.stopApp(appId);
70
+ await sandbox.startApp(appId);
71
+
72
+ const { logs } = await sandbox.getAppLogs(appId);
73
+ console.log(logs);
74
+ ```
75
+
48
76
  ## Regions
49
77
 
50
78
  Configure the API region:
package/dist/index.d.mts CHANGED
@@ -88,6 +88,10 @@ type SandboxIdView = {
88
88
  * The current status of the sandbox
89
89
  */
90
90
  status?: "STARTING" | "STOPPING" | "FAILED" | "RUNNING" | "STOPPED" | "RESTORING";
91
+ /**
92
+ * The current setup status of the sandbox
93
+ */
94
+ setup_status?: "INPROGRESS" | "SUCCESS" | "FAILED";
91
95
  };
92
96
  /**
93
97
  * Integration reference
@@ -116,7 +120,7 @@ type IntegrationIdView = {
116
120
  /**
117
121
  * The type of integration
118
122
  */
119
- type?: "GIT_HUB" | "BITBUCKET" | "GOOGLE" | "DIGITAL_OCEAN" | "SLACK" | "MODULUS" | "HEROKU" | "AMAZON" | "GIT_LAB" | "SHOPIFY" | "GIT_HUB_ENTERPRISE" | "GIT_LAB_ENTERPRISE" | "PUSHOVER" | "PUSHBULLET" | "RACKSPACE" | "CUSTOM" | "CLOUDFLARE" | "NEW_RELIC" | "SENTRY" | "ROLLBAR" | "DATADOG" | "DO_SPACES" | "HONEYBADGER" | "VULTR" | "SENTRY_ENTERPRISE" | "LOGGLY" | "HIP_CHAT" | "FIREBASE" | "TELEGRAM" | "AZURE" | "UPCLOUD" | "GHOST_INSPECTOR" | "NETLIFY" | "AZURE_CLOUD" | "MICROSOFT_TEAMS" | "GOOGLE_SERVICE_ACCOUNT" | "GOOGLE_PLAY_STORE" | "DOCKER_HUB" | "APP_STORE" | "GIT_HUB_APP" | "GIT_HUB_APP_ENTERPRISE" | "GIT_HUB_API" | "ATOP" | "SNYK" | "STACK_HAWK" | "BLACKFIRE" | "BACKBLAZE" | "ONE_LOGIN" | "OKTA" | "CONTENTFUL";
123
+ type?: "GIT_HUB" | "BITBUCKET" | "GOOGLE" | "DIGITAL_OCEAN" | "SLACK" | "MODULUS" | "HEROKU" | "AMAZON" | "GIT_LAB" | "SHOPIFY" | "GIT_HUB_ENTERPRISE" | "GIT_LAB_ENTERPRISE" | "PUSHOVER" | "PUSHBULLET" | "RACKSPACE" | "CUSTOM" | "CLOUDFLARE" | "NEW_RELIC" | "SENTRY" | "ROLLBAR" | "DATADOG" | "DO_SPACES" | "HONEYBADGER" | "VULTR" | "SENTRY_ENTERPRISE" | "LOGGLY" | "HIP_CHAT" | "FIREBASE" | "TELEGRAM" | "AZURE" | "UPCLOUD" | "GHOST_INSPECTOR" | "NETLIFY" | "AZURE_CLOUD" | "MICROSOFT_TEAMS" | "GOOGLE_SERVICE_ACCOUNT" | "GOOGLE_PLAY_STORE" | "DOCKER_HUB" | "APP_STORE" | "GIT_HUB_APP" | "GIT_HUB_APP_ENTERPRISE" | "GIT_HUB_API" | "ATOP" | "SNYK" | "STACK_HAWK" | "BLACKFIRE" | "BACKBLAZE" | "ONE_LOGIN" | "OKTA" | "CONTENTFUL" | "JIRA";
120
124
  /**
121
125
  * The authentication method used by the integration
122
126
  */
@@ -336,9 +340,9 @@ type HttpSettingsView = {
336
340
  /**
337
341
  * Custom HTTP headers to add to requests
338
342
  */
339
- request_headers?: Array<{
343
+ request_headers?: {
340
344
  [key: string]: string;
341
- }>;
345
+ };
342
346
  /**
343
347
  * List of allowed User-Agent strings
344
348
  */
@@ -350,9 +354,9 @@ type HttpSettingsView = {
350
354
  /**
351
355
  * Custom HTTP headers to add to responses
352
356
  */
353
- response_headers?: Array<{
357
+ response_headers?: {
354
358
  [key: string]: string;
355
- }>;
359
+ };
356
360
  /**
357
361
  * Basic authentication username
358
362
  */
@@ -410,6 +414,20 @@ type TunnelView = {
410
414
  */
411
415
  endpoint_url?: string;
412
416
  };
417
+ type SandboxAppView = {
418
+ /**
419
+ * The auto-generated ID of the app
420
+ */
421
+ id?: string;
422
+ /**
423
+ * The run command of the app
424
+ */
425
+ command?: string;
426
+ /**
427
+ * The current status of the app
428
+ */
429
+ app_status?: "NONE" | "RUNNING" | "ENDED" | "FAILED";
430
+ };
413
431
  type SandboxesView = {
414
432
  /**
415
433
  * API endpoint to GET this object
@@ -496,6 +514,14 @@ type SandboxCommandView = {
496
514
  * Command exit code
497
515
  */
498
516
  exit_code?: number;
517
+ /**
518
+ * Command execution start date
519
+ */
520
+ start_date?: Date;
521
+ /**
522
+ * Command execution finish date
523
+ */
524
+ finish_date?: Date;
499
525
  /**
500
526
  * API endpoint URL to retrieve logs for this command
501
527
  */
@@ -511,6 +537,24 @@ type SandboxCommandLog = {
511
537
  */
512
538
  data?: string;
513
539
  };
540
+ type SandboxAppLogsView = {
541
+ /**
542
+ * API endpoint to GET this object
543
+ */
544
+ readonly url?: string;
545
+ /**
546
+ * Web URL to view this object in Buddy.works
547
+ */
548
+ readonly html_url?: string;
549
+ /**
550
+ * Cursor for pagination
551
+ */
552
+ cursor?: string;
553
+ /**
554
+ * Application log entries
555
+ */
556
+ logs?: Array<string>;
557
+ };
514
558
  type ExecuteSandboxCommandRequest = {
515
559
  /**
516
560
  * Command to execute in the sandbox
@@ -521,9 +565,6 @@ type ExecuteSandboxCommandRequest = {
521
565
  */
522
566
  runtime?: "BASH" | "JAVASCRIPT" | "TYPESCRIPT" | "PYTHON";
523
567
  };
524
- /**
525
- * The list of variables you can use the action
526
- */
527
568
  type EnvironmentVariableView = {
528
569
  /**
529
570
  * The ID of the variable
@@ -645,6 +686,10 @@ type SandboxResponse = {
645
686
  * The current status of the sandbox
646
687
  */
647
688
  status?: "STARTING" | "STOPPING" | "FAILED" | "RUNNING" | "STOPPED" | "RESTORING";
689
+ /**
690
+ * The current setup status of the sandbox
691
+ */
692
+ setup_status?: "INPROGRESS" | "SUCCESS" | "FAILED" | "STALE";
648
693
  /**
649
694
  * The operating system of the sandbox ["ubuntu:22.04", "ubuntu:24.04"]
650
695
  */
@@ -654,37 +699,29 @@ type SandboxResponse = {
654
699
  */
655
700
  resources?: "1x2" | "2x4" | "3x6" | "4x8" | "5x10" | "6x12" | "7x14" | "8x16" | "9x18" | "10x20" | "11x22" | "12x24" | "CUSTOM";
656
701
  /**
657
- * The commands to run during setup of the sandbox
658
- */
659
- install_commands?: string;
660
- /**
661
- * The run command of the sandbox
702
+ * The commands to run during first boot of the sandbox
662
703
  */
663
- run_command?: string;
704
+ first_boot_commands?: string;
664
705
  /**
665
706
  * The application directory of the sandbox
666
707
  */
667
708
  app_dir?: string;
668
709
  /**
669
- * The application type of the sandbox (passed command or existent service eg. apache2)
710
+ * The list of apps (run commands) for the sandbox
670
711
  */
671
- app_type?: "CMD" | "SERVICE";
712
+ apps?: Array<SandboxAppView>;
672
713
  /**
673
- * The list of tags associated with the sandbox
714
+ * The timeout in seconds after which the sandbox will be automatically stopped
674
715
  */
675
- tags?: Array<string>;
716
+ timeout?: number;
676
717
  /**
677
- * The current application status of the sandbox
718
+ * The list of tags associated with the sandbox
678
719
  */
679
- app_status?: "NONE" | "RUNNING" | "ENDED" | "FAILED";
720
+ tags?: Array<string>;
680
721
  /**
681
722
  * The boot logs of the sandbox
682
723
  */
683
724
  boot_logs?: Array<string>;
684
- /**
685
- * The current setup status of the sandbox
686
- */
687
- setup_status?: "INPROGRESS" | "SUCCESS" | "FAILED";
688
725
  /**
689
726
  * The tunnel endpoints of the sandbox
690
727
  */
@@ -805,9 +842,9 @@ type HttpSettingsViewWritable = {
805
842
  /**
806
843
  * Custom HTTP headers to add to requests
807
844
  */
808
- request_headers?: Array<{
845
+ request_headers?: {
809
846
  [key: string]: string;
810
- }>;
847
+ };
811
848
  /**
812
849
  * List of allowed User-Agent strings
813
850
  */
@@ -819,9 +856,9 @@ type HttpSettingsViewWritable = {
819
856
  /**
820
857
  * Custom HTTP headers to add to responses
821
858
  */
822
- response_headers?: Array<{
859
+ response_headers?: {
823
860
  [key: string]: string;
824
- }>;
861
+ };
825
862
  /**
826
863
  * Basic authentication username
827
864
  */
@@ -897,21 +934,17 @@ type CreateNewSandboxRequestWritable = {
897
934
  */
898
935
  resources?: "1x2" | "2x4" | "3x6" | "4x8" | "5x10" | "6x12" | "7x14" | "8x16" | "9x18" | "10x20" | "11x22" | "12x24" | "CUSTOM";
899
936
  /**
900
- * The commands to run during setup of the sandbox
901
- */
902
- install_commands?: string;
903
- /**
904
- * The run command of the sandbox
937
+ * The commands to run during first boot of the sandbox
905
938
  */
906
- run_command?: string;
939
+ first_boot_commands?: string;
907
940
  /**
908
941
  * The application directory of the sandbox
909
942
  */
910
943
  app_dir?: string;
911
944
  /**
912
- * The application type of the sandbox (passed command or existent service eg. apache2)
945
+ * The list of apps (run commands) for the sandbox
913
946
  */
914
- app_type?: "CMD" | "SERVICE";
947
+ apps?: Array<string>;
915
948
  /**
916
949
  * The list of tags associated with the sandbox
917
950
  */
@@ -924,6 +957,11 @@ type CreateNewSandboxRequestWritable = {
924
957
  * The environment variables of the sandbox
925
958
  */
926
959
  variables?: Array<AddVariableInObjectRequestWritable>;
960
+ /**
961
+ * The timeout in seconds after which the sandbox will be automatically stopped
962
+ */
963
+ timeout?: number;
964
+ permissions?: PermissionsView;
927
965
  };
928
966
  type CreateFromSnapshotRequestWritable = {
929
967
  /**
@@ -947,21 +985,17 @@ type CreateFromSnapshotRequestWritable = {
947
985
  */
948
986
  resources?: "1x2" | "2x4" | "3x6" | "4x8" | "5x10" | "6x12" | "7x14" | "8x16" | "9x18" | "10x20" | "11x22" | "12x24" | "CUSTOM";
949
987
  /**
950
- * The commands to run during setup of the sandbox
951
- */
952
- install_commands?: string;
953
- /**
954
- * The run command of the sandbox
988
+ * The commands to run during first boot of the sandbox
955
989
  */
956
- run_command?: string;
990
+ first_boot_commands?: string;
957
991
  /**
958
992
  * The application directory of the sandbox
959
993
  */
960
994
  app_dir?: string;
961
995
  /**
962
- * The application type of the sandbox (passed command or existent service eg. apache2)
996
+ * The list of apps (run commands) for the sandbox
963
997
  */
964
- app_type?: "CMD" | "SERVICE";
998
+ apps?: Array<string>;
965
999
  /**
966
1000
  * The list of tags associated with the sandbox
967
1001
  */
@@ -1077,6 +1111,72 @@ type GetSandboxResponses = {
1077
1111
  200: SandboxResponse;
1078
1112
  };
1079
1113
  type GetSandboxResponse = GetSandboxResponses[keyof GetSandboxResponses];
1114
+ type GetSandboxAppLogsByIdData = {
1115
+ body?: never;
1116
+ path: {
1117
+ /**
1118
+ * The human-readable ID of the workspace
1119
+ */
1120
+ workspace_domain: string;
1121
+ /**
1122
+ * The ID of the sandbox
1123
+ */
1124
+ sandbox_id: string;
1125
+ /**
1126
+ * The ID of the app
1127
+ */
1128
+ app_id: string;
1129
+ };
1130
+ query?: {
1131
+ /**
1132
+ * Cursor for pagination
1133
+ */
1134
+ cursor?: string;
1135
+ };
1136
+ url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/apps/{app_id}/logs";
1137
+ };
1138
+ type GetSandboxAppLogsByIdResponses = {
1139
+ 200: SandboxAppLogsView;
1140
+ };
1141
+ type GetSandboxAppLogsByIdResponse = GetSandboxAppLogsByIdResponses[keyof GetSandboxAppLogsByIdResponses];
1142
+ type StartSandboxAppData = {
1143
+ body?: never;
1144
+ path: {
1145
+ /**
1146
+ * The human-readable ID of the workspace
1147
+ */
1148
+ workspace_domain: string;
1149
+ /**
1150
+ * The ID of the sandbox
1151
+ */
1152
+ sandbox_id: string;
1153
+ /**
1154
+ * The ID of the app
1155
+ */
1156
+ app_id: string;
1157
+ };
1158
+ query?: never;
1159
+ url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/apps/{app_id}/start";
1160
+ };
1161
+ type StopSandboxAppData = {
1162
+ body?: never;
1163
+ path: {
1164
+ /**
1165
+ * The human-readable ID of the workspace
1166
+ */
1167
+ workspace_domain: string;
1168
+ /**
1169
+ * The ID of the sandbox
1170
+ */
1171
+ sandbox_id: string;
1172
+ /**
1173
+ * The ID of the app
1174
+ */
1175
+ app_id: string;
1176
+ };
1177
+ query?: never;
1178
+ url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/apps/{app_id}/stop";
1179
+ };
1080
1180
  type ExecuteSandboxCommandData = {
1081
1181
  body?: ExecuteSandboxCommandRequest;
1082
1182
  path: {
@@ -1406,6 +1506,12 @@ declare class BuddyApiClient extends HttpClient {
1406
1506
  stopSandbox<const Data$1 extends StopSandboxData>(data: ClientData<Data$1>): Promise<SandboxResponse>;
1407
1507
  /** Restart a sandbox */
1408
1508
  restartSandbox<const Data$1 extends RestartSandboxData>(data: ClientData<Data$1>): Promise<SandboxResponse>;
1509
+ /** Start a sandbox app */
1510
+ startSandboxApp<const Data$1 extends StartSandboxAppData>(data: ClientData<Data$1>): Promise<SandboxResponse>;
1511
+ /** Stop a sandbox app */
1512
+ stopSandboxApp<const Data$1 extends StopSandboxAppData>(data: ClientData<Data$1>): Promise<SandboxResponse>;
1513
+ /** Get logs for a specific sandbox app */
1514
+ getSandboxAppLogs<const Data$1 extends GetSandboxAppLogsByIdData>(data: ClientData<Data$1>): Promise<SandboxAppLogsView>;
1409
1515
  /** Get sandbox content (list files/directories at a path) */
1410
1516
  getSandboxContent<const Data$1 extends GetSandboxContentData>(data: ClientData<Data$1>): Promise<GetSandboxContentResponse>;
1411
1517
  /** Delete a file or directory from a sandbox */
@@ -1721,6 +1827,29 @@ declare class Sandbox {
1721
1827
  * Waits until the sandbox reaches RUNNING state and setup is complete
1722
1828
  */
1723
1829
  restart(): Promise<void>;
1830
+ /**
1831
+ * Start a specific app within the sandbox
1832
+ *
1833
+ * Updates the internal sandbox data with the latest state after starting.
1834
+ * @param appId - The auto-generated ID of the app (from sandbox.data.apps)
1835
+ */
1836
+ startApp(appId: NonNullable<SandboxAppView["id"]>): Promise<void>;
1837
+ /**
1838
+ * Stop a specific app within the sandbox
1839
+ *
1840
+ * Updates the internal sandbox data with the latest state after stopping.
1841
+ * @param appId - The auto-generated ID of the app (from sandbox.data.apps)
1842
+ */
1843
+ stopApp(appId: NonNullable<SandboxAppView["id"]>): Promise<void>;
1844
+ /**
1845
+ * Get logs for a specific app within the sandbox
1846
+ *
1847
+ * Returns paginated log entries. Pass the returned cursor to fetch the next page.
1848
+ * @param appId - The auto-generated ID of the app (from sandbox.data.apps)
1849
+ * @param cursor - Pagination cursor from a previous response
1850
+ * @returns Log entries and a cursor for the next page
1851
+ */
1852
+ getAppLogs(appId: NonNullable<SandboxAppView["id"]>, cursor?: string): Promise<GetSandboxAppLogsByIdResponse>;
1724
1853
  private constructor();
1725
1854
  }
1726
1855
  //#endregion
@@ -1744,4 +1873,4 @@ declare class BuddySDKError extends Error {
1744
1873
  });
1745
1874
  }
1746
1875
  //#endregion
1747
- export { API_URLS, BuddyApiClient, BuddySDKError, Command, type ConnectionConfig, type CreateSandboxConfig, ERROR_CODES, type ErrorCode, type FileInfo, FileSystem, type GetFileSystemConfig, type GetSandboxConfig, type ListSandboxesConfig, REGIONS, type Region, Sandbox, type SandboxIdView };
1876
+ export { API_URLS, BuddyApiClient, BuddySDKError, Command, type ConnectionConfig, type CreateSandboxConfig, ERROR_CODES, type ErrorCode, type FileInfo, FileSystem, type GetFileSystemConfig, type GetSandboxConfig, type ListSandboxesConfig, REGIONS, type Region, Sandbox, type SandboxAppView, type SandboxIdView };
package/dist/index.mjs CHANGED
@@ -20,6 +20,31 @@ const getSandboxResponseTransformer = async (data) => {
20
20
  data = sandboxResponseSchemaResponseTransformer(data);
21
21
  return data;
22
22
  };
23
+ const startSandboxAppResponseTransformer = async (data) => {
24
+ data = sandboxResponseSchemaResponseTransformer(data);
25
+ return data;
26
+ };
27
+ const stopSandboxAppResponseTransformer = async (data) => {
28
+ data = sandboxResponseSchemaResponseTransformer(data);
29
+ return data;
30
+ };
31
+ const sandboxCommandViewSchemaResponseTransformer = (data) => {
32
+ if (data.start_date) data.start_date = new Date(data.start_date);
33
+ if (data.finish_date) data.finish_date = new Date(data.finish_date);
34
+ return data;
35
+ };
36
+ const executeSandboxCommandResponseTransformer = async (data) => {
37
+ data = sandboxCommandViewSchemaResponseTransformer(data);
38
+ return data;
39
+ };
40
+ const getSandboxCommandResponseTransformer = async (data) => {
41
+ data = sandboxCommandViewSchemaResponseTransformer(data);
42
+ return data;
43
+ };
44
+ const terminateSandboxCommandResponseTransformer = async (data) => {
45
+ data = sandboxCommandViewSchemaResponseTransformer(data);
46
+ return data;
47
+ };
23
48
  const sandboxContentItemSchemaResponseTransformer = (data) => {
24
49
  if (data.size) data.size = BigInt(data.size.toString());
25
50
  return data;
@@ -473,7 +498,8 @@ const zIntegrationView = z.object({
473
498
  "BACKBLAZE",
474
499
  "ONE_LOGIN",
475
500
  "OKTA",
476
- "CONTENTFUL"
501
+ "CONTENTFUL",
502
+ "JIRA"
477
503
  ])),
478
504
  auth_type: z.optional(z.enum([
479
505
  "OAUTH",
@@ -625,7 +651,8 @@ const zAddIntegrationRequest = z.object({
625
651
  "BACKBLAZE",
626
652
  "ONE_LOGIN",
627
653
  "OKTA",
628
- "CONTENTFUL"
654
+ "CONTENTFUL",
655
+ "JIRA"
629
656
  ]),
630
657
  scope: z.enum([
631
658
  "WORKSPACE",
@@ -650,6 +677,11 @@ const zSandboxIdView = z.object({
650
677
  "RUNNING",
651
678
  "STOPPED",
652
679
  "RESTORING"
680
+ ])),
681
+ setup_status: z.optional(z.enum([
682
+ "INPROGRESS",
683
+ "SUCCESS",
684
+ "FAILED"
653
685
  ]))
654
686
  });
655
687
  /**
@@ -711,7 +743,8 @@ const zIntegrationIdView = z.object({
711
743
  "BACKBLAZE",
712
744
  "ONE_LOGIN",
713
745
  "OKTA",
714
- "CONTENTFUL"
746
+ "CONTENTFUL",
747
+ "JIRA"
715
748
  ])),
716
749
  auth_type: z.optional(z.enum([
717
750
  "OAUTH",
@@ -854,10 +887,10 @@ const zHttpSettingsView = z.object({
854
887
  compression: z.optional(z.boolean()),
855
888
  http2: z.optional(z.boolean()),
856
889
  log_requests: z.optional(z.boolean()),
857
- request_headers: z.optional(z.array(z.record(z.string(), z.string()))),
890
+ request_headers: z.optional(z.record(z.string(), z.string())),
858
891
  whitelist_user_agents: z.optional(z.array(z.string())),
859
892
  rewrite_host_header: z.optional(z.string()),
860
- response_headers: z.optional(z.array(z.record(z.string(), z.string()))),
893
+ response_headers: z.optional(z.record(z.string(), z.string())),
861
894
  login: z.optional(z.string()),
862
895
  circuit_breaker: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
863
896
  serve_path: z.optional(z.string()),
@@ -889,6 +922,16 @@ const zTunnelView = z.object({
889
922
  tls: z.optional(zTlsSettingsView),
890
923
  endpoint_url: z.optional(z.string())
891
924
  });
925
+ const zSandboxAppView = z.object({
926
+ id: z.optional(z.string()),
927
+ command: z.optional(z.string()),
928
+ app_status: z.optional(z.enum([
929
+ "NONE",
930
+ "RUNNING",
931
+ "ENDED",
932
+ "FAILED"
933
+ ]))
934
+ });
892
935
  const zUpdateSandboxRequest = z.object({
893
936
  name: z.optional(z.string()),
894
937
  identifier: z.optional(z.string()),
@@ -907,10 +950,10 @@ const zUpdateSandboxRequest = z.object({
907
950
  "12x24",
908
951
  "CUSTOM"
909
952
  ])),
910
- install_commands: z.optional(z.string()),
911
- run_command: z.optional(z.string()),
953
+ first_boot_commands: z.optional(z.string()),
912
954
  app_dir: z.optional(z.string()),
913
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
955
+ apps: z.optional(z.array(zSandboxAppView)),
956
+ timeout: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
914
957
  tags: z.optional(z.array(z.string())),
915
958
  endpoints: z.optional(z.array(zTunnelView)),
916
959
  variables: z.optional(z.array(zAddVariableInObjectRequest)),
@@ -957,6 +1000,8 @@ const zSandboxCommandView = z.object({
957
1000
  "FAILED"
958
1001
  ])),
959
1002
  exit_code: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1003
+ start_date: z.optional(z.iso.datetime()),
1004
+ finish_date: z.optional(z.iso.datetime()),
960
1005
  logs_url: z.optional(z.string())
961
1006
  });
962
1007
  const zSandboxCommandsView = z.object({
@@ -1042,17 +1087,15 @@ const zCreateNewSandboxRequest = z.object({
1042
1087
  "12x24",
1043
1088
  "CUSTOM"
1044
1089
  ])),
1045
- install_commands: z.optional(z.string()),
1046
- run_command: z.optional(z.string()),
1090
+ first_boot_commands: z.optional(z.string()),
1047
1091
  app_dir: z.optional(z.string()),
1048
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1092
+ apps: z.optional(z.array(z.string())),
1049
1093
  tags: z.optional(z.array(z.string())),
1050
1094
  endpoints: z.optional(z.array(zTunnelView)),
1051
- variables: z.optional(z.array(zAddVariableInObjectRequest))
1095
+ variables: z.optional(z.array(zAddVariableInObjectRequest)),
1096
+ timeout: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1097
+ permissions: z.optional(zPermissionsView)
1052
1098
  });
1053
- /**
1054
- * The list of variables you can use the action
1055
- */
1056
1099
  const zEnvironmentVariableView = z.object({
1057
1100
  id: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1058
1101
  key: z.optional(z.string()),
@@ -1103,10 +1146,9 @@ const zCreateFromSnapshotRequest = z.object({
1103
1146
  "12x24",
1104
1147
  "CUSTOM"
1105
1148
  ])),
1106
- install_commands: z.optional(z.string()),
1107
- run_command: z.optional(z.string()),
1149
+ first_boot_commands: z.optional(z.string()),
1108
1150
  app_dir: z.optional(z.string()),
1109
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1151
+ apps: z.optional(z.array(z.string())),
1110
1152
  tags: z.optional(z.array(z.string())),
1111
1153
  endpoints: z.optional(z.array(zTunnelView)),
1112
1154
  variables: z.optional(z.array(zEnvironmentVariableView))
@@ -1130,6 +1172,12 @@ const zSandboxResponse = z.object({
1130
1172
  "STOPPED",
1131
1173
  "RESTORING"
1132
1174
  ])),
1175
+ setup_status: z.optional(z.enum([
1176
+ "INPROGRESS",
1177
+ "SUCCESS",
1178
+ "FAILED",
1179
+ "STALE"
1180
+ ])),
1133
1181
  os: z.optional(z.string()),
1134
1182
  resources: z.optional(z.enum([
1135
1183
  "1x2",
@@ -1146,23 +1194,12 @@ const zSandboxResponse = z.object({
1146
1194
  "12x24",
1147
1195
  "CUSTOM"
1148
1196
  ])),
1149
- install_commands: z.optional(z.string()),
1150
- run_command: z.optional(z.string()),
1197
+ first_boot_commands: z.optional(z.string()),
1151
1198
  app_dir: z.optional(z.string()),
1152
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1199
+ apps: z.optional(z.array(zSandboxAppView)),
1200
+ timeout: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1153
1201
  tags: z.optional(z.array(z.string())),
1154
- app_status: z.optional(z.enum([
1155
- "NONE",
1156
- "RUNNING",
1157
- "ENDED",
1158
- "FAILED"
1159
- ])),
1160
1202
  boot_logs: z.optional(z.array(z.string())),
1161
- setup_status: z.optional(z.enum([
1162
- "INPROGRESS",
1163
- "SUCCESS",
1164
- "FAILED"
1165
- ])),
1166
1203
  endpoints: z.optional(z.array(zTunnelView)),
1167
1204
  project: z.optional(zProjectView),
1168
1205
  permissions: z.optional(zPermissionsView),
@@ -1370,7 +1407,8 @@ const zIntegrationViewWritable = z.object({
1370
1407
  "BACKBLAZE",
1371
1408
  "ONE_LOGIN",
1372
1409
  "OKTA",
1373
- "CONTENTFUL"
1410
+ "CONTENTFUL",
1411
+ "JIRA"
1374
1412
  ])),
1375
1413
  auth_type: z.optional(z.enum([
1376
1414
  "OAUTH",
@@ -1424,6 +1462,11 @@ const zSandboxIdViewWritable = z.object({
1424
1462
  "RUNNING",
1425
1463
  "STOPPED",
1426
1464
  "RESTORING"
1465
+ ])),
1466
+ setup_status: z.optional(z.enum([
1467
+ "INPROGRESS",
1468
+ "SUCCESS",
1469
+ "FAILED"
1427
1470
  ]))
1428
1471
  });
1429
1472
  /**
@@ -1483,7 +1526,8 @@ const zIntegrationIdViewWritable = z.object({
1483
1526
  "BACKBLAZE",
1484
1527
  "ONE_LOGIN",
1485
1528
  "OKTA",
1486
- "CONTENTFUL"
1529
+ "CONTENTFUL",
1530
+ "JIRA"
1487
1531
  ])),
1488
1532
  auth_type: z.optional(z.enum([
1489
1533
  "OAUTH",
@@ -1597,10 +1641,10 @@ const zHttpSettingsViewWritable = z.object({
1597
1641
  compression: z.optional(z.boolean()),
1598
1642
  http2: z.optional(z.boolean()),
1599
1643
  log_requests: z.optional(z.boolean()),
1600
- request_headers: z.optional(z.array(z.record(z.string(), z.string()))),
1644
+ request_headers: z.optional(z.record(z.string(), z.string())),
1601
1645
  whitelist_user_agents: z.optional(z.array(z.string())),
1602
1646
  rewrite_host_header: z.optional(z.string()),
1603
- response_headers: z.optional(z.array(z.record(z.string(), z.string()))),
1647
+ response_headers: z.optional(z.record(z.string(), z.string())),
1604
1648
  login: z.optional(z.string()),
1605
1649
  password: z.optional(z.string()),
1606
1650
  tls_ca: z.optional(z.string()),
@@ -1650,10 +1694,10 @@ const zUpdateSandboxRequestWritable = z.object({
1650
1694
  "12x24",
1651
1695
  "CUSTOM"
1652
1696
  ])),
1653
- install_commands: z.optional(z.string()),
1654
- run_command: z.optional(z.string()),
1697
+ first_boot_commands: z.optional(z.string()),
1655
1698
  app_dir: z.optional(z.string()),
1656
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1699
+ apps: z.optional(z.array(zSandboxAppView)),
1700
+ timeout: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1657
1701
  tags: z.optional(z.array(z.string())),
1658
1702
  endpoints: z.optional(z.array(zTunnelViewWritable)),
1659
1703
  variables: z.optional(z.array(zAddVariableInObjectRequestWritable)),
@@ -1688,6 +1732,8 @@ const zSandboxCommandViewWritable = z.object({
1688
1732
  "FAILED"
1689
1733
  ])),
1690
1734
  exit_code: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1735
+ start_date: z.optional(z.iso.datetime()),
1736
+ finish_date: z.optional(z.iso.datetime()),
1691
1737
  logs_url: z.optional(z.string())
1692
1738
  });
1693
1739
  const zSandboxCommandsViewWritable = z.object({ commands: z.optional(z.array(zSandboxCommandViewWritable)) });
@@ -1741,13 +1787,14 @@ const zCreateNewSandboxRequestWritable = z.object({
1741
1787
  "12x24",
1742
1788
  "CUSTOM"
1743
1789
  ])),
1744
- install_commands: z.optional(z.string()),
1745
- run_command: z.optional(z.string()),
1790
+ first_boot_commands: z.optional(z.string()),
1746
1791
  app_dir: z.optional(z.string()),
1747
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1792
+ apps: z.optional(z.array(z.string())),
1748
1793
  tags: z.optional(z.array(z.string())),
1749
1794
  endpoints: z.optional(z.array(zTunnelViewWritable)),
1750
- variables: z.optional(z.array(zAddVariableInObjectRequestWritable))
1795
+ variables: z.optional(z.array(zAddVariableInObjectRequestWritable)),
1796
+ timeout: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1797
+ permissions: z.optional(zPermissionsView)
1751
1798
  });
1752
1799
  const zCreateFromSnapshotRequestWritable = z.object({
1753
1800
  snapshot_id: z.string(),
@@ -1769,10 +1816,9 @@ const zCreateFromSnapshotRequestWritable = z.object({
1769
1816
  "12x24",
1770
1817
  "CUSTOM"
1771
1818
  ])),
1772
- install_commands: z.optional(z.string()),
1773
- run_command: z.optional(z.string()),
1819
+ first_boot_commands: z.optional(z.string()),
1774
1820
  app_dir: z.optional(z.string()),
1775
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1821
+ apps: z.optional(z.array(z.string())),
1776
1822
  tags: z.optional(z.array(z.string())),
1777
1823
  endpoints: z.optional(z.array(zTunnelViewWritable)),
1778
1824
  variables: z.optional(z.array(zEnvironmentVariableView))
@@ -1789,6 +1835,12 @@ const zSandboxResponseWritable = z.object({
1789
1835
  "STOPPED",
1790
1836
  "RESTORING"
1791
1837
  ])),
1838
+ setup_status: z.optional(z.enum([
1839
+ "INPROGRESS",
1840
+ "SUCCESS",
1841
+ "FAILED",
1842
+ "STALE"
1843
+ ])),
1792
1844
  os: z.optional(z.string()),
1793
1845
  resources: z.optional(z.enum([
1794
1846
  "1x2",
@@ -1805,23 +1857,12 @@ const zSandboxResponseWritable = z.object({
1805
1857
  "12x24",
1806
1858
  "CUSTOM"
1807
1859
  ])),
1808
- install_commands: z.optional(z.string()),
1809
- run_command: z.optional(z.string()),
1860
+ first_boot_commands: z.optional(z.string()),
1810
1861
  app_dir: z.optional(z.string()),
1811
- app_type: z.optional(z.enum(["CMD", "SERVICE"])),
1862
+ apps: z.optional(z.array(zSandboxAppView)),
1863
+ timeout: z.optional(z.int().min(-2147483648, { error: "Invalid value: Expected int32 to be >= -2147483648" }).max(2147483647, { error: "Invalid value: Expected int32 to be <= 2147483647" })),
1812
1864
  tags: z.optional(z.array(z.string())),
1813
- app_status: z.optional(z.enum([
1814
- "NONE",
1815
- "RUNNING",
1816
- "ENDED",
1817
- "FAILED"
1818
- ])),
1819
1865
  boot_logs: z.optional(z.array(z.string())),
1820
- setup_status: z.optional(z.enum([
1821
- "INPROGRESS",
1822
- "SUCCESS",
1823
- "FAILED"
1824
- ])),
1825
1866
  endpoints: z.optional(z.array(zTunnelViewWritable)),
1826
1867
  project: z.optional(zProjectViewWritable),
1827
1868
  permissions: z.optional(zPermissionsView),
@@ -2002,14 +2043,36 @@ const zUpdateSandboxData = z.object({
2002
2043
  }),
2003
2044
  query: z.optional(z.never())
2004
2045
  });
2005
- const zGetSandboxAppLogsData = z.object({
2046
+ const zGetSandboxAppLogsByIdData = z.object({
2006
2047
  body: z.optional(z.never()),
2007
2048
  path: z.object({
2008
2049
  workspace_domain: z.string(),
2009
- sandbox_id: z.string()
2050
+ sandbox_id: z.string(),
2051
+ app_id: z.string()
2010
2052
  }),
2011
2053
  query: z.optional(z.object({ cursor: z.optional(z.string()) }))
2012
2054
  });
2055
+ const zGetSandboxAppLogsByIdResponse = zSandboxAppLogsView;
2056
+ const zStartSandboxAppData = z.object({
2057
+ body: z.optional(z.never()),
2058
+ path: z.object({
2059
+ workspace_domain: z.string(),
2060
+ sandbox_id: z.string(),
2061
+ app_id: z.string()
2062
+ }),
2063
+ query: z.optional(z.never())
2064
+ });
2065
+ const zStartSandboxAppResponse = zSandboxResponse;
2066
+ const zStopSandboxAppData = z.object({
2067
+ body: z.optional(z.never()),
2068
+ path: z.object({
2069
+ workspace_domain: z.string(),
2070
+ sandbox_id: z.string(),
2071
+ app_id: z.string()
2072
+ }),
2073
+ query: z.optional(z.never())
2074
+ });
2075
+ const zStopSandboxAppResponse = zSandboxResponse;
2013
2076
  const zGetSandboxCommandsData = z.object({
2014
2077
  body: z.optional(z.never()),
2015
2078
  path: z.object({
@@ -2238,7 +2301,7 @@ const zUpdateSsoData = z.object({
2238
2301
  //#endregion
2239
2302
  //#region package.json
2240
2303
  var name = "@buddy-works/sandbox-sdk";
2241
- var version = "0.1.4-rc.0";
2304
+ var version = "0.1.5";
2242
2305
 
2243
2306
  //#endregion
2244
2307
  //#region src/utils/environment.ts
@@ -2662,7 +2725,7 @@ var BuddyApiClient = class extends HttpClient {
2662
2725
  data,
2663
2726
  url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/commands",
2664
2727
  dataSchema: zExecuteSandboxCommandData,
2665
- responseSchema: zExecuteSandboxCommandResponse
2728
+ responseSchema: zExecuteSandboxCommandResponse.transform(executeSandboxCommandResponseTransformer)
2666
2729
  });
2667
2730
  }
2668
2731
  /** Get a specific command execution details */
@@ -2672,7 +2735,7 @@ var BuddyApiClient = class extends HttpClient {
2672
2735
  data,
2673
2736
  url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/commands/{id}",
2674
2737
  dataSchema: zGetSandboxCommandData,
2675
- responseSchema: zGetSandboxCommandResponse
2738
+ responseSchema: zGetSandboxCommandResponse.transform(getSandboxCommandResponseTransformer)
2676
2739
  });
2677
2740
  }
2678
2741
  /** Terminate a running command in a sandbox */
@@ -2682,7 +2745,7 @@ var BuddyApiClient = class extends HttpClient {
2682
2745
  data,
2683
2746
  url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/commands/{command_id}/terminate",
2684
2747
  dataSchema: zTerminateSandboxCommandData,
2685
- responseSchema: zTerminateSandboxCommandResponse
2748
+ responseSchema: zTerminateSandboxCommandResponse.transform(terminateSandboxCommandResponseTransformer)
2686
2749
  });
2687
2750
  }
2688
2751
  /** Delete a sandbox by its ID */
@@ -2741,6 +2804,36 @@ var BuddyApiClient = class extends HttpClient {
2741
2804
  responseSchema: zRestartSandboxResponse.transform(restartSandboxResponseTransformer)
2742
2805
  });
2743
2806
  }
2807
+ /** Start a sandbox app */
2808
+ async startSandboxApp(data) {
2809
+ return this.#requestWithValidation({
2810
+ method: "POST",
2811
+ data,
2812
+ url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/apps/{app_id}/start",
2813
+ dataSchema: zStartSandboxAppData,
2814
+ responseSchema: zStartSandboxAppResponse.transform(startSandboxAppResponseTransformer)
2815
+ });
2816
+ }
2817
+ /** Stop a sandbox app */
2818
+ async stopSandboxApp(data) {
2819
+ return this.#requestWithValidation({
2820
+ method: "POST",
2821
+ data,
2822
+ url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/apps/{app_id}/stop",
2823
+ dataSchema: zStopSandboxAppData,
2824
+ responseSchema: zStopSandboxAppResponse.transform(stopSandboxAppResponseTransformer)
2825
+ });
2826
+ }
2827
+ /** Get logs for a specific sandbox app */
2828
+ async getSandboxAppLogs(data) {
2829
+ return this.#requestWithValidation({
2830
+ method: "GET",
2831
+ data,
2832
+ url: "/workspaces/{workspace_domain}/sandboxes/{sandbox_id}/apps/{app_id}/logs",
2833
+ dataSchema: zGetSandboxAppLogsByIdData,
2834
+ responseSchema: zGetSandboxAppLogsByIdResponse
2835
+ });
2836
+ }
2744
2837
  /** Get sandbox content (list files/directories at a path) */
2745
2838
  async getSandboxContent(data) {
2746
2839
  return this.#requestWithValidation({
@@ -3457,6 +3550,7 @@ var Sandbox = class Sandbox {
3457
3550
  await this.refresh();
3458
3551
  if (this.data.setup_status === "SUCCESS") return;
3459
3552
  if (this.data.setup_status === "FAILED") throw new Error(`Sandbox ${sandboxId} setup failed. Status: ${this.data.setup_status}`);
3553
+ if (this.data.setup_status === "STALE") throw new Error(`Sandbox ${sandboxId} setup is stale. The first_boot_commands were changed but not applied. Recreate the sandbox to apply them.`);
3460
3554
  await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
3461
3555
  }
3462
3556
  });
@@ -3554,6 +3648,56 @@ var Sandbox = class Sandbox {
3554
3648
  logger_default.debug(`Sandbox ${sandboxId} has been restarted and is ready. Status: ${this.data.status}, Setup status: ${this.data.setup_status}`);
3555
3649
  });
3556
3650
  }
3651
+ /**
3652
+ * Start a specific app within the sandbox
3653
+ *
3654
+ * Updates the internal sandbox data with the latest state after starting.
3655
+ * @param appId - The auto-generated ID of the app (from sandbox.data.apps)
3656
+ */
3657
+ async startApp(appId) {
3658
+ const sandboxId = this.initializedId;
3659
+ return withErrorHandler("Failed to start app", async () => {
3660
+ this.#sandboxData = await this.#client.startSandboxApp({ path: {
3661
+ sandbox_id: sandboxId,
3662
+ app_id: appId
3663
+ } });
3664
+ });
3665
+ }
3666
+ /**
3667
+ * Stop a specific app within the sandbox
3668
+ *
3669
+ * Updates the internal sandbox data with the latest state after stopping.
3670
+ * @param appId - The auto-generated ID of the app (from sandbox.data.apps)
3671
+ */
3672
+ async stopApp(appId) {
3673
+ const sandboxId = this.initializedId;
3674
+ return withErrorHandler("Failed to stop app", async () => {
3675
+ this.#sandboxData = await this.#client.stopSandboxApp({ path: {
3676
+ sandbox_id: sandboxId,
3677
+ app_id: appId
3678
+ } });
3679
+ });
3680
+ }
3681
+ /**
3682
+ * Get logs for a specific app within the sandbox
3683
+ *
3684
+ * Returns paginated log entries. Pass the returned cursor to fetch the next page.
3685
+ * @param appId - The auto-generated ID of the app (from sandbox.data.apps)
3686
+ * @param cursor - Pagination cursor from a previous response
3687
+ * @returns Log entries and a cursor for the next page
3688
+ */
3689
+ async getAppLogs(appId, cursor) {
3690
+ const sandboxId = this.initializedId;
3691
+ return withErrorHandler("Failed to get app logs", async () => {
3692
+ return this.#client.getSandboxAppLogs({
3693
+ path: {
3694
+ sandbox_id: sandboxId,
3695
+ app_id: appId
3696
+ },
3697
+ query: { cursor }
3698
+ });
3699
+ });
3700
+ }
3557
3701
  constructor(sandboxData, client, constructorKey) {
3558
3702
  if (constructorKey !== PRIVATE_CONSTRUCTOR_KEY) throw new Error(`Cannot construct Sandbox directly. ${INITIALIZE_INSTRUCTIONS}`);
3559
3703
  this.#sandboxData = sandboxData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buddy-works/sandbox-sdk",
3
- "version": "0.1.4-rc.0",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "description": "TypeScript SDK for managing sandboxes through the Buddy API",
6
6
  "main": "./dist/index.mjs",