@computesdk/lambda 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 computesdk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # @computesdk/lambda
2
+
3
+ Lambda provider for ComputeSDK - enables sandbox creation and management on Lambda cloud infrastructure.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @computesdk/lambda
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { lambda } from '@computesdk/lambda';
15
+
16
+ const compute = lambda({
17
+ apiKey: 'your-lambda-api-key', // or set LAMBDA_API_KEY environment variable
18
+ regionName: 'us-west-1', // or set LAMBDA_REGION_NAME environment variable
19
+ instanceTypeName: 'gpu_1x_a10', // or set LAMBDA_INSTANCE_TYPE_NAME environment variable
20
+ sshKeyName: 'your-ssh-key' // or set LAMBDA_SSH_KEY_NAME environment variable
21
+ });
22
+
23
+ // Create a new sandbox
24
+ const { sandbox, sandboxId } = await compute.sandbox.create({
25
+ runtime: 'node' // or 'python'
26
+ });
27
+
28
+ // List all sandboxes
29
+ const sandboxes = await compute.sandbox.list();
30
+
31
+ // Get a specific sandbox
32
+ const retrieved = await compute.sandbox.getById(sandboxId);
33
+
34
+ // Destroy a sandbox
35
+ await compute.sandbox.destroy(sandboxId);
36
+ ```
37
+
38
+ ## Configuration
39
+
40
+ Set the following environment variables or pass them in the config object:
41
+
42
+ - `LAMBDA_API_KEY` - Your Lambda API key
43
+ - `LAMBDA_REGION_NAME` - Lambda region (e.g., 'us-west-1')
44
+ - `LAMBDA_INSTANCE_TYPE_NAME` - Instance type (e.g., 'gpu_1x_a10')
45
+ - `LAMBDA_SSH_KEY_NAME` - SSH key name for instance access
46
+
47
+
48
+ ## License
49
+
50
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,229 @@
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
+ fetchLambda: () => fetchLambda,
24
+ getAndValidateCredentials: () => getAndValidateCredentials,
25
+ lambda: () => lambda
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var import_computesdk = require("computesdk");
29
+ var getAndValidateCredentials = (config) => {
30
+ const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.LAMBDA_API_KEY || "";
31
+ const regionName = config.regionName || typeof process !== "undefined" && process.env?.LAMBDA_REGION_NAME || "";
32
+ const instanceTypeName = config.instanceTypeName || typeof process !== "undefined" && process.env?.LAMBDA_INSTANCE_TYPE_NAME || "";
33
+ const sshKeyName = config.sshKeyName || typeof process !== "undefined" && process.env?.LAMBDA_SSH_KEY_NAME || "";
34
+ if (!apiKey) {
35
+ throw new Error(
36
+ "Missing Lambda API key. Provide apiKey in config or set LAMBDA_API_KEY environment variable."
37
+ );
38
+ }
39
+ if (!regionName) {
40
+ throw new Error(
41
+ "Missing Lambda Region Name. Provide regionName in config or set LAMBDA_REGION_NAME environment variable."
42
+ );
43
+ }
44
+ if (!instanceTypeName) {
45
+ throw new Error(
46
+ "Missing Lambda Instance Type Name. Provide instanceTypeName in config or set LAMBDA_INSTANCE_TYPE_NAME environment variable."
47
+ );
48
+ }
49
+ if (!sshKeyName) {
50
+ throw new Error(
51
+ "Missing Lambda SSH Key Name. Provide sshKeyName in config or set LAMBDA_SSH_KEY_NAME environment variable."
52
+ );
53
+ }
54
+ return { apiKey, regionName, instanceTypeName, sshKeyName };
55
+ };
56
+ var LAMBDA_API_ENDPOINTS = {
57
+ LAUNCH_INSTANCE: "https://cloud.lambda.ai/api/v1/instance-operations/launch",
58
+ LIST_INSTANCES: "https://cloud.lambda.ai/api/v1/instances",
59
+ GET_INSTANCE: (instanceId) => `https://cloud.lambda.ai/api/v1/instances/${instanceId}`,
60
+ TERMINATE_INSTANCES: "https://cloud.lambda.ai/api/v1/instance-operations/terminate"
61
+ };
62
+ var handleLambdaAPIError = (response, data) => {
63
+ if (!response.ok) {
64
+ let errorMessage;
65
+ if (data?.error) {
66
+ if (typeof data.error === "object" && data.error.message) {
67
+ errorMessage = `${data.error.message}${data.error.suggestion ? ` ${data.error.suggestion}` : ""} (${data.error.code || "unknown"})`;
68
+ } else {
69
+ errorMessage = JSON.stringify(data.error);
70
+ }
71
+ } else {
72
+ errorMessage = data?.message || `HTTP ${response.status} ${response.statusText}`;
73
+ }
74
+ throw new Error(`Lambda API error: ${errorMessage}`);
75
+ }
76
+ };
77
+ var fetchLambda = async (apiKey, endpoint, options = {}) => {
78
+ const { method = "GET", body } = options;
79
+ const response = await fetch(endpoint, {
80
+ method,
81
+ headers: {
82
+ "Content-Type": "application/json",
83
+ "Authorization": `Bearer ${apiKey}`
84
+ },
85
+ ...body ? { body: JSON.stringify(body) } : {}
86
+ });
87
+ const data = await response.json();
88
+ handleLambdaAPIError(response, data);
89
+ return data;
90
+ };
91
+ var lambda = (0, import_computesdk.createProvider)({
92
+ name: "lambda",
93
+ methods: {
94
+ sandbox: {
95
+ // Collection operations (compute.sandbox.*)
96
+ create: async (config, options) => {
97
+ const { apiKey, regionName, instanceTypeName, sshKeyName } = getAndValidateCredentials(config);
98
+ try {
99
+ const dockerImage = options?.runtime === "node" ? "node:alpine" : "python:alpine";
100
+ const userData = `#!/bin/bash
101
+ apt-get update
102
+ apt-get install -y docker.io
103
+ systemctl start docker
104
+ systemctl enable docker
105
+ docker pull ${dockerImage}
106
+ docker run -d --name compute-app ${dockerImage} tail -f /dev/null`;
107
+ const launchBody = {
108
+ region_name: regionName,
109
+ instance_type_name: instanceTypeName,
110
+ ssh_key_names: [sshKeyName],
111
+ name: `compute-${options?.runtime || "node"}-instance`,
112
+ user_data: userData
113
+ };
114
+ const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LAUNCH_INSTANCE, {
115
+ method: "POST",
116
+ body: launchBody
117
+ });
118
+ const instanceIds = responseData?.data?.instance_ids;
119
+ if (!instanceIds || !Array.isArray(instanceIds) || instanceIds.length === 0) {
120
+ throw new Error(`No instance IDs returned from Lambda API. Full response: ${JSON.stringify(responseData)}`);
121
+ }
122
+ const instanceId = instanceIds[0];
123
+ const lambdaSandbox = {
124
+ instanceId,
125
+ regionName,
126
+ instanceTypeName
127
+ };
128
+ return {
129
+ sandbox: lambdaSandbox,
130
+ sandboxId: instanceId
131
+ };
132
+ } catch (error) {
133
+ throw new Error(
134
+ `Failed to create Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`
135
+ );
136
+ }
137
+ },
138
+ getById: async (config, sandboxId) => {
139
+ const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);
140
+ try {
141
+ const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.GET_INSTANCE(sandboxId));
142
+ const instance = responseData?.data;
143
+ if (!instance) {
144
+ return null;
145
+ }
146
+ if (!instance.id) {
147
+ throw new Error("Instance data is missing ID from Lambda response");
148
+ }
149
+ const lambdaSandbox = {
150
+ instanceId: instance.id,
151
+ regionName,
152
+ instanceTypeName
153
+ };
154
+ return {
155
+ sandbox: lambdaSandbox,
156
+ sandboxId: instance.id
157
+ };
158
+ } catch (error) {
159
+ if (error instanceof Error && (error.message.includes("404") || error.message.includes("Not Found"))) {
160
+ return null;
161
+ }
162
+ throw new Error(
163
+ `Failed to get Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`
164
+ );
165
+ }
166
+ },
167
+ list: async (config) => {
168
+ const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);
169
+ try {
170
+ const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LIST_INSTANCES);
171
+ const instances = responseData?.data || [];
172
+ if (!Array.isArray(instances)) {
173
+ throw new Error(`Expected instances array, got: ${typeof instances}`);
174
+ }
175
+ const sandboxes = instances.map((instance) => {
176
+ const lambdaSandbox = {
177
+ instanceId: instance.id,
178
+ regionName,
179
+ instanceTypeName
180
+ };
181
+ return {
182
+ sandbox: lambdaSandbox,
183
+ sandboxId: instance.id
184
+ };
185
+ });
186
+ return sandboxes;
187
+ } catch (error) {
188
+ throw new Error(
189
+ `Failed to list Lambda sandboxes: ${error instanceof Error ? error.message : String(error)}`
190
+ );
191
+ }
192
+ },
193
+ destroy: async (config, sandboxId) => {
194
+ const { apiKey } = getAndValidateCredentials(config);
195
+ try {
196
+ const terminateBody = {
197
+ instance_ids: [sandboxId]
198
+ };
199
+ await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.TERMINATE_INSTANCES, {
200
+ method: "POST",
201
+ body: terminateBody
202
+ });
203
+ } catch (error) {
204
+ console.warn(`Lambda destroy warning: ${error instanceof Error ? error.message : String(error)}`);
205
+ }
206
+ },
207
+ // Instance operations (minimal stubs - not implemented yet)
208
+ runCode: async (_sandbox, _code, _runtime) => {
209
+ throw new Error("Lambda runCode method not implemented yet");
210
+ },
211
+ runCommand: async (_sandbox, _command, _args, _options) => {
212
+ throw new Error("Lambda runCommand method not implemented yet");
213
+ },
214
+ getInfo: async (_sandbox) => {
215
+ throw new Error("Lambda getInfo method not implemented yet");
216
+ },
217
+ getUrl: async (_sandbox, _options) => {
218
+ throw new Error("Lambda getUrl method not implemented yet");
219
+ }
220
+ }
221
+ }
222
+ });
223
+ // Annotate the CommonJS export names for ESM import in node:
224
+ 0 && (module.exports = {
225
+ fetchLambda,
226
+ getAndValidateCredentials,
227
+ lambda
228
+ });
229
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Lambda Provider - Factory-based Implementation\n * \n * Curl Command to start instance with Node:Alpine\n * curl --request POST \\\n --url 'https://cloud.lambda.ai/api/v1/instance-operations/launch' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"region_name\": LAMBDA_REGION_NAME,\n \"instance_type_name\": LAMBDA_INSTANCE_TYPE_NAME,\n \"ssh_key_names\": [\"LAMBDA_SSH_KEY_NAME\"],\n \"name\": \"node-alpine-instance\",\n \"user_data\": \"#!/bin/bash\\napt-get update\\napt-get install -y docker.io\\nsystemctl start docker\\nsystemctl enable docker\\ndocker pull node:alpine\\ndocker run -d --name node-app node:alpine tail -f /dev/null\"\n }'\n *\n * Curl Command to list instances\n * curl --request GET \\\n --url 'https://cloud.lambda.ai/api/v1/instances' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY'\n *\n * Curl Command to getById()\n * curl --request GET \\\n --url 'https://cloud.lambda.ai/api/v1/instances/<INSTANCE-ID>' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY'\n *\n * Curl Command to Destroy Instance (terminate)\n * curl --request POST \\\n --url 'https://cloud.lambda.ai/api/v1/instance-operations/terminate' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"instance_ids\": [\"<YOUR-INSTANCE-ID>\"]\n }'\n */\n\nimport { createProvider } from 'computesdk';\nimport type { Runtime, ExecutionResult, SandboxInfo, CreateSandboxOptions, FileEntry, RunCommandOptions } from 'computesdk';\n\n/**\n * Lambda sandbox interface\n */\ninterface LambdaSandbox {\n instanceId: string;\n regionName: string;\n instanceTypeName: string;\n}\n\nexport interface LambdaConfig {\n /** Lambda API key - if not provided, will fallback to LAMBDA_API_KEY environment variable */\n apiKey?: string;\n /** Lambda Region Name - if not provided, will fallback to LAMBDA_REGION_NAME environment variable */\n regionName?: string;\n /** Lambda Instance Type Name - if not provided, will fallback to LAMBDA_INSTANCE_TYPE_NAME environment variable */\n instanceTypeName?: string;\n /** Lambda SSH Key Name - if not provided, will fallback to LAMBDA_SSH_KEY_NAME environment variable */\n sshKeyName?: string;\n}\n\nexport const getAndValidateCredentials = (config: LambdaConfig) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.LAMBDA_API_KEY) || '';\n const regionName = config.regionName || (typeof process !== 'undefined' && process.env?.LAMBDA_REGION_NAME) || '';\n const instanceTypeName = config.instanceTypeName || (typeof process !== 'undefined' && process.env?.LAMBDA_INSTANCE_TYPE_NAME) || '';\n const sshKeyName = config.sshKeyName || (typeof process !== 'undefined' && process.env?.LAMBDA_SSH_KEY_NAME) || '';\n\n if (!apiKey) {\n throw new Error(\n 'Missing Lambda API key. Provide apiKey in config or set LAMBDA_API_KEY environment variable.'\n );\n }\n\n if (!regionName) {\n throw new Error(\n 'Missing Lambda Region Name. Provide regionName in config or set LAMBDA_REGION_NAME environment variable.'\n );\n }\n\n if (!instanceTypeName) {\n throw new Error(\n 'Missing Lambda Instance Type Name. Provide instanceTypeName in config or set LAMBDA_INSTANCE_TYPE_NAME environment variable.'\n );\n }\n\n if (!sshKeyName) {\n throw new Error(\n 'Missing Lambda SSH Key Name. Provide sshKeyName in config or set LAMBDA_SSH_KEY_NAME environment variable.'\n );\n }\n\n return { apiKey, regionName, instanceTypeName, sshKeyName };\n};\n\nconst LAMBDA_API_ENDPOINTS = {\n LAUNCH_INSTANCE: 'https://cloud.lambda.ai/api/v1/instance-operations/launch',\n LIST_INSTANCES: 'https://cloud.lambda.ai/api/v1/instances',\n GET_INSTANCE: (instanceId: string) => `https://cloud.lambda.ai/api/v1/instances/${instanceId}`,\n TERMINATE_INSTANCES: 'https://cloud.lambda.ai/api/v1/instance-operations/terminate'\n};\n\nconst handleLambdaAPIError = (response: Response, data?: any) => {\n if (!response.ok) {\n let errorMessage;\n if (data?.error) {\n // Handle Lambda API error format: { \"error\": { \"code\": \"...\", \"message\": \"...\", \"suggestion\": \"...\" } }\n if (typeof data.error === 'object' && data.error.message) {\n errorMessage = `${data.error.message}${data.error.suggestion ? ` ${data.error.suggestion}` : ''} (${data.error.code || 'unknown'})`;\n } else {\n errorMessage = JSON.stringify(data.error);\n }\n } else {\n errorMessage = data?.message || `HTTP ${response.status} ${response.statusText}`;\n }\n throw new Error(`Lambda API error: ${errorMessage}`);\n }\n};\n\n\nexport const fetchLambda = async (\n apiKey: string,\n endpoint: string,\n options: {\n method?: string;\n body?: any;\n } = {}\n) => {\n const { method = 'GET', body } = options;\n \n const response = await fetch(endpoint, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`\n },\n ...(body ? { body: JSON.stringify(body) } : {})\n });\n\n const data = await response.json();\n\n // Handle Lambda API errors\n handleLambdaAPIError(response, data);\n\n return data;\n};\n\n\n\n/**\n * Create a Lambda provider instance using the factory pattern\n */\nexport const lambda = createProvider<LambdaSandbox, LambdaConfig>({\n name: 'lambda',\n methods: {\n sandbox: {\n // Collection operations (compute.sandbox.*)\n create: async (config: LambdaConfig, options?: CreateSandboxOptions) => {\n const { apiKey, regionName, instanceTypeName, sshKeyName } = getAndValidateCredentials(config);\n\n try {\n const dockerImage = options?.runtime === 'node' ? 'node:alpine' : 'python:alpine';\n const userData = `#!/bin/bash\napt-get update\napt-get install -y docker.io\nsystemctl start docker\nsystemctl enable docker\ndocker pull ${dockerImage}\ndocker run -d --name compute-app ${dockerImage} tail -f /dev/null`;\n\n const launchBody = {\n region_name: regionName,\n instance_type_name: instanceTypeName,\n ssh_key_names: [sshKeyName],\n name: `compute-${options?.runtime || 'node'}-instance`,\n user_data: userData\n };\n\n const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LAUNCH_INSTANCE, {\n method: 'POST',\n body: launchBody\n });\n \n // Lambda API returns instance_ids as an array\n const instanceIds = responseData?.data?.instance_ids;\n if (!instanceIds || !Array.isArray(instanceIds) || instanceIds.length === 0) {\n throw new Error(`No instance IDs returned from Lambda API. Full response: ${JSON.stringify(responseData)}`);\n }\n\n // Take the first instance ID (should only be one for single instance creation)\n const instanceId = instanceIds[0];\n\n const lambdaSandbox: LambdaSandbox = {\n instanceId,\n regionName,\n instanceTypeName,\n };\n\n return {\n sandbox: lambdaSandbox,\n sandboxId: instanceId\n };\n } catch (error) {\n throw new Error(\n `Failed to create Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: LambdaConfig, sandboxId: string) => {\n const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.GET_INSTANCE(sandboxId));\n \n // Lambda API returns the instance directly in data (single instance, not array)\n const instance = responseData?.data;\n if (!instance) {\n return null;\n }\n \n if (!instance.id) {\n throw new Error('Instance data is missing ID from Lambda response');\n }\n\n const lambdaSandbox: LambdaSandbox = {\n instanceId: instance.id,\n regionName,\n instanceTypeName,\n };\n\n return {\n sandbox: lambdaSandbox,\n sandboxId: instance.id\n };\n } catch (error) {\n // Return null for 404s (instance not found)\n if (error instanceof Error && (error.message.includes('404') || error.message.includes('Not Found'))) {\n return null;\n }\n throw new Error(\n `Failed to get Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n \n list: async (config: LambdaConfig) => {\n const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LIST_INSTANCES);\n \n // Lambda API returns instances directly in data array\n const instances = responseData?.data || [];\n \n if (!Array.isArray(instances)) {\n throw new Error(`Expected instances array, got: ${typeof instances}`);\n }\n \n // Transform each instance into the expected format\n const sandboxes = instances.map((instance: any) => {\n const lambdaSandbox: LambdaSandbox = {\n instanceId: instance.id,\n regionName,\n instanceTypeName,\n };\n\n return {\n sandbox: lambdaSandbox,\n sandboxId: instance.id\n };\n });\n\n return sandboxes;\n } catch (error) {\n throw new Error(\n `Failed to list Lambda sandboxes: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n destroy: async (config: LambdaConfig, sandboxId: string) => {\n const { apiKey } = getAndValidateCredentials(config);\n\n try {\n const terminateBody = {\n instance_ids: [sandboxId]\n };\n\n await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.TERMINATE_INSTANCES, {\n method: 'POST',\n body: terminateBody\n });\n } catch (error) {\n // For destroy operations, we typically don't throw if the instance is already gone\n console.warn(`Lambda destroy warning: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n // Instance operations (minimal stubs - not implemented yet)\n runCode: async (_sandbox: LambdaSandbox, _code: string, _runtime?: Runtime) => {\n throw new Error('Lambda runCode method not implemented yet');\n },\n\n runCommand: async (_sandbox: LambdaSandbox, _command: string, _args?: string[], _options?: RunCommandOptions) => {\n throw new Error('Lambda runCommand method not implemented yet');\n },\n\n getInfo: async (_sandbox: LambdaSandbox) => {\n throw new Error('Lambda getInfo method not implemented yet');\n },\n\n getUrl: async (_sandbox: LambdaSandbox, _options: { port: number; protocol?: string }) => {\n throw new Error('Lambda getUrl method not implemented yet');\n },\n\n },\n },\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,71 @@
1
+ import * as computesdk from 'computesdk';
2
+
3
+ /**
4
+ * Lambda Provider - Factory-based Implementation
5
+ *
6
+ * Curl Command to start instance with Node:Alpine
7
+ * curl --request POST \
8
+ --url 'https://cloud.lambda.ai/api/v1/instance-operations/launch' \
9
+ --header 'Authorization: Bearer LAMBDA_API_KEY' \
10
+ --header 'Content-Type: application/json' \
11
+ --data '{
12
+ "region_name": LAMBDA_REGION_NAME,
13
+ "instance_type_name": LAMBDA_INSTANCE_TYPE_NAME,
14
+ "ssh_key_names": ["LAMBDA_SSH_KEY_NAME"],
15
+ "name": "node-alpine-instance",
16
+ "user_data": "#!/bin/bash\napt-get update\napt-get install -y docker.io\nsystemctl start docker\nsystemctl enable docker\ndocker pull node:alpine\ndocker run -d --name node-app node:alpine tail -f /dev/null"
17
+ }'
18
+ *
19
+ * Curl Command to list instances
20
+ * curl --request GET \
21
+ --url 'https://cloud.lambda.ai/api/v1/instances' \
22
+ --header 'Authorization: Bearer LAMBDA_API_KEY'
23
+ *
24
+ * Curl Command to getById()
25
+ * curl --request GET \
26
+ --url 'https://cloud.lambda.ai/api/v1/instances/<INSTANCE-ID>' \
27
+ --header 'Authorization: Bearer LAMBDA_API_KEY'
28
+ *
29
+ * Curl Command to Destroy Instance (terminate)
30
+ * curl --request POST \
31
+ --url 'https://cloud.lambda.ai/api/v1/instance-operations/terminate' \
32
+ --header 'Authorization: Bearer LAMBDA_API_KEY' \
33
+ --header 'Content-Type: application/json' \
34
+ --data '{
35
+ "instance_ids": ["<YOUR-INSTANCE-ID>"]
36
+ }'
37
+ */
38
+ /**
39
+ * Lambda sandbox interface
40
+ */
41
+ interface LambdaSandbox {
42
+ instanceId: string;
43
+ regionName: string;
44
+ instanceTypeName: string;
45
+ }
46
+ interface LambdaConfig {
47
+ /** Lambda API key - if not provided, will fallback to LAMBDA_API_KEY environment variable */
48
+ apiKey?: string;
49
+ /** Lambda Region Name - if not provided, will fallback to LAMBDA_REGION_NAME environment variable */
50
+ regionName?: string;
51
+ /** Lambda Instance Type Name - if not provided, will fallback to LAMBDA_INSTANCE_TYPE_NAME environment variable */
52
+ instanceTypeName?: string;
53
+ /** Lambda SSH Key Name - if not provided, will fallback to LAMBDA_SSH_KEY_NAME environment variable */
54
+ sshKeyName?: string;
55
+ }
56
+ declare const getAndValidateCredentials: (config: LambdaConfig) => {
57
+ apiKey: string;
58
+ regionName: string;
59
+ instanceTypeName: string;
60
+ sshKeyName: string;
61
+ };
62
+ declare const fetchLambda: (apiKey: string, endpoint: string, options?: {
63
+ method?: string;
64
+ body?: any;
65
+ }) => Promise<any>;
66
+ /**
67
+ * Create a Lambda provider instance using the factory pattern
68
+ */
69
+ declare const lambda: (config: LambdaConfig) => computesdk.Provider<LambdaSandbox, any, any>;
70
+
71
+ export { type LambdaConfig, fetchLambda, getAndValidateCredentials, lambda };
@@ -0,0 +1,71 @@
1
+ import * as computesdk from 'computesdk';
2
+
3
+ /**
4
+ * Lambda Provider - Factory-based Implementation
5
+ *
6
+ * Curl Command to start instance with Node:Alpine
7
+ * curl --request POST \
8
+ --url 'https://cloud.lambda.ai/api/v1/instance-operations/launch' \
9
+ --header 'Authorization: Bearer LAMBDA_API_KEY' \
10
+ --header 'Content-Type: application/json' \
11
+ --data '{
12
+ "region_name": LAMBDA_REGION_NAME,
13
+ "instance_type_name": LAMBDA_INSTANCE_TYPE_NAME,
14
+ "ssh_key_names": ["LAMBDA_SSH_KEY_NAME"],
15
+ "name": "node-alpine-instance",
16
+ "user_data": "#!/bin/bash\napt-get update\napt-get install -y docker.io\nsystemctl start docker\nsystemctl enable docker\ndocker pull node:alpine\ndocker run -d --name node-app node:alpine tail -f /dev/null"
17
+ }'
18
+ *
19
+ * Curl Command to list instances
20
+ * curl --request GET \
21
+ --url 'https://cloud.lambda.ai/api/v1/instances' \
22
+ --header 'Authorization: Bearer LAMBDA_API_KEY'
23
+ *
24
+ * Curl Command to getById()
25
+ * curl --request GET \
26
+ --url 'https://cloud.lambda.ai/api/v1/instances/<INSTANCE-ID>' \
27
+ --header 'Authorization: Bearer LAMBDA_API_KEY'
28
+ *
29
+ * Curl Command to Destroy Instance (terminate)
30
+ * curl --request POST \
31
+ --url 'https://cloud.lambda.ai/api/v1/instance-operations/terminate' \
32
+ --header 'Authorization: Bearer LAMBDA_API_KEY' \
33
+ --header 'Content-Type: application/json' \
34
+ --data '{
35
+ "instance_ids": ["<YOUR-INSTANCE-ID>"]
36
+ }'
37
+ */
38
+ /**
39
+ * Lambda sandbox interface
40
+ */
41
+ interface LambdaSandbox {
42
+ instanceId: string;
43
+ regionName: string;
44
+ instanceTypeName: string;
45
+ }
46
+ interface LambdaConfig {
47
+ /** Lambda API key - if not provided, will fallback to LAMBDA_API_KEY environment variable */
48
+ apiKey?: string;
49
+ /** Lambda Region Name - if not provided, will fallback to LAMBDA_REGION_NAME environment variable */
50
+ regionName?: string;
51
+ /** Lambda Instance Type Name - if not provided, will fallback to LAMBDA_INSTANCE_TYPE_NAME environment variable */
52
+ instanceTypeName?: string;
53
+ /** Lambda SSH Key Name - if not provided, will fallback to LAMBDA_SSH_KEY_NAME environment variable */
54
+ sshKeyName?: string;
55
+ }
56
+ declare const getAndValidateCredentials: (config: LambdaConfig) => {
57
+ apiKey: string;
58
+ regionName: string;
59
+ instanceTypeName: string;
60
+ sshKeyName: string;
61
+ };
62
+ declare const fetchLambda: (apiKey: string, endpoint: string, options?: {
63
+ method?: string;
64
+ body?: any;
65
+ }) => Promise<any>;
66
+ /**
67
+ * Create a Lambda provider instance using the factory pattern
68
+ */
69
+ declare const lambda: (config: LambdaConfig) => computesdk.Provider<LambdaSandbox, any, any>;
70
+
71
+ export { type LambdaConfig, fetchLambda, getAndValidateCredentials, lambda };
package/dist/index.js ADDED
@@ -0,0 +1,202 @@
1
+ // src/index.ts
2
+ import { createProvider } from "computesdk";
3
+ var getAndValidateCredentials = (config) => {
4
+ const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.LAMBDA_API_KEY || "";
5
+ const regionName = config.regionName || typeof process !== "undefined" && process.env?.LAMBDA_REGION_NAME || "";
6
+ const instanceTypeName = config.instanceTypeName || typeof process !== "undefined" && process.env?.LAMBDA_INSTANCE_TYPE_NAME || "";
7
+ const sshKeyName = config.sshKeyName || typeof process !== "undefined" && process.env?.LAMBDA_SSH_KEY_NAME || "";
8
+ if (!apiKey) {
9
+ throw new Error(
10
+ "Missing Lambda API key. Provide apiKey in config or set LAMBDA_API_KEY environment variable."
11
+ );
12
+ }
13
+ if (!regionName) {
14
+ throw new Error(
15
+ "Missing Lambda Region Name. Provide regionName in config or set LAMBDA_REGION_NAME environment variable."
16
+ );
17
+ }
18
+ if (!instanceTypeName) {
19
+ throw new Error(
20
+ "Missing Lambda Instance Type Name. Provide instanceTypeName in config or set LAMBDA_INSTANCE_TYPE_NAME environment variable."
21
+ );
22
+ }
23
+ if (!sshKeyName) {
24
+ throw new Error(
25
+ "Missing Lambda SSH Key Name. Provide sshKeyName in config or set LAMBDA_SSH_KEY_NAME environment variable."
26
+ );
27
+ }
28
+ return { apiKey, regionName, instanceTypeName, sshKeyName };
29
+ };
30
+ var LAMBDA_API_ENDPOINTS = {
31
+ LAUNCH_INSTANCE: "https://cloud.lambda.ai/api/v1/instance-operations/launch",
32
+ LIST_INSTANCES: "https://cloud.lambda.ai/api/v1/instances",
33
+ GET_INSTANCE: (instanceId) => `https://cloud.lambda.ai/api/v1/instances/${instanceId}`,
34
+ TERMINATE_INSTANCES: "https://cloud.lambda.ai/api/v1/instance-operations/terminate"
35
+ };
36
+ var handleLambdaAPIError = (response, data) => {
37
+ if (!response.ok) {
38
+ let errorMessage;
39
+ if (data?.error) {
40
+ if (typeof data.error === "object" && data.error.message) {
41
+ errorMessage = `${data.error.message}${data.error.suggestion ? ` ${data.error.suggestion}` : ""} (${data.error.code || "unknown"})`;
42
+ } else {
43
+ errorMessage = JSON.stringify(data.error);
44
+ }
45
+ } else {
46
+ errorMessage = data?.message || `HTTP ${response.status} ${response.statusText}`;
47
+ }
48
+ throw new Error(`Lambda API error: ${errorMessage}`);
49
+ }
50
+ };
51
+ var fetchLambda = async (apiKey, endpoint, options = {}) => {
52
+ const { method = "GET", body } = options;
53
+ const response = await fetch(endpoint, {
54
+ method,
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ "Authorization": `Bearer ${apiKey}`
58
+ },
59
+ ...body ? { body: JSON.stringify(body) } : {}
60
+ });
61
+ const data = await response.json();
62
+ handleLambdaAPIError(response, data);
63
+ return data;
64
+ };
65
+ var lambda = createProvider({
66
+ name: "lambda",
67
+ methods: {
68
+ sandbox: {
69
+ // Collection operations (compute.sandbox.*)
70
+ create: async (config, options) => {
71
+ const { apiKey, regionName, instanceTypeName, sshKeyName } = getAndValidateCredentials(config);
72
+ try {
73
+ const dockerImage = options?.runtime === "node" ? "node:alpine" : "python:alpine";
74
+ const userData = `#!/bin/bash
75
+ apt-get update
76
+ apt-get install -y docker.io
77
+ systemctl start docker
78
+ systemctl enable docker
79
+ docker pull ${dockerImage}
80
+ docker run -d --name compute-app ${dockerImage} tail -f /dev/null`;
81
+ const launchBody = {
82
+ region_name: regionName,
83
+ instance_type_name: instanceTypeName,
84
+ ssh_key_names: [sshKeyName],
85
+ name: `compute-${options?.runtime || "node"}-instance`,
86
+ user_data: userData
87
+ };
88
+ const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LAUNCH_INSTANCE, {
89
+ method: "POST",
90
+ body: launchBody
91
+ });
92
+ const instanceIds = responseData?.data?.instance_ids;
93
+ if (!instanceIds || !Array.isArray(instanceIds) || instanceIds.length === 0) {
94
+ throw new Error(`No instance IDs returned from Lambda API. Full response: ${JSON.stringify(responseData)}`);
95
+ }
96
+ const instanceId = instanceIds[0];
97
+ const lambdaSandbox = {
98
+ instanceId,
99
+ regionName,
100
+ instanceTypeName
101
+ };
102
+ return {
103
+ sandbox: lambdaSandbox,
104
+ sandboxId: instanceId
105
+ };
106
+ } catch (error) {
107
+ throw new Error(
108
+ `Failed to create Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`
109
+ );
110
+ }
111
+ },
112
+ getById: async (config, sandboxId) => {
113
+ const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);
114
+ try {
115
+ const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.GET_INSTANCE(sandboxId));
116
+ const instance = responseData?.data;
117
+ if (!instance) {
118
+ return null;
119
+ }
120
+ if (!instance.id) {
121
+ throw new Error("Instance data is missing ID from Lambda response");
122
+ }
123
+ const lambdaSandbox = {
124
+ instanceId: instance.id,
125
+ regionName,
126
+ instanceTypeName
127
+ };
128
+ return {
129
+ sandbox: lambdaSandbox,
130
+ sandboxId: instance.id
131
+ };
132
+ } catch (error) {
133
+ if (error instanceof Error && (error.message.includes("404") || error.message.includes("Not Found"))) {
134
+ return null;
135
+ }
136
+ throw new Error(
137
+ `Failed to get Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`
138
+ );
139
+ }
140
+ },
141
+ list: async (config) => {
142
+ const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);
143
+ try {
144
+ const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LIST_INSTANCES);
145
+ const instances = responseData?.data || [];
146
+ if (!Array.isArray(instances)) {
147
+ throw new Error(`Expected instances array, got: ${typeof instances}`);
148
+ }
149
+ const sandboxes = instances.map((instance) => {
150
+ const lambdaSandbox = {
151
+ instanceId: instance.id,
152
+ regionName,
153
+ instanceTypeName
154
+ };
155
+ return {
156
+ sandbox: lambdaSandbox,
157
+ sandboxId: instance.id
158
+ };
159
+ });
160
+ return sandboxes;
161
+ } catch (error) {
162
+ throw new Error(
163
+ `Failed to list Lambda sandboxes: ${error instanceof Error ? error.message : String(error)}`
164
+ );
165
+ }
166
+ },
167
+ destroy: async (config, sandboxId) => {
168
+ const { apiKey } = getAndValidateCredentials(config);
169
+ try {
170
+ const terminateBody = {
171
+ instance_ids: [sandboxId]
172
+ };
173
+ await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.TERMINATE_INSTANCES, {
174
+ method: "POST",
175
+ body: terminateBody
176
+ });
177
+ } catch (error) {
178
+ console.warn(`Lambda destroy warning: ${error instanceof Error ? error.message : String(error)}`);
179
+ }
180
+ },
181
+ // Instance operations (minimal stubs - not implemented yet)
182
+ runCode: async (_sandbox, _code, _runtime) => {
183
+ throw new Error("Lambda runCode method not implemented yet");
184
+ },
185
+ runCommand: async (_sandbox, _command, _args, _options) => {
186
+ throw new Error("Lambda runCommand method not implemented yet");
187
+ },
188
+ getInfo: async (_sandbox) => {
189
+ throw new Error("Lambda getInfo method not implemented yet");
190
+ },
191
+ getUrl: async (_sandbox, _options) => {
192
+ throw new Error("Lambda getUrl method not implemented yet");
193
+ }
194
+ }
195
+ }
196
+ });
197
+ export {
198
+ fetchLambda,
199
+ getAndValidateCredentials,
200
+ lambda
201
+ };
202
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Lambda Provider - Factory-based Implementation\n * \n * Curl Command to start instance with Node:Alpine\n * curl --request POST \\\n --url 'https://cloud.lambda.ai/api/v1/instance-operations/launch' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"region_name\": LAMBDA_REGION_NAME,\n \"instance_type_name\": LAMBDA_INSTANCE_TYPE_NAME,\n \"ssh_key_names\": [\"LAMBDA_SSH_KEY_NAME\"],\n \"name\": \"node-alpine-instance\",\n \"user_data\": \"#!/bin/bash\\napt-get update\\napt-get install -y docker.io\\nsystemctl start docker\\nsystemctl enable docker\\ndocker pull node:alpine\\ndocker run -d --name node-app node:alpine tail -f /dev/null\"\n }'\n *\n * Curl Command to list instances\n * curl --request GET \\\n --url 'https://cloud.lambda.ai/api/v1/instances' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY'\n *\n * Curl Command to getById()\n * curl --request GET \\\n --url 'https://cloud.lambda.ai/api/v1/instances/<INSTANCE-ID>' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY'\n *\n * Curl Command to Destroy Instance (terminate)\n * curl --request POST \\\n --url 'https://cloud.lambda.ai/api/v1/instance-operations/terminate' \\\n --header 'Authorization: Bearer LAMBDA_API_KEY' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"instance_ids\": [\"<YOUR-INSTANCE-ID>\"]\n }'\n */\n\nimport { createProvider } from 'computesdk';\nimport type { Runtime, ExecutionResult, SandboxInfo, CreateSandboxOptions, FileEntry, RunCommandOptions } from 'computesdk';\n\n/**\n * Lambda sandbox interface\n */\ninterface LambdaSandbox {\n instanceId: string;\n regionName: string;\n instanceTypeName: string;\n}\n\nexport interface LambdaConfig {\n /** Lambda API key - if not provided, will fallback to LAMBDA_API_KEY environment variable */\n apiKey?: string;\n /** Lambda Region Name - if not provided, will fallback to LAMBDA_REGION_NAME environment variable */\n regionName?: string;\n /** Lambda Instance Type Name - if not provided, will fallback to LAMBDA_INSTANCE_TYPE_NAME environment variable */\n instanceTypeName?: string;\n /** Lambda SSH Key Name - if not provided, will fallback to LAMBDA_SSH_KEY_NAME environment variable */\n sshKeyName?: string;\n}\n\nexport const getAndValidateCredentials = (config: LambdaConfig) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.LAMBDA_API_KEY) || '';\n const regionName = config.regionName || (typeof process !== 'undefined' && process.env?.LAMBDA_REGION_NAME) || '';\n const instanceTypeName = config.instanceTypeName || (typeof process !== 'undefined' && process.env?.LAMBDA_INSTANCE_TYPE_NAME) || '';\n const sshKeyName = config.sshKeyName || (typeof process !== 'undefined' && process.env?.LAMBDA_SSH_KEY_NAME) || '';\n\n if (!apiKey) {\n throw new Error(\n 'Missing Lambda API key. Provide apiKey in config or set LAMBDA_API_KEY environment variable.'\n );\n }\n\n if (!regionName) {\n throw new Error(\n 'Missing Lambda Region Name. Provide regionName in config or set LAMBDA_REGION_NAME environment variable.'\n );\n }\n\n if (!instanceTypeName) {\n throw new Error(\n 'Missing Lambda Instance Type Name. Provide instanceTypeName in config or set LAMBDA_INSTANCE_TYPE_NAME environment variable.'\n );\n }\n\n if (!sshKeyName) {\n throw new Error(\n 'Missing Lambda SSH Key Name. Provide sshKeyName in config or set LAMBDA_SSH_KEY_NAME environment variable.'\n );\n }\n\n return { apiKey, regionName, instanceTypeName, sshKeyName };\n};\n\nconst LAMBDA_API_ENDPOINTS = {\n LAUNCH_INSTANCE: 'https://cloud.lambda.ai/api/v1/instance-operations/launch',\n LIST_INSTANCES: 'https://cloud.lambda.ai/api/v1/instances',\n GET_INSTANCE: (instanceId: string) => `https://cloud.lambda.ai/api/v1/instances/${instanceId}`,\n TERMINATE_INSTANCES: 'https://cloud.lambda.ai/api/v1/instance-operations/terminate'\n};\n\nconst handleLambdaAPIError = (response: Response, data?: any) => {\n if (!response.ok) {\n let errorMessage;\n if (data?.error) {\n // Handle Lambda API error format: { \"error\": { \"code\": \"...\", \"message\": \"...\", \"suggestion\": \"...\" } }\n if (typeof data.error === 'object' && data.error.message) {\n errorMessage = `${data.error.message}${data.error.suggestion ? ` ${data.error.suggestion}` : ''} (${data.error.code || 'unknown'})`;\n } else {\n errorMessage = JSON.stringify(data.error);\n }\n } else {\n errorMessage = data?.message || `HTTP ${response.status} ${response.statusText}`;\n }\n throw new Error(`Lambda API error: ${errorMessage}`);\n }\n};\n\n\nexport const fetchLambda = async (\n apiKey: string,\n endpoint: string,\n options: {\n method?: string;\n body?: any;\n } = {}\n) => {\n const { method = 'GET', body } = options;\n \n const response = await fetch(endpoint, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`\n },\n ...(body ? { body: JSON.stringify(body) } : {})\n });\n\n const data = await response.json();\n\n // Handle Lambda API errors\n handleLambdaAPIError(response, data);\n\n return data;\n};\n\n\n\n/**\n * Create a Lambda provider instance using the factory pattern\n */\nexport const lambda = createProvider<LambdaSandbox, LambdaConfig>({\n name: 'lambda',\n methods: {\n sandbox: {\n // Collection operations (compute.sandbox.*)\n create: async (config: LambdaConfig, options?: CreateSandboxOptions) => {\n const { apiKey, regionName, instanceTypeName, sshKeyName } = getAndValidateCredentials(config);\n\n try {\n const dockerImage = options?.runtime === 'node' ? 'node:alpine' : 'python:alpine';\n const userData = `#!/bin/bash\napt-get update\napt-get install -y docker.io\nsystemctl start docker\nsystemctl enable docker\ndocker pull ${dockerImage}\ndocker run -d --name compute-app ${dockerImage} tail -f /dev/null`;\n\n const launchBody = {\n region_name: regionName,\n instance_type_name: instanceTypeName,\n ssh_key_names: [sshKeyName],\n name: `compute-${options?.runtime || 'node'}-instance`,\n user_data: userData\n };\n\n const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LAUNCH_INSTANCE, {\n method: 'POST',\n body: launchBody\n });\n \n // Lambda API returns instance_ids as an array\n const instanceIds = responseData?.data?.instance_ids;\n if (!instanceIds || !Array.isArray(instanceIds) || instanceIds.length === 0) {\n throw new Error(`No instance IDs returned from Lambda API. Full response: ${JSON.stringify(responseData)}`);\n }\n\n // Take the first instance ID (should only be one for single instance creation)\n const instanceId = instanceIds[0];\n\n const lambdaSandbox: LambdaSandbox = {\n instanceId,\n regionName,\n instanceTypeName,\n };\n\n return {\n sandbox: lambdaSandbox,\n sandboxId: instanceId\n };\n } catch (error) {\n throw new Error(\n `Failed to create Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: LambdaConfig, sandboxId: string) => {\n const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.GET_INSTANCE(sandboxId));\n \n // Lambda API returns the instance directly in data (single instance, not array)\n const instance = responseData?.data;\n if (!instance) {\n return null;\n }\n \n if (!instance.id) {\n throw new Error('Instance data is missing ID from Lambda response');\n }\n\n const lambdaSandbox: LambdaSandbox = {\n instanceId: instance.id,\n regionName,\n instanceTypeName,\n };\n\n return {\n sandbox: lambdaSandbox,\n sandboxId: instance.id\n };\n } catch (error) {\n // Return null for 404s (instance not found)\n if (error instanceof Error && (error.message.includes('404') || error.message.includes('Not Found'))) {\n return null;\n }\n throw new Error(\n `Failed to get Lambda sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n \n list: async (config: LambdaConfig) => {\n const { apiKey, regionName, instanceTypeName } = getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.LIST_INSTANCES);\n \n // Lambda API returns instances directly in data array\n const instances = responseData?.data || [];\n \n if (!Array.isArray(instances)) {\n throw new Error(`Expected instances array, got: ${typeof instances}`);\n }\n \n // Transform each instance into the expected format\n const sandboxes = instances.map((instance: any) => {\n const lambdaSandbox: LambdaSandbox = {\n instanceId: instance.id,\n regionName,\n instanceTypeName,\n };\n\n return {\n sandbox: lambdaSandbox,\n sandboxId: instance.id\n };\n });\n\n return sandboxes;\n } catch (error) {\n throw new Error(\n `Failed to list Lambda sandboxes: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n destroy: async (config: LambdaConfig, sandboxId: string) => {\n const { apiKey } = getAndValidateCredentials(config);\n\n try {\n const terminateBody = {\n instance_ids: [sandboxId]\n };\n\n await fetchLambda(apiKey, LAMBDA_API_ENDPOINTS.TERMINATE_INSTANCES, {\n method: 'POST',\n body: terminateBody\n });\n } catch (error) {\n // For destroy operations, we typically don't throw if the instance is already gone\n console.warn(`Lambda destroy warning: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n // Instance operations (minimal stubs - not implemented yet)\n runCode: async (_sandbox: LambdaSandbox, _code: string, _runtime?: Runtime) => {\n throw new Error('Lambda runCode method not implemented yet');\n },\n\n runCommand: async (_sandbox: LambdaSandbox, _command: string, _args?: string[], _options?: RunCommandOptions) => {\n throw new Error('Lambda runCommand method not implemented yet');\n },\n\n getInfo: async (_sandbox: LambdaSandbox) => {\n throw new Error('Lambda getInfo method not implemented yet');\n },\n\n getUrl: async (_sandbox: LambdaSandbox, _options: { port: number; protocol?: string }) => {\n throw new Error('Lambda getUrl method not implemented yet');\n },\n\n },\n },\n});\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@computesdk/lambda",
3
+ "version": "1.0.0",
4
+ "description": "Lambda provider for ComputeSDK",
5
+ "author": "ComputeSDK Team",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.mjs",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "dependencies": {
22
+ "computesdk": "1.8.8"
23
+ },
24
+ "keywords": [
25
+ "lambda",
26
+ "sandbox",
27
+ "code-execution",
28
+ "cloud",
29
+ "compute",
30
+ "containers",
31
+ "gpu"
32
+ ],
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/computesdk/computesdk.git",
36
+ "directory": "packages/lambda"
37
+ },
38
+ "homepage": "https://github.com/computesdk/computesdk/tree/main/packages/lambda",
39
+ "bugs": {
40
+ "url": "https://github.com/computesdk/computesdk/issues"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^20.0.0",
44
+ "@vitest/coverage-v8": "^1.0.0",
45
+ "eslint": "^8.37.0",
46
+ "rimraf": "^5.0.0",
47
+ "tsup": "^8.0.0",
48
+ "typescript": "^5.0.0",
49
+ "vitest": "^1.0.0",
50
+ "@computesdk/test-utils": "1.4.1"
51
+ },
52
+ "scripts": {
53
+ "build": "tsup",
54
+ "clean": "rimraf dist",
55
+ "dev": "tsup --watch",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest watch",
58
+ "test:coverage": "vitest run --coverage",
59
+ "typecheck": "tsc --noEmit",
60
+ "lint": "eslint"
61
+ }
62
+ }