@computesdk/aws-ecs 1.1.6 → 1.1.8

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
@@ -27,10 +27,32 @@ AWS_SECURITY_GROUPS=sg-xxx
27
27
 
28
28
  ## Usage
29
29
 
30
+ ### Gateway Mode (Recommended)
31
+
32
+ Use the gateway for zero-config auto-detection:
33
+
34
+ ```typescript
35
+ import { compute } from 'computesdk';
36
+
37
+ // Auto-detects AWS ECS from AWS credentials and environment variables
38
+ const sandbox = await compute.sandbox.create();
39
+ console.log(`Created sandbox: ${sandbox.id}`);
40
+
41
+ // List all running sandboxes
42
+ const sandboxes = await compute.sandbox.list();
43
+
44
+ // Destroy the sandbox
45
+ await sandbox.destroy();
46
+ ```
47
+
48
+ ### Direct Mode
49
+
50
+ For direct SDK usage without the gateway:
51
+
30
52
  ```typescript
31
53
  import { fargate } from '@computesdk/aws';
32
54
 
33
- const provider = fargate({
55
+ const compute = fargate({
34
56
  cluster: 'my-ecs-cluster',
35
57
  taskDefinition: 'my-task-definition',
36
58
  subnets: ['subnet-12345', 'subnet-67890'],
@@ -39,17 +61,14 @@ const provider = fargate({
39
61
  });
40
62
 
41
63
  // Create a sandbox (ECS task)
42
- const sandbox = await provider.sandbox.create({ runtime: 'node' });
43
- console.log(`Created sandbox: ${sandbox.sandboxId}`);
44
-
45
- // Get sandbox by ID
46
- const retrieved = await provider.sandbox.getById(sandbox.sandboxId);
64
+ const sandbox = await compute.sandbox.create({ runtime: 'node' });
65
+ console.log(`Created sandbox: ${sandbox.id}`);
47
66
 
48
67
  // List all running sandboxes
49
- const sandboxes = await provider.sandbox.list();
68
+ const sandboxes = await compute.sandbox.list();
50
69
 
51
70
  // Destroy the sandbox
52
- await provider.sandbox.destroy(sandbox.sandboxId);
71
+ await sandbox.destroy();
53
72
  ```
54
73
 
55
74
  ## Currently Implemented
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/aws-ecs",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "AWS ECS provider for ComputeSDK - scalable containerized sandboxes using Fargate",
5
5
  "author": "ComputeSDK Team",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "@aws-sdk/client-ecs": "^3.943.0",
22
- "computesdk": "1.10.0"
22
+ "computesdk": "1.10.2"
23
23
  },
24
24
  "keywords": [
25
25
  "computesdk",
package/dist/index.d.mts DELETED
@@ -1,52 +0,0 @@
1
- import * as computesdk from 'computesdk';
2
-
3
- /**
4
- * AWS ECS Fargate Provider - Factory-based Implementation
5
- */
6
- /**
7
- * Fargate sandbox interface
8
- */
9
- interface FargateSandbox {
10
- taskArn: string;
11
- clusterArn: string;
12
- taskId: string;
13
- }
14
- interface FargateConfig {
15
- /** AWS Access Key ID - falls back to AWS_ACCESS_KEY_ID env var or default credential chain */
16
- accessKeyId?: string;
17
- /** AWS Secret Access Key - falls back to AWS_SECRET_ACCESS_KEY env var or default credential chain */
18
- secretAccessKey?: string;
19
- /** AWS Region - falls back to AWS_REGION env var */
20
- region?: string;
21
- /** ECS Cluster name or ARN */
22
- cluster: string;
23
- /** Task definition family name or ARN */
24
- taskDefinition: string;
25
- /** VPC Subnet IDs for task networking */
26
- subnets: string[];
27
- /** Security Group IDs for task networking */
28
- securityGroups: string[];
29
- /** Whether to assign a public IP (default: true) */
30
- assignPublicIp?: boolean;
31
- /** Container name in the task definition (default: 'sandbox') */
32
- containerName?: string;
33
- }
34
- declare const getAndValidateCredentials: (config: FargateConfig) => {
35
- region: string;
36
- cluster: string;
37
- taskDefinition: string;
38
- subnets: string[];
39
- securityGroups: string[];
40
- credentials: {
41
- accessKeyId: string;
42
- secretAccessKey: string;
43
- } | undefined;
44
- assignPublicIp: boolean;
45
- containerName: string;
46
- };
47
- /**
48
- * Create an AWS ECS Fargate provider instance using the factory pattern
49
- */
50
- declare const fargate: (config: FargateConfig & computesdk.BaseProviderConfig) => computesdk.Provider<FargateSandbox, any, any>;
51
-
52
- export { type FargateConfig, fargate, getAndValidateCredentials };
package/dist/index.d.ts DELETED
@@ -1,52 +0,0 @@
1
- import * as computesdk from 'computesdk';
2
-
3
- /**
4
- * AWS ECS Fargate Provider - Factory-based Implementation
5
- */
6
- /**
7
- * Fargate sandbox interface
8
- */
9
- interface FargateSandbox {
10
- taskArn: string;
11
- clusterArn: string;
12
- taskId: string;
13
- }
14
- interface FargateConfig {
15
- /** AWS Access Key ID - falls back to AWS_ACCESS_KEY_ID env var or default credential chain */
16
- accessKeyId?: string;
17
- /** AWS Secret Access Key - falls back to AWS_SECRET_ACCESS_KEY env var or default credential chain */
18
- secretAccessKey?: string;
19
- /** AWS Region - falls back to AWS_REGION env var */
20
- region?: string;
21
- /** ECS Cluster name or ARN */
22
- cluster: string;
23
- /** Task definition family name or ARN */
24
- taskDefinition: string;
25
- /** VPC Subnet IDs for task networking */
26
- subnets: string[];
27
- /** Security Group IDs for task networking */
28
- securityGroups: string[];
29
- /** Whether to assign a public IP (default: true) */
30
- assignPublicIp?: boolean;
31
- /** Container name in the task definition (default: 'sandbox') */
32
- containerName?: string;
33
- }
34
- declare const getAndValidateCredentials: (config: FargateConfig) => {
35
- region: string;
36
- cluster: string;
37
- taskDefinition: string;
38
- subnets: string[];
39
- securityGroups: string[];
40
- credentials: {
41
- accessKeyId: string;
42
- secretAccessKey: string;
43
- } | undefined;
44
- assignPublicIp: boolean;
45
- containerName: string;
46
- };
47
- /**
48
- * Create an AWS ECS Fargate provider instance using the factory pattern
49
- */
50
- declare const fargate: (config: FargateConfig & computesdk.BaseProviderConfig) => computesdk.Provider<FargateSandbox, any, any>;
51
-
52
- export { type FargateConfig, fargate, getAndValidateCredentials };
package/dist/index.js DELETED
@@ -1,250 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- fargate: () => fargate,
24
- getAndValidateCredentials: () => getAndValidateCredentials
25
- });
26
- module.exports = __toCommonJS(index_exports);
27
- var import_computesdk = require("computesdk");
28
- var import_client_ecs = require("@aws-sdk/client-ecs");
29
- var getAndValidateCredentials = (config) => {
30
- const region = config.region || process.env?.AWS_REGION || "us-east-1";
31
- const cluster = config.cluster;
32
- const taskDefinition = config.taskDefinition;
33
- const subnets = config.subnets;
34
- const securityGroups = config.securityGroups;
35
- if (!cluster) {
36
- throw new Error("Missing ECS cluster. Provide cluster in config.");
37
- }
38
- if (!taskDefinition) {
39
- throw new Error("Missing ECS task definition. Provide taskDefinition in config.");
40
- }
41
- if (!subnets || subnets.length === 0) {
42
- throw new Error("Missing subnets. Provide at least one subnet in config.");
43
- }
44
- if (!securityGroups || securityGroups.length === 0) {
45
- throw new Error("Missing security groups. Provide at least one security group in config.");
46
- }
47
- const credentials = config.accessKeyId && config.secretAccessKey ? {
48
- accessKeyId: config.accessKeyId,
49
- secretAccessKey: config.secretAccessKey
50
- } : void 0;
51
- return {
52
- region,
53
- cluster,
54
- taskDefinition,
55
- subnets,
56
- securityGroups,
57
- credentials,
58
- assignPublicIp: config.assignPublicIp ?? true,
59
- containerName: config.containerName || "sandbox"
60
- };
61
- };
62
- var createECSClient = (config) => {
63
- const { region, credentials } = getAndValidateCredentials(config);
64
- return new import_client_ecs.ECSClient({
65
- region,
66
- ...credentials && { credentials }
67
- });
68
- };
69
- var extractTaskId = (taskArn) => {
70
- const parts = taskArn.split("/");
71
- return parts[parts.length - 1];
72
- };
73
- var fargate = (0, import_computesdk.createProvider)({
74
- name: "fargate",
75
- methods: {
76
- sandbox: {
77
- // Collection operations (compute.sandbox.*)
78
- create: async (config, options) => {
79
- const {
80
- cluster,
81
- taskDefinition,
82
- subnets,
83
- securityGroups,
84
- assignPublicIp,
85
- containerName
86
- } = getAndValidateCredentials(config);
87
- const client = createECSClient(config);
88
- try {
89
- const command = new import_client_ecs.RunTaskCommand({
90
- cluster,
91
- taskDefinition,
92
- launchType: "FARGATE",
93
- networkConfiguration: {
94
- awsvpcConfiguration: {
95
- subnets,
96
- securityGroups,
97
- assignPublicIp: assignPublicIp ? "ENABLED" : "DISABLED"
98
- }
99
- },
100
- // Container overrides for ECS are limited to environment variables,
101
- // memory, CPU, and command - not the image itself
102
- ...containerName && {
103
- overrides: {
104
- containerOverrides: [
105
- {
106
- name: containerName
107
- // Additional container overrides can be added here if needed
108
- // such as environment variables, memory, CPU, etc.
109
- }
110
- ]
111
- }
112
- }
113
- });
114
- const response = await client.send(command);
115
- if (!response.tasks || response.tasks.length === 0) {
116
- const failures = response.failures?.map((f) => `${f.reason}: ${f.detail}`).join(", ");
117
- throw new Error(`No task created. Failures: ${failures || "unknown"}`);
118
- }
119
- const task = response.tasks[0];
120
- if (!task.taskArn) {
121
- throw new Error("Task ARN is undefined in response");
122
- }
123
- const fargateSandbox = {
124
- taskArn: task.taskArn,
125
- clusterArn: task.clusterArn || cluster,
126
- taskId: extractTaskId(task.taskArn)
127
- };
128
- return {
129
- sandbox: fargateSandbox,
130
- sandboxId: task.taskArn
131
- };
132
- } catch (error) {
133
- throw new Error(
134
- `Failed to create Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`
135
- );
136
- }
137
- },
138
- getById: async (config, sandboxId) => {
139
- const { cluster } = getAndValidateCredentials(config);
140
- const client = createECSClient(config);
141
- try {
142
- const command = new import_client_ecs.DescribeTasksCommand({
143
- cluster,
144
- tasks: [sandboxId]
145
- });
146
- const response = await client.send(command);
147
- if (!response.tasks || response.tasks.length === 0) {
148
- return null;
149
- }
150
- const task = response.tasks[0];
151
- if (!task.taskArn) {
152
- throw new Error("Task ARN is missing from response");
153
- }
154
- const fargateSandbox = {
155
- taskArn: task.taskArn,
156
- clusterArn: task.clusterArn || cluster,
157
- taskId: extractTaskId(task.taskArn)
158
- };
159
- return {
160
- sandbox: fargateSandbox,
161
- sandboxId: task.taskArn
162
- };
163
- } catch (error) {
164
- if (error instanceof Error && (error.message.includes("MISSING") || error.message.includes("not found"))) {
165
- return null;
166
- }
167
- throw new Error(
168
- `Failed to get Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`
169
- );
170
- }
171
- },
172
- list: async (config) => {
173
- const { cluster } = getAndValidateCredentials(config);
174
- const client = createECSClient(config);
175
- try {
176
- const listCommand = new import_client_ecs.ListTasksCommand({
177
- cluster,
178
- desiredStatus: "RUNNING"
179
- });
180
- const listResponse = await client.send(listCommand);
181
- const taskArns = listResponse.taskArns || [];
182
- if (taskArns.length === 0) {
183
- return [];
184
- }
185
- const describeCommand = new import_client_ecs.DescribeTasksCommand({
186
- cluster,
187
- tasks: taskArns
188
- });
189
- const describeResponse = await client.send(describeCommand);
190
- const tasks = describeResponse.tasks || [];
191
- const sandboxes = tasks.filter((task) => task.taskArn).map((task) => {
192
- const fargateSandbox = {
193
- taskArn: task.taskArn,
194
- clusterArn: task.clusterArn || cluster,
195
- taskId: extractTaskId(task.taskArn)
196
- };
197
- return {
198
- sandbox: fargateSandbox,
199
- sandboxId: task.taskArn
200
- };
201
- });
202
- return sandboxes;
203
- } catch (error) {
204
- throw new Error(
205
- `Failed to list Fargate sandboxes: ${error instanceof Error ? error.message : String(error)}`
206
- );
207
- }
208
- },
209
- destroy: async (config, sandboxId) => {
210
- const { cluster } = getAndValidateCredentials(config);
211
- const client = createECSClient(config);
212
- try {
213
- const command = new import_client_ecs.StopTaskCommand({
214
- cluster,
215
- task: sandboxId,
216
- reason: "User requested termination"
217
- });
218
- await client.send(command);
219
- } catch (error) {
220
- if (error instanceof Error && (error.message.includes("MISSING") || error.message.includes("not found") || error.message.includes("STOPPED"))) {
221
- console.warn(`Fargate destroy warning: Task already stopped or not found`);
222
- return;
223
- }
224
- console.warn(
225
- `Fargate destroy warning: ${error instanceof Error ? error.message : String(error)}`
226
- );
227
- }
228
- },
229
- // Instance operations (minimal stubs - not implemented yet)
230
- runCode: async (_sandbox, _code, _runtime) => {
231
- throw new Error("Fargate runCode method not implemented yet");
232
- },
233
- runCommand: async (_sandbox, _command, _args, _options) => {
234
- throw new Error("Fargate runCommand method not implemented yet");
235
- },
236
- getInfo: async (_sandbox) => {
237
- throw new Error("Fargate getInfo method not implemented yet");
238
- },
239
- getUrl: async (_sandbox, _options) => {
240
- throw new Error("Fargate getUrl method not implemented yet");
241
- }
242
- }
243
- }
244
- });
245
- // Annotate the CommonJS export names for ESM import in node:
246
- 0 && (module.exports = {
247
- fargate,
248
- getAndValidateCredentials
249
- });
250
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * AWS ECS Fargate Provider - Factory-based Implementation\n */\n\nimport { createProvider } from 'computesdk';\nimport type { Runtime, CreateSandboxOptions, RunCommandOptions } from 'computesdk';\nimport {\n ECSClient,\n RunTaskCommand,\n StopTaskCommand,\n DescribeTasksCommand,\n ListTasksCommand,\n} from '@aws-sdk/client-ecs';\n\n/**\n * Fargate sandbox interface\n */\ninterface FargateSandbox {\n taskArn: string;\n clusterArn: string;\n taskId: string;\n}\n\nexport interface FargateConfig {\n /** AWS Access Key ID - falls back to AWS_ACCESS_KEY_ID env var or default credential chain */\n accessKeyId?: string;\n /** AWS Secret Access Key - falls back to AWS_SECRET_ACCESS_KEY env var or default credential chain */\n secretAccessKey?: string;\n /** AWS Region - falls back to AWS_REGION env var */\n region?: string;\n /** ECS Cluster name or ARN */\n cluster: string;\n /** Task definition family name or ARN */\n taskDefinition: string;\n /** VPC Subnet IDs for task networking */\n subnets: string[];\n /** Security Group IDs for task networking */\n securityGroups: string[];\n /** Whether to assign a public IP (default: true) */\n assignPublicIp?: boolean;\n /** Container name in the task definition (default: 'sandbox') */\n containerName?: string;\n}\n\nexport const getAndValidateCredentials = (config: FargateConfig) => {\n const region = config.region || process.env?.AWS_REGION || 'us-east-1';\n const cluster = config.cluster;\n const taskDefinition = config.taskDefinition;\n const subnets = config.subnets;\n const securityGroups = config.securityGroups;\n\n if (!cluster) {\n throw new Error('Missing ECS cluster. Provide cluster in config.');\n }\n\n if (!taskDefinition) {\n throw new Error('Missing ECS task definition. Provide taskDefinition in config.');\n }\n\n if (!subnets || subnets.length === 0) {\n throw new Error('Missing subnets. Provide at least one subnet in config.');\n }\n\n if (!securityGroups || securityGroups.length === 0) {\n throw new Error('Missing security groups. Provide at least one security group in config.');\n }\n\n // Build credentials object only if explicitly provided\n // Otherwise, let the SDK use the default credential chain\n const credentials = config.accessKeyId && config.secretAccessKey\n ? {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n }\n : undefined;\n\n return {\n region,\n cluster,\n taskDefinition,\n subnets,\n securityGroups,\n credentials,\n assignPublicIp: config.assignPublicIp ?? true,\n containerName: config.containerName || 'sandbox',\n };\n};\n\n/**\n * Create an ECS client instance\n */\nconst createECSClient = (config: FargateConfig): ECSClient => {\n const { region, credentials } = getAndValidateCredentials(config);\n \n return new ECSClient({\n region,\n ...(credentials && { credentials }),\n });\n};\n\n/**\n * Extract task ID from task ARN\n * ARN format: arn:aws:ecs:region:account:task/cluster-name/task-id\n */\nconst extractTaskId = (taskArn: string): string => {\n const parts = taskArn.split('/');\n return parts[parts.length - 1];\n};\n\n/**\n * Normalize task identifier to full ARN if needed\n */\nconst normalizeTaskArn = (taskId: string, cluster: string, region: string, accountId?: string): string => {\n if (taskId.startsWith('arn:aws:ecs:')) {\n return taskId;\n }\n // If we don't have account ID, just return the task ID and let AWS resolve it\n return taskId;\n};\n\n/**\n * Create an AWS ECS Fargate provider instance using the factory pattern\n */\nexport const fargate = createProvider<FargateSandbox, FargateConfig>({\n name: 'fargate',\n methods: {\n sandbox: {\n // Collection operations (compute.sandbox.*)\n create: async (config: FargateConfig, options?: CreateSandboxOptions) => {\n const {\n cluster,\n taskDefinition,\n subnets,\n securityGroups,\n assignPublicIp,\n containerName,\n } = getAndValidateCredentials(config);\n \n const client = createECSClient(config);\n\n try {\n // Note: For AWS ECS Fargate, the image is specified in the task definition,\n // not as a runtime override. The task definition should be pre-configured\n // with the appropriate image for the desired runtime.\n // \n // The options?.runtime parameter is acknowledged but the actual runtime\n // environment is determined by the pre-configured task definition.\n \n const command = new RunTaskCommand({\n cluster,\n taskDefinition,\n launchType: 'FARGATE',\n networkConfiguration: {\n awsvpcConfiguration: {\n subnets,\n securityGroups,\n assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED',\n },\n },\n // Container overrides for ECS are limited to environment variables, \n // memory, CPU, and command - not the image itself\n ...(containerName && {\n overrides: {\n containerOverrides: [\n {\n name: containerName,\n // Additional container overrides can be added here if needed\n // such as environment variables, memory, CPU, etc.\n },\n ],\n },\n }),\n });\n\n const response = await client.send(command);\n\n if (!response.tasks || response.tasks.length === 0) {\n const failures = response.failures?.map(f => `${f.reason}: ${f.detail}`).join(', ');\n throw new Error(`No task created. Failures: ${failures || 'unknown'}`);\n }\n\n const task = response.tasks[0];\n \n if (!task.taskArn) {\n throw new Error('Task ARN is undefined in response');\n }\n\n const fargateSandbox: FargateSandbox = {\n taskArn: task.taskArn,\n clusterArn: task.clusterArn || cluster,\n taskId: extractTaskId(task.taskArn),\n };\n\n return {\n sandbox: fargateSandbox,\n sandboxId: task.taskArn,\n };\n } catch (error) {\n throw new Error(\n `Failed to create Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: FargateConfig, sandboxId: string) => {\n const { cluster } = getAndValidateCredentials(config);\n const client = createECSClient(config);\n\n try {\n const command = new DescribeTasksCommand({\n cluster,\n tasks: [sandboxId],\n });\n\n const response = await client.send(command);\n\n if (!response.tasks || response.tasks.length === 0) {\n return null;\n }\n\n const task = response.tasks[0];\n \n if (!task.taskArn) {\n throw new Error('Task ARN is missing from response');\n }\n\n const fargateSandbox: FargateSandbox = {\n taskArn: task.taskArn,\n clusterArn: task.clusterArn || cluster,\n taskId: extractTaskId(task.taskArn),\n };\n\n return {\n sandbox: fargateSandbox,\n sandboxId: task.taskArn,\n };\n } catch (error) {\n // Handle task not found\n if (error instanceof Error && \n (error.message.includes('MISSING') || error.message.includes('not found'))) {\n return null;\n }\n throw new Error(\n `Failed to get Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n list: async (config: FargateConfig) => {\n const { cluster } = getAndValidateCredentials(config);\n const client = createECSClient(config);\n\n try {\n // Step 1: List task ARNs\n const listCommand = new ListTasksCommand({\n cluster,\n desiredStatus: 'RUNNING',\n });\n\n const listResponse = await client.send(listCommand);\n const taskArns = listResponse.taskArns || [];\n\n if (taskArns.length === 0) {\n return [];\n }\n\n // Step 2: Describe tasks to get full details\n const describeCommand = new DescribeTasksCommand({\n cluster,\n tasks: taskArns,\n });\n\n const describeResponse = await client.send(describeCommand);\n const tasks = describeResponse.tasks || [];\n\n // Transform each task into the expected format\n const sandboxes = tasks\n .filter(task => task.taskArn)\n .map(task => {\n const fargateSandbox: FargateSandbox = {\n taskArn: task.taskArn!,\n clusterArn: task.clusterArn || cluster,\n taskId: extractTaskId(task.taskArn!),\n };\n\n return {\n sandbox: fargateSandbox,\n sandboxId: task.taskArn!,\n };\n });\n\n return sandboxes;\n } catch (error) {\n throw new Error(\n `Failed to list Fargate sandboxes: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n destroy: async (config: FargateConfig, sandboxId: string) => {\n const { cluster } = getAndValidateCredentials(config);\n const client = createECSClient(config);\n\n try {\n const command = new StopTaskCommand({\n cluster,\n task: sandboxId,\n reason: 'User requested termination',\n });\n\n await client.send(command);\n } catch (error) {\n // For destroy operations, don't throw if task is already stopped/gone\n if (error instanceof Error && \n (error.message.includes('MISSING') || \n error.message.includes('not found') ||\n error.message.includes('STOPPED'))) {\n console.warn(`Fargate destroy warning: Task already stopped or not found`);\n return;\n }\n console.warn(\n `Fargate destroy warning: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Instance operations (minimal stubs - not implemented yet)\n runCode: async (_sandbox: FargateSandbox, _code: string, _runtime?: Runtime) => {\n throw new Error('Fargate runCode method not implemented yet');\n },\n\n runCommand: async (_sandbox: FargateSandbox, _command: string, _args?: string[], _options?: RunCommandOptions) => {\n throw new Error('Fargate runCommand method not implemented yet');\n },\n\n getInfo: async (_sandbox: FargateSandbox) => {\n throw new Error('Fargate getInfo method not implemented yet');\n },\n\n getUrl: async (_sandbox: FargateSandbox, _options: { port: number; protocol?: string }) => {\n throw new Error('Fargate getUrl method not implemented yet');\n },\n },\n },\n});"],"mappings":"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","names":[]}
package/dist/index.mjs DELETED
@@ -1,230 +0,0 @@
1
- // src/index.ts
2
- import { createProvider } from "computesdk";
3
- import {
4
- ECSClient,
5
- RunTaskCommand,
6
- StopTaskCommand,
7
- DescribeTasksCommand,
8
- ListTasksCommand
9
- } from "@aws-sdk/client-ecs";
10
- var getAndValidateCredentials = (config) => {
11
- const region = config.region || process.env?.AWS_REGION || "us-east-1";
12
- const cluster = config.cluster;
13
- const taskDefinition = config.taskDefinition;
14
- const subnets = config.subnets;
15
- const securityGroups = config.securityGroups;
16
- if (!cluster) {
17
- throw new Error("Missing ECS cluster. Provide cluster in config.");
18
- }
19
- if (!taskDefinition) {
20
- throw new Error("Missing ECS task definition. Provide taskDefinition in config.");
21
- }
22
- if (!subnets || subnets.length === 0) {
23
- throw new Error("Missing subnets. Provide at least one subnet in config.");
24
- }
25
- if (!securityGroups || securityGroups.length === 0) {
26
- throw new Error("Missing security groups. Provide at least one security group in config.");
27
- }
28
- const credentials = config.accessKeyId && config.secretAccessKey ? {
29
- accessKeyId: config.accessKeyId,
30
- secretAccessKey: config.secretAccessKey
31
- } : void 0;
32
- return {
33
- region,
34
- cluster,
35
- taskDefinition,
36
- subnets,
37
- securityGroups,
38
- credentials,
39
- assignPublicIp: config.assignPublicIp ?? true,
40
- containerName: config.containerName || "sandbox"
41
- };
42
- };
43
- var createECSClient = (config) => {
44
- const { region, credentials } = getAndValidateCredentials(config);
45
- return new ECSClient({
46
- region,
47
- ...credentials && { credentials }
48
- });
49
- };
50
- var extractTaskId = (taskArn) => {
51
- const parts = taskArn.split("/");
52
- return parts[parts.length - 1];
53
- };
54
- var fargate = createProvider({
55
- name: "fargate",
56
- methods: {
57
- sandbox: {
58
- // Collection operations (compute.sandbox.*)
59
- create: async (config, options) => {
60
- const {
61
- cluster,
62
- taskDefinition,
63
- subnets,
64
- securityGroups,
65
- assignPublicIp,
66
- containerName
67
- } = getAndValidateCredentials(config);
68
- const client = createECSClient(config);
69
- try {
70
- const command = new RunTaskCommand({
71
- cluster,
72
- taskDefinition,
73
- launchType: "FARGATE",
74
- networkConfiguration: {
75
- awsvpcConfiguration: {
76
- subnets,
77
- securityGroups,
78
- assignPublicIp: assignPublicIp ? "ENABLED" : "DISABLED"
79
- }
80
- },
81
- // Container overrides for ECS are limited to environment variables,
82
- // memory, CPU, and command - not the image itself
83
- ...containerName && {
84
- overrides: {
85
- containerOverrides: [
86
- {
87
- name: containerName
88
- // Additional container overrides can be added here if needed
89
- // such as environment variables, memory, CPU, etc.
90
- }
91
- ]
92
- }
93
- }
94
- });
95
- const response = await client.send(command);
96
- if (!response.tasks || response.tasks.length === 0) {
97
- const failures = response.failures?.map((f) => `${f.reason}: ${f.detail}`).join(", ");
98
- throw new Error(`No task created. Failures: ${failures || "unknown"}`);
99
- }
100
- const task = response.tasks[0];
101
- if (!task.taskArn) {
102
- throw new Error("Task ARN is undefined in response");
103
- }
104
- const fargateSandbox = {
105
- taskArn: task.taskArn,
106
- clusterArn: task.clusterArn || cluster,
107
- taskId: extractTaskId(task.taskArn)
108
- };
109
- return {
110
- sandbox: fargateSandbox,
111
- sandboxId: task.taskArn
112
- };
113
- } catch (error) {
114
- throw new Error(
115
- `Failed to create Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`
116
- );
117
- }
118
- },
119
- getById: async (config, sandboxId) => {
120
- const { cluster } = getAndValidateCredentials(config);
121
- const client = createECSClient(config);
122
- try {
123
- const command = new DescribeTasksCommand({
124
- cluster,
125
- tasks: [sandboxId]
126
- });
127
- const response = await client.send(command);
128
- if (!response.tasks || response.tasks.length === 0) {
129
- return null;
130
- }
131
- const task = response.tasks[0];
132
- if (!task.taskArn) {
133
- throw new Error("Task ARN is missing from response");
134
- }
135
- const fargateSandbox = {
136
- taskArn: task.taskArn,
137
- clusterArn: task.clusterArn || cluster,
138
- taskId: extractTaskId(task.taskArn)
139
- };
140
- return {
141
- sandbox: fargateSandbox,
142
- sandboxId: task.taskArn
143
- };
144
- } catch (error) {
145
- if (error instanceof Error && (error.message.includes("MISSING") || error.message.includes("not found"))) {
146
- return null;
147
- }
148
- throw new Error(
149
- `Failed to get Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`
150
- );
151
- }
152
- },
153
- list: async (config) => {
154
- const { cluster } = getAndValidateCredentials(config);
155
- const client = createECSClient(config);
156
- try {
157
- const listCommand = new ListTasksCommand({
158
- cluster,
159
- desiredStatus: "RUNNING"
160
- });
161
- const listResponse = await client.send(listCommand);
162
- const taskArns = listResponse.taskArns || [];
163
- if (taskArns.length === 0) {
164
- return [];
165
- }
166
- const describeCommand = new DescribeTasksCommand({
167
- cluster,
168
- tasks: taskArns
169
- });
170
- const describeResponse = await client.send(describeCommand);
171
- const tasks = describeResponse.tasks || [];
172
- const sandboxes = tasks.filter((task) => task.taskArn).map((task) => {
173
- const fargateSandbox = {
174
- taskArn: task.taskArn,
175
- clusterArn: task.clusterArn || cluster,
176
- taskId: extractTaskId(task.taskArn)
177
- };
178
- return {
179
- sandbox: fargateSandbox,
180
- sandboxId: task.taskArn
181
- };
182
- });
183
- return sandboxes;
184
- } catch (error) {
185
- throw new Error(
186
- `Failed to list Fargate sandboxes: ${error instanceof Error ? error.message : String(error)}`
187
- );
188
- }
189
- },
190
- destroy: async (config, sandboxId) => {
191
- const { cluster } = getAndValidateCredentials(config);
192
- const client = createECSClient(config);
193
- try {
194
- const command = new StopTaskCommand({
195
- cluster,
196
- task: sandboxId,
197
- reason: "User requested termination"
198
- });
199
- await client.send(command);
200
- } catch (error) {
201
- if (error instanceof Error && (error.message.includes("MISSING") || error.message.includes("not found") || error.message.includes("STOPPED"))) {
202
- console.warn(`Fargate destroy warning: Task already stopped or not found`);
203
- return;
204
- }
205
- console.warn(
206
- `Fargate destroy warning: ${error instanceof Error ? error.message : String(error)}`
207
- );
208
- }
209
- },
210
- // Instance operations (minimal stubs - not implemented yet)
211
- runCode: async (_sandbox, _code, _runtime) => {
212
- throw new Error("Fargate runCode method not implemented yet");
213
- },
214
- runCommand: async (_sandbox, _command, _args, _options) => {
215
- throw new Error("Fargate runCommand method not implemented yet");
216
- },
217
- getInfo: async (_sandbox) => {
218
- throw new Error("Fargate getInfo method not implemented yet");
219
- },
220
- getUrl: async (_sandbox, _options) => {
221
- throw new Error("Fargate getUrl method not implemented yet");
222
- }
223
- }
224
- }
225
- });
226
- export {
227
- fargate,
228
- getAndValidateCredentials
229
- };
230
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * AWS ECS Fargate Provider - Factory-based Implementation\n */\n\nimport { createProvider } from 'computesdk';\nimport type { Runtime, CreateSandboxOptions, RunCommandOptions } from 'computesdk';\nimport {\n ECSClient,\n RunTaskCommand,\n StopTaskCommand,\n DescribeTasksCommand,\n ListTasksCommand,\n} from '@aws-sdk/client-ecs';\n\n/**\n * Fargate sandbox interface\n */\ninterface FargateSandbox {\n taskArn: string;\n clusterArn: string;\n taskId: string;\n}\n\nexport interface FargateConfig {\n /** AWS Access Key ID - falls back to AWS_ACCESS_KEY_ID env var or default credential chain */\n accessKeyId?: string;\n /** AWS Secret Access Key - falls back to AWS_SECRET_ACCESS_KEY env var or default credential chain */\n secretAccessKey?: string;\n /** AWS Region - falls back to AWS_REGION env var */\n region?: string;\n /** ECS Cluster name or ARN */\n cluster: string;\n /** Task definition family name or ARN */\n taskDefinition: string;\n /** VPC Subnet IDs for task networking */\n subnets: string[];\n /** Security Group IDs for task networking */\n securityGroups: string[];\n /** Whether to assign a public IP (default: true) */\n assignPublicIp?: boolean;\n /** Container name in the task definition (default: 'sandbox') */\n containerName?: string;\n}\n\nexport const getAndValidateCredentials = (config: FargateConfig) => {\n const region = config.region || process.env?.AWS_REGION || 'us-east-1';\n const cluster = config.cluster;\n const taskDefinition = config.taskDefinition;\n const subnets = config.subnets;\n const securityGroups = config.securityGroups;\n\n if (!cluster) {\n throw new Error('Missing ECS cluster. Provide cluster in config.');\n }\n\n if (!taskDefinition) {\n throw new Error('Missing ECS task definition. Provide taskDefinition in config.');\n }\n\n if (!subnets || subnets.length === 0) {\n throw new Error('Missing subnets. Provide at least one subnet in config.');\n }\n\n if (!securityGroups || securityGroups.length === 0) {\n throw new Error('Missing security groups. Provide at least one security group in config.');\n }\n\n // Build credentials object only if explicitly provided\n // Otherwise, let the SDK use the default credential chain\n const credentials = config.accessKeyId && config.secretAccessKey\n ? {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n }\n : undefined;\n\n return {\n region,\n cluster,\n taskDefinition,\n subnets,\n securityGroups,\n credentials,\n assignPublicIp: config.assignPublicIp ?? true,\n containerName: config.containerName || 'sandbox',\n };\n};\n\n/**\n * Create an ECS client instance\n */\nconst createECSClient = (config: FargateConfig): ECSClient => {\n const { region, credentials } = getAndValidateCredentials(config);\n \n return new ECSClient({\n region,\n ...(credentials && { credentials }),\n });\n};\n\n/**\n * Extract task ID from task ARN\n * ARN format: arn:aws:ecs:region:account:task/cluster-name/task-id\n */\nconst extractTaskId = (taskArn: string): string => {\n const parts = taskArn.split('/');\n return parts[parts.length - 1];\n};\n\n/**\n * Normalize task identifier to full ARN if needed\n */\nconst normalizeTaskArn = (taskId: string, cluster: string, region: string, accountId?: string): string => {\n if (taskId.startsWith('arn:aws:ecs:')) {\n return taskId;\n }\n // If we don't have account ID, just return the task ID and let AWS resolve it\n return taskId;\n};\n\n/**\n * Create an AWS ECS Fargate provider instance using the factory pattern\n */\nexport const fargate = createProvider<FargateSandbox, FargateConfig>({\n name: 'fargate',\n methods: {\n sandbox: {\n // Collection operations (compute.sandbox.*)\n create: async (config: FargateConfig, options?: CreateSandboxOptions) => {\n const {\n cluster,\n taskDefinition,\n subnets,\n securityGroups,\n assignPublicIp,\n containerName,\n } = getAndValidateCredentials(config);\n \n const client = createECSClient(config);\n\n try {\n // Note: For AWS ECS Fargate, the image is specified in the task definition,\n // not as a runtime override. The task definition should be pre-configured\n // with the appropriate image for the desired runtime.\n // \n // The options?.runtime parameter is acknowledged but the actual runtime\n // environment is determined by the pre-configured task definition.\n \n const command = new RunTaskCommand({\n cluster,\n taskDefinition,\n launchType: 'FARGATE',\n networkConfiguration: {\n awsvpcConfiguration: {\n subnets,\n securityGroups,\n assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED',\n },\n },\n // Container overrides for ECS are limited to environment variables, \n // memory, CPU, and command - not the image itself\n ...(containerName && {\n overrides: {\n containerOverrides: [\n {\n name: containerName,\n // Additional container overrides can be added here if needed\n // such as environment variables, memory, CPU, etc.\n },\n ],\n },\n }),\n });\n\n const response = await client.send(command);\n\n if (!response.tasks || response.tasks.length === 0) {\n const failures = response.failures?.map(f => `${f.reason}: ${f.detail}`).join(', ');\n throw new Error(`No task created. Failures: ${failures || 'unknown'}`);\n }\n\n const task = response.tasks[0];\n \n if (!task.taskArn) {\n throw new Error('Task ARN is undefined in response');\n }\n\n const fargateSandbox: FargateSandbox = {\n taskArn: task.taskArn,\n clusterArn: task.clusterArn || cluster,\n taskId: extractTaskId(task.taskArn),\n };\n\n return {\n sandbox: fargateSandbox,\n sandboxId: task.taskArn,\n };\n } catch (error) {\n throw new Error(\n `Failed to create Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: FargateConfig, sandboxId: string) => {\n const { cluster } = getAndValidateCredentials(config);\n const client = createECSClient(config);\n\n try {\n const command = new DescribeTasksCommand({\n cluster,\n tasks: [sandboxId],\n });\n\n const response = await client.send(command);\n\n if (!response.tasks || response.tasks.length === 0) {\n return null;\n }\n\n const task = response.tasks[0];\n \n if (!task.taskArn) {\n throw new Error('Task ARN is missing from response');\n }\n\n const fargateSandbox: FargateSandbox = {\n taskArn: task.taskArn,\n clusterArn: task.clusterArn || cluster,\n taskId: extractTaskId(task.taskArn),\n };\n\n return {\n sandbox: fargateSandbox,\n sandboxId: task.taskArn,\n };\n } catch (error) {\n // Handle task not found\n if (error instanceof Error && \n (error.message.includes('MISSING') || error.message.includes('not found'))) {\n return null;\n }\n throw new Error(\n `Failed to get Fargate sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n list: async (config: FargateConfig) => {\n const { cluster } = getAndValidateCredentials(config);\n const client = createECSClient(config);\n\n try {\n // Step 1: List task ARNs\n const listCommand = new ListTasksCommand({\n cluster,\n desiredStatus: 'RUNNING',\n });\n\n const listResponse = await client.send(listCommand);\n const taskArns = listResponse.taskArns || [];\n\n if (taskArns.length === 0) {\n return [];\n }\n\n // Step 2: Describe tasks to get full details\n const describeCommand = new DescribeTasksCommand({\n cluster,\n tasks: taskArns,\n });\n\n const describeResponse = await client.send(describeCommand);\n const tasks = describeResponse.tasks || [];\n\n // Transform each task into the expected format\n const sandboxes = tasks\n .filter(task => task.taskArn)\n .map(task => {\n const fargateSandbox: FargateSandbox = {\n taskArn: task.taskArn!,\n clusterArn: task.clusterArn || cluster,\n taskId: extractTaskId(task.taskArn!),\n };\n\n return {\n sandbox: fargateSandbox,\n sandboxId: task.taskArn!,\n };\n });\n\n return sandboxes;\n } catch (error) {\n throw new Error(\n `Failed to list Fargate sandboxes: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n destroy: async (config: FargateConfig, sandboxId: string) => {\n const { cluster } = getAndValidateCredentials(config);\n const client = createECSClient(config);\n\n try {\n const command = new StopTaskCommand({\n cluster,\n task: sandboxId,\n reason: 'User requested termination',\n });\n\n await client.send(command);\n } catch (error) {\n // For destroy operations, don't throw if task is already stopped/gone\n if (error instanceof Error && \n (error.message.includes('MISSING') || \n error.message.includes('not found') ||\n error.message.includes('STOPPED'))) {\n console.warn(`Fargate destroy warning: Task already stopped or not found`);\n return;\n }\n console.warn(\n `Fargate destroy warning: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Instance operations (minimal stubs - not implemented yet)\n runCode: async (_sandbox: FargateSandbox, _code: string, _runtime?: Runtime) => {\n throw new Error('Fargate runCode method not implemented yet');\n },\n\n runCommand: async (_sandbox: FargateSandbox, _command: string, _args?: string[], _options?: RunCommandOptions) => {\n throw new Error('Fargate runCommand method not implemented yet');\n },\n\n getInfo: async (_sandbox: FargateSandbox) => {\n throw new Error('Fargate getInfo method not implemented yet');\n },\n\n getUrl: async (_sandbox: FargateSandbox, _options: { port: number; protocol?: string }) => {\n throw new Error('Fargate getUrl method not implemented yet');\n },\n },\n },\n});"],"mappings":"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","names":[]}