@computesdk/namespace 1.4.0 → 1.5.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/dist/index.d.mts CHANGED
@@ -1,12 +1,30 @@
1
- import * as computesdk from 'computesdk';
2
- import { ComputeConfig } from '@computesdk/provider';
1
+ import * as _computesdk_provider from '@computesdk/provider';
3
2
 
3
+ /**
4
+ * Namespace Provider
5
+ *
6
+ * Full-featured provider using the factory pattern.
7
+ * Supports instance lifecycle management and command execution via Namespace Compute API.
8
+ */
9
+ /**
10
+ * Namespace sandbox instance
11
+ */
12
+ interface NamespaceSandbox {
13
+ instanceId: string;
14
+ name: string;
15
+ commandServiceEndpoint?: string;
16
+ token: string;
17
+ targetContainerName: string;
18
+ createdAt: Date;
19
+ }
4
20
  /**
5
21
  * Namespace provider configuration
6
22
  */
7
- interface NamespaceConfig extends ComputeConfig {
23
+ interface NamespaceConfig {
8
24
  /** Namespace API token - if not provided, will fallback to NSC_TOKEN environment variable */
9
25
  token?: string;
26
+ /** Path to a JSON token file (e.g. from `nsc login`) containing bearer_token - fallback to NSC_TOKEN_FILE */
27
+ tokenFile?: string;
10
28
  /** Virtual CPU cores for the instance */
11
29
  virtualCpu?: number;
12
30
  /** Memory in megabytes for the instance */
@@ -19,37 +37,25 @@ interface NamespaceConfig extends ComputeConfig {
19
37
  documentedPurpose?: string;
20
38
  /** Reason for destroying instances (default: "ComputeSDK cleanup") */
21
39
  destroyReason?: string;
40
+ /** Target container name for command execution (default: "main-container") */
41
+ targetContainerName?: string;
22
42
  }
23
43
  /**
24
- * Namespace compute factory - creates configured compute instances
25
- *
26
- * Namespace is an infrastructure provider that becomes a full sandbox provider
27
- * via the ComputeSDK gateway. The gateway provisions Namespace instances with the
28
- * daemon pre-installed, enabling full sandbox capabilities.
29
- *
30
- * @example
31
- * ```typescript
32
- * import { namespace } from '@computesdk/namespace';
33
- *
34
- * const compute = namespace({
35
- * token: 'nsc_xxx'
36
- * });
37
- *
38
- * // Full compute API available (routes through gateway)
39
- * const sandbox = await compute.sandbox.create();
40
- *
41
- * // Execute code
42
- * const result = await sandbox.runCode('console.log("Hello from Namespace!")');
43
- * console.log(result.stdout);
44
- *
45
- * // Filesystem operations
46
- * await sandbox.filesystem.writeFile('/tmp/test.txt', 'Hello!');
47
- * const content = await sandbox.filesystem.readFile('/tmp/test.txt');
44
+ * Get and validate Namespace credentials from config and environment.
45
+ * Supports:
46
+ * - config.token (direct bearer token)
47
+ * - NSC_TOKEN env var (direct bearer token)
48
+ * - NSC_TOKEN_FILE env var (path to JSON file with bearer_token field)
49
+ */
50
+ declare const getAndValidateCredentials: (config: NamespaceConfig) => Promise<{
51
+ token: string;
52
+ }>;
53
+ declare const fetchNamespace: (token: string, endpoint: string, options?: RequestInit, baseUrl?: string) => Promise<any>;
54
+ /**
55
+ * Namespace provider
48
56
  *
49
- * // Cleanup
50
- * await sandbox.destroy();
51
- * ```
57
+ * Creates Namespace instances and supports command execution via CommandService.
52
58
  */
53
- declare const namespace: (config: NamespaceConfig) => computesdk.CallableCompute;
59
+ declare const namespace: (config: NamespaceConfig) => _computesdk_provider.Provider<NamespaceSandbox, any, any>;
54
60
 
55
- export { type NamespaceConfig, namespace };
61
+ export { type NamespaceConfig, type NamespaceSandbox, fetchNamespace, getAndValidateCredentials, namespace };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,30 @@
1
- import * as computesdk from 'computesdk';
2
- import { ComputeConfig } from '@computesdk/provider';
1
+ import * as _computesdk_provider from '@computesdk/provider';
3
2
 
3
+ /**
4
+ * Namespace Provider
5
+ *
6
+ * Full-featured provider using the factory pattern.
7
+ * Supports instance lifecycle management and command execution via Namespace Compute API.
8
+ */
9
+ /**
10
+ * Namespace sandbox instance
11
+ */
12
+ interface NamespaceSandbox {
13
+ instanceId: string;
14
+ name: string;
15
+ commandServiceEndpoint?: string;
16
+ token: string;
17
+ targetContainerName: string;
18
+ createdAt: Date;
19
+ }
4
20
  /**
5
21
  * Namespace provider configuration
6
22
  */
7
- interface NamespaceConfig extends ComputeConfig {
23
+ interface NamespaceConfig {
8
24
  /** Namespace API token - if not provided, will fallback to NSC_TOKEN environment variable */
9
25
  token?: string;
26
+ /** Path to a JSON token file (e.g. from `nsc login`) containing bearer_token - fallback to NSC_TOKEN_FILE */
27
+ tokenFile?: string;
10
28
  /** Virtual CPU cores for the instance */
11
29
  virtualCpu?: number;
12
30
  /** Memory in megabytes for the instance */
@@ -19,37 +37,25 @@ interface NamespaceConfig extends ComputeConfig {
19
37
  documentedPurpose?: string;
20
38
  /** Reason for destroying instances (default: "ComputeSDK cleanup") */
21
39
  destroyReason?: string;
40
+ /** Target container name for command execution (default: "main-container") */
41
+ targetContainerName?: string;
22
42
  }
23
43
  /**
24
- * Namespace compute factory - creates configured compute instances
25
- *
26
- * Namespace is an infrastructure provider that becomes a full sandbox provider
27
- * via the ComputeSDK gateway. The gateway provisions Namespace instances with the
28
- * daemon pre-installed, enabling full sandbox capabilities.
29
- *
30
- * @example
31
- * ```typescript
32
- * import { namespace } from '@computesdk/namespace';
33
- *
34
- * const compute = namespace({
35
- * token: 'nsc_xxx'
36
- * });
37
- *
38
- * // Full compute API available (routes through gateway)
39
- * const sandbox = await compute.sandbox.create();
40
- *
41
- * // Execute code
42
- * const result = await sandbox.runCode('console.log("Hello from Namespace!")');
43
- * console.log(result.stdout);
44
- *
45
- * // Filesystem operations
46
- * await sandbox.filesystem.writeFile('/tmp/test.txt', 'Hello!');
47
- * const content = await sandbox.filesystem.readFile('/tmp/test.txt');
44
+ * Get and validate Namespace credentials from config and environment.
45
+ * Supports:
46
+ * - config.token (direct bearer token)
47
+ * - NSC_TOKEN env var (direct bearer token)
48
+ * - NSC_TOKEN_FILE env var (path to JSON file with bearer_token field)
49
+ */
50
+ declare const getAndValidateCredentials: (config: NamespaceConfig) => Promise<{
51
+ token: string;
52
+ }>;
53
+ declare const fetchNamespace: (token: string, endpoint: string, options?: RequestInit, baseUrl?: string) => Promise<any>;
54
+ /**
55
+ * Namespace provider
48
56
  *
49
- * // Cleanup
50
- * await sandbox.destroy();
51
- * ```
57
+ * Creates Namespace instances and supports command execution via CommandService.
52
58
  */
53
- declare const namespace: (config: NamespaceConfig) => computesdk.CallableCompute;
59
+ declare const namespace: (config: NamespaceConfig) => _computesdk_provider.Provider<NamespaceSandbox, any, any>;
54
60
 
55
- export { type NamespaceConfig, namespace };
61
+ export { type NamespaceConfig, type NamespaceSandbox, fetchNamespace, getAndValidateCredentials, namespace };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,20 +17,300 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
33
+ fetchNamespace: () => fetchNamespace,
34
+ getAndValidateCredentials: () => getAndValidateCredentials,
23
35
  namespace: () => namespace
24
36
  });
25
37
  module.exports = __toCommonJS(index_exports);
38
+ var fs = __toESM(require("fs/promises"));
26
39
  var import_provider = require("@computesdk/provider");
27
- var namespace = (0, import_provider.defineCompute)({
28
- provider: "namespace"
40
+ var API_ENDPOINTS = {
41
+ CREATE_INSTANCE: "/namespace.cloud.compute.v1beta.ComputeService/CreateInstance",
42
+ DESCRIBE_INSTANCE: "/namespace.cloud.compute.v1beta.ComputeService/DescribeInstance",
43
+ LIST_INSTANCES: "/namespace.cloud.compute.v1beta.ComputeService/ListInstances",
44
+ DESTROY_INSTANCE: "/namespace.cloud.compute.v1beta.ComputeService/DestroyInstance"
45
+ };
46
+ var COMMAND_SERVICE = {
47
+ RUN_COMMAND_SYNC: "/namespace.cloud.compute.v1beta.CommandService/RunCommandSync"
48
+ };
49
+ async function loadTokenFromFile(filePath) {
50
+ const content = await fs.readFile(filePath, "utf8");
51
+ const tokenJson = JSON.parse(content);
52
+ if (!tokenJson.bearer_token) {
53
+ throw new Error(`Token file ${filePath} does not contain a bearer_token`);
54
+ }
55
+ return tokenJson.bearer_token;
56
+ }
57
+ var getAndValidateCredentials = async (config) => {
58
+ let token = config.token || typeof process !== "undefined" && process.env?.NSC_TOKEN || "";
59
+ if (!token) {
60
+ const tokenFile = config.tokenFile || typeof process !== "undefined" && process.env?.NSC_TOKEN_FILE || "";
61
+ if (tokenFile) {
62
+ token = await loadTokenFromFile(tokenFile);
63
+ }
64
+ }
65
+ if (!token) {
66
+ throw new Error(
67
+ "Missing Namespace token. Provide token in config, set NSC_TOKEN, or set NSC_TOKEN_FILE environment variable (or provide tokenFile in config)."
68
+ );
69
+ }
70
+ return { token };
71
+ };
72
+ var handleApiErrors = (response) => {
73
+ if (response.error) {
74
+ throw new Error(`Namespace API error: ${response.error}`);
75
+ }
76
+ };
77
+ var fetchNamespace = async (token, endpoint, options = {}, baseUrl = "https://us.compute.namespaceapis.com") => {
78
+ const response = await fetch(`${baseUrl}${endpoint}`, {
79
+ ...options,
80
+ headers: {
81
+ "Content-Type": "application/json",
82
+ "Authorization": `Bearer ${token}`,
83
+ ...options.headers
84
+ }
85
+ });
86
+ if (!response.ok) {
87
+ throw new Error(`Namespace API error: ${response.status} ${response.statusText}`);
88
+ }
89
+ const data = await response.json();
90
+ handleApiErrors(data);
91
+ return data;
92
+ };
93
+ var namespace = (0, import_provider.defineProvider)({
94
+ name: "namespace",
95
+ methods: {
96
+ sandbox: {
97
+ // Collection operations (map to compute.sandbox.*)
98
+ create: async (config, options) => {
99
+ const { token } = await getAndValidateCredentials(config);
100
+ const containerName = config.targetContainerName || "main-container";
101
+ try {
102
+ const requestBody = {
103
+ shape: {
104
+ virtual_cpu: config.virtualCpu || 2,
105
+ memory_megabytes: config.memoryMegabytes || 4096,
106
+ machine_arch: config.machineArch || "amd64",
107
+ os: config.os || "linux"
108
+ },
109
+ containers: [{
110
+ name: containerName,
111
+ image_ref: options?.image ?? "ubuntu:latest",
112
+ args: ["sleep", "infinity"],
113
+ ...options?.envs && Object.keys(options.envs).length > 0 && {
114
+ environment: options.envs
115
+ }
116
+ }],
117
+ documented_purpose: config.documentedPurpose || "ComputeSDK sandbox",
118
+ deadline: new Date(Date.now() + 60 * 60 * 1e3).toISOString()
119
+ };
120
+ const responseData = await fetchNamespace(token, API_ENDPOINTS.CREATE_INSTANCE, {
121
+ method: "POST",
122
+ body: JSON.stringify(requestBody)
123
+ });
124
+ if (!responseData.metadata?.instanceId) {
125
+ throw new Error(`Instance ID is undefined. Full response object: ${JSON.stringify(responseData, null, 2)}`);
126
+ }
127
+ const instanceId = responseData.metadata.instanceId;
128
+ const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;
129
+ const sandbox = {
130
+ instanceId,
131
+ name: `instance-${instanceId}`,
132
+ commandServiceEndpoint,
133
+ token,
134
+ targetContainerName: containerName,
135
+ createdAt: /* @__PURE__ */ new Date()
136
+ };
137
+ return {
138
+ sandbox,
139
+ sandboxId: instanceId
140
+ };
141
+ } catch (error) {
142
+ throw new Error(
143
+ `Failed to create Namespace instance: ${error instanceof Error ? error.message : String(error)}`
144
+ );
145
+ }
146
+ },
147
+ getById: async (config, sandboxId) => {
148
+ const { token } = await getAndValidateCredentials(config);
149
+ try {
150
+ const responseData = await fetchNamespace(token, API_ENDPOINTS.DESCRIBE_INSTANCE, {
151
+ method: "POST",
152
+ body: JSON.stringify({ instance_id: sandboxId })
153
+ });
154
+ if (!responseData.metadata?.instanceId) {
155
+ throw new Error("Instance data is missing from Namespace response");
156
+ }
157
+ const instanceId = responseData.metadata.instanceId;
158
+ const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;
159
+ const sandbox = {
160
+ instanceId,
161
+ name: `instance-${instanceId}`,
162
+ commandServiceEndpoint,
163
+ token,
164
+ targetContainerName: config.targetContainerName || "main-container",
165
+ createdAt: responseData.metadata?.createdAt ? new Date(responseData.metadata.createdAt) : /* @__PURE__ */ new Date(0)
166
+ };
167
+ return {
168
+ sandbox,
169
+ sandboxId: instanceId
170
+ };
171
+ } catch (error) {
172
+ if (error instanceof Error && error.message.includes("404")) {
173
+ return null;
174
+ }
175
+ throw new Error(
176
+ `Failed to get Namespace instance: ${error instanceof Error ? error.message : String(error)}`
177
+ );
178
+ }
179
+ },
180
+ list: async (config) => {
181
+ const { token } = await getAndValidateCredentials(config);
182
+ try {
183
+ const responseData = await fetchNamespace(token, API_ENDPOINTS.LIST_INSTANCES, {
184
+ method: "POST",
185
+ body: JSON.stringify({})
186
+ });
187
+ const instances = responseData?.instances || [];
188
+ return instances.filter((instanceData) => instanceData.instanceId || instanceData.metadata?.instanceId).map((instanceData) => {
189
+ const instanceId = instanceData.instanceId || instanceData.metadata.instanceId;
190
+ const commandServiceEndpoint = instanceData.extendedMetadata?.commandServiceEndpoint;
191
+ const sandbox = {
192
+ instanceId,
193
+ name: `instance-${instanceId}`,
194
+ commandServiceEndpoint,
195
+ token,
196
+ targetContainerName: config.targetContainerName || "main-container",
197
+ createdAt: instanceData.metadata?.createdAt ? new Date(instanceData.metadata.createdAt) : /* @__PURE__ */ new Date(0)
198
+ };
199
+ return {
200
+ sandbox,
201
+ sandboxId: instanceId
202
+ };
203
+ });
204
+ } catch (error) {
205
+ throw new Error(
206
+ `Failed to list Namespace instances: ${error instanceof Error ? error.message : String(error)}`
207
+ );
208
+ }
209
+ },
210
+ destroy: async (config, sandboxId) => {
211
+ const { token } = await getAndValidateCredentials(config);
212
+ try {
213
+ const data = await fetchNamespace(token, API_ENDPOINTS.DESTROY_INSTANCE, {
214
+ method: "POST",
215
+ body: JSON.stringify({
216
+ instance_id: sandboxId,
217
+ reason: config.destroyReason || "ComputeSDK cleanup"
218
+ })
219
+ });
220
+ if (data.error) {
221
+ console.warn(`Namespace destroy warning: ${data.error}`);
222
+ }
223
+ } catch (error) {
224
+ console.warn(`Namespace destroy warning: ${error instanceof Error ? error.message : String(error)}`);
225
+ }
226
+ },
227
+ // Command execution via Namespace CommandService
228
+ runCommand: async (sandbox, command, options) => {
229
+ if (!sandbox.commandServiceEndpoint) {
230
+ throw new Error("Command service endpoint not available. The instance may not support command execution.");
231
+ }
232
+ const startTime = Date.now();
233
+ try {
234
+ let fullCommand = command;
235
+ if (options?.env && Object.keys(options.env).length > 0) {
236
+ const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}=${(0, import_provider.escapeShellArg)(v)}`).join(" ");
237
+ fullCommand = `${envPrefix} ${fullCommand}`;
238
+ }
239
+ if (options?.cwd) {
240
+ fullCommand = `cd ${(0, import_provider.escapeShellArg)(options.cwd)} && ${fullCommand}`;
241
+ }
242
+ if (options?.background) {
243
+ fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
244
+ }
245
+ const result = await fetchNamespace(
246
+ sandbox.token,
247
+ COMMAND_SERVICE.RUN_COMMAND_SYNC,
248
+ {
249
+ method: "POST",
250
+ body: JSON.stringify({
251
+ instanceId: sandbox.instanceId,
252
+ targetContainerName: sandbox.targetContainerName,
253
+ command: {
254
+ command: ["sh", "-c", fullCommand]
255
+ }
256
+ })
257
+ },
258
+ sandbox.commandServiceEndpoint
259
+ );
260
+ const decodeBase64 = (data) => {
261
+ if (!data) return "";
262
+ try {
263
+ return Buffer.from(data, "base64").toString();
264
+ } catch {
265
+ return data;
266
+ }
267
+ };
268
+ const stdout = decodeBase64(result.stdout);
269
+ const stderr = decodeBase64(result.stderr);
270
+ return {
271
+ stdout,
272
+ stderr,
273
+ exitCode: result.exitCode ?? 0,
274
+ durationMs: Date.now() - startTime
275
+ };
276
+ } catch (error) {
277
+ throw new Error(
278
+ `Namespace command execution failed: ${error instanceof Error ? error.message : String(error)}`
279
+ );
280
+ }
281
+ },
282
+ // Not supported - throw as no-op
283
+ runCode: async (_sandbox, _code, _runtime, _config) => {
284
+ throw new Error("Namespace provider does not support runCode. Use runCommand instead.");
285
+ },
286
+ getInfo: async (sandbox) => {
287
+ return {
288
+ id: sandbox.instanceId,
289
+ provider: "namespace",
290
+ runtime: "node",
291
+ status: "running",
292
+ createdAt: sandbox.createdAt,
293
+ timeout: 0,
294
+ metadata: {
295
+ name: sandbox.name,
296
+ commandServiceEndpoint: sandbox.commandServiceEndpoint
297
+ }
298
+ };
299
+ },
300
+ // Not supported - throw as no-op
301
+ getUrl: async (_sandbox, _options) => {
302
+ throw new Error("Namespace provider does not support getUrl.");
303
+ },
304
+ getInstance: (sandbox) => {
305
+ return sandbox;
306
+ }
307
+ }
308
+ }
29
309
  });
30
310
  // Annotate the CommonJS export names for ESM import in node:
31
311
  0 && (module.exports = {
312
+ fetchNamespace,
313
+ getAndValidateCredentials,
32
314
  namespace
33
315
  });
34
316
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Namespace Provider - Compute Factory\n *\n * Provides a first-class Namespace provider experience by routing all operations\n * through the ComputeSDK gateway. The gateway handles infrastructure provisioning\n * via @computesdk/gateway and installs the daemon for full sandbox capabilities.\n */\n\nimport { defineCompute, type ComputeConfig } from '@computesdk/provider';\n\n/**\n * Namespace provider configuration\n */\nexport interface NamespaceConfig extends ComputeConfig {\n /** Namespace API token - if not provided, will fallback to NSC_TOKEN environment variable */\n token?: string;\n /** Virtual CPU cores for the instance */\n virtualCpu?: number;\n /** Memory in megabytes for the instance */\n memoryMegabytes?: number;\n /** Machine architecture (default: amd64) */\n machineArch?: string;\n /** Operating system (default: linux) */\n os?: string;\n /** Documented purpose for the instance */\n documentedPurpose?: string;\n /** Reason for destroying instances (default: \"ComputeSDK cleanup\") */\n destroyReason?: string;\n}\n\n/**\n * Namespace compute factory - creates configured compute instances\n *\n * Namespace is an infrastructure provider that becomes a full sandbox provider\n * via the ComputeSDK gateway. The gateway provisions Namespace instances with the\n * daemon pre-installed, enabling full sandbox capabilities.\n *\n * @example\n * ```typescript\n * import { namespace } from '@computesdk/namespace';\n *\n * const compute = namespace({\n * token: 'nsc_xxx'\n * });\n *\n * // Full compute API available (routes through gateway)\n * const sandbox = await compute.sandbox.create();\n *\n * // Execute code\n * const result = await sandbox.runCode('console.log(\"Hello from Namespace!\")');\n * console.log(result.stdout);\n *\n * // Filesystem operations\n * await sandbox.filesystem.writeFile('/tmp/test.txt', 'Hello!');\n * const content = await sandbox.filesystem.readFile('/tmp/test.txt');\n *\n * // Cleanup\n * await sandbox.destroy();\n * ```\n */\nexport const namespace = defineCompute<NamespaceConfig>({\n provider: 'namespace'\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAAkD;AAoD3C,IAAM,gBAAY,+BAA+B;AAAA,EACtD,UAAU;AACZ,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Namespace Provider\n *\n * Full-featured provider using the factory pattern.\n * Supports instance lifecycle management and command execution via Namespace Compute API.\n */\n\nimport * as fs from 'fs/promises';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\nimport type { Runtime, CodeResult, CommandResult, SandboxInfo, CreateSandboxOptions, RunCommandOptions } from '@computesdk/provider';\n\n/**\n * Namespace sandbox instance\n */\nexport interface NamespaceSandbox {\n instanceId: string;\n name: string;\n commandServiceEndpoint?: string;\n token: string;\n targetContainerName: string;\n createdAt: Date;\n}\n\n/**\n * Namespace provider configuration\n */\nexport interface NamespaceConfig {\n /** Namespace API token - if not provided, will fallback to NSC_TOKEN environment variable */\n token?: string;\n /** Path to a JSON token file (e.g. from `nsc login`) containing bearer_token - fallback to NSC_TOKEN_FILE */\n tokenFile?: string;\n /** Virtual CPU cores for the instance */\n virtualCpu?: number;\n /** Memory in megabytes for the instance */\n memoryMegabytes?: number;\n /** Machine architecture (default: amd64) */\n machineArch?: string;\n /** Operating system (default: linux) */\n os?: string;\n /** Documented purpose for the instance */\n documentedPurpose?: string;\n /** Reason for destroying instances (default: \"ComputeSDK cleanup\") */\n destroyReason?: string;\n /** Target container name for command execution (default: \"main-container\") */\n targetContainerName?: string;\n}\n\nconst API_ENDPOINTS = {\n CREATE_INSTANCE: '/namespace.cloud.compute.v1beta.ComputeService/CreateInstance',\n DESCRIBE_INSTANCE: '/namespace.cloud.compute.v1beta.ComputeService/DescribeInstance',\n LIST_INSTANCES: '/namespace.cloud.compute.v1beta.ComputeService/ListInstances',\n DESTROY_INSTANCE: '/namespace.cloud.compute.v1beta.ComputeService/DestroyInstance'\n};\n\nconst COMMAND_SERVICE = {\n RUN_COMMAND_SYNC: '/namespace.cloud.compute.v1beta.CommandService/RunCommandSync',\n};\n\n/**\n * Load bearer token from a JSON token file (e.g. from `nsc login`)\n */\nasync function loadTokenFromFile(filePath: string): Promise<string> {\n const content = await fs.readFile(filePath, 'utf8');\n const tokenJson: { bearer_token?: string } = JSON.parse(content);\n if (!tokenJson.bearer_token) {\n throw new Error(`Token file ${filePath} does not contain a bearer_token`);\n }\n return tokenJson.bearer_token;\n}\n\n/**\n * Get and validate Namespace credentials from config and environment.\n * Supports:\n * - config.token (direct bearer token)\n * - NSC_TOKEN env var (direct bearer token)\n * - NSC_TOKEN_FILE env var (path to JSON file with bearer_token field)\n */\nexport const getAndValidateCredentials = async (config: NamespaceConfig) => {\n // 1. Direct token from config or env\n let token = config.token || (typeof process !== 'undefined' && process.env?.NSC_TOKEN) || '';\n\n // 2. If no direct token, try loading from token file\n if (!token) {\n const tokenFile = config.tokenFile || (typeof process !== 'undefined' && process.env?.NSC_TOKEN_FILE) || '';\n if (tokenFile) {\n token = await loadTokenFromFile(tokenFile);\n }\n }\n\n if (!token) {\n throw new Error(\n 'Missing Namespace token. Provide token in config, set NSC_TOKEN, or set NSC_TOKEN_FILE environment variable (or provide tokenFile in config).'\n );\n }\n\n return { token };\n};\n\nconst handleApiErrors = (response: any) => {\n if (response.error) {\n throw new Error(`Namespace API error: ${response.error}`);\n }\n};\n\nexport const fetchNamespace = async (\n token: string,\n endpoint: string,\n options: RequestInit = {},\n baseUrl: string = 'https://us.compute.namespaceapis.com'\n) => {\n const response = await fetch(`${baseUrl}${endpoint}`, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n ...options.headers\n }\n });\n\n if (!response.ok) {\n throw new Error(`Namespace API error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n // Standard error handling for all operations\n handleApiErrors(data);\n\n return data;\n};\n\n/**\n * Namespace provider\n *\n * Creates Namespace instances and supports command execution via CommandService.\n */\nexport const namespace = defineProvider<NamespaceSandbox, NamespaceConfig>({\n name: 'namespace',\n\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: NamespaceConfig, options?: CreateSandboxOptions) => {\n const { token } = await getAndValidateCredentials(config);\n const containerName = config.targetContainerName || 'main-container';\n\n try {\n const requestBody = {\n shape: {\n virtual_cpu: config.virtualCpu || 2,\n memory_megabytes: config.memoryMegabytes || 4096,\n machine_arch: config.machineArch || 'amd64',\n os: config.os || 'linux'\n },\n containers: [{\n name: containerName,\n image_ref: options?.image ?? 'ubuntu:latest',\n args: ['sleep', 'infinity'],\n ...(options?.envs && Object.keys(options.envs).length > 0 && {\n environment: options.envs\n })\n }],\n documented_purpose: config.documentedPurpose || 'ComputeSDK sandbox',\n deadline: new Date(Date.now() + 60 * 60 * 1000).toISOString()\n };\n\n const responseData = await fetchNamespace(token, API_ENDPOINTS.CREATE_INSTANCE, {\n method: 'POST',\n body: JSON.stringify(requestBody)\n });\n\n // Extract instance ID from the Namespace API response structure\n if (!responseData.metadata?.instanceId) {\n throw new Error(`Instance ID is undefined. Full response object: ${JSON.stringify(responseData, null, 2)}`);\n }\n\n const instanceId = responseData.metadata.instanceId;\n const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;\n\n const sandbox: NamespaceSandbox = {\n instanceId,\n name: `instance-${instanceId}`,\n commandServiceEndpoint,\n token,\n targetContainerName: containerName,\n createdAt: new Date(),\n };\n\n return {\n sandbox,\n sandboxId: instanceId\n };\n } catch (error) {\n throw new Error(\n `Failed to create Namespace instance: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: NamespaceConfig, sandboxId: string) => {\n const { token } = await getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchNamespace(token, API_ENDPOINTS.DESCRIBE_INSTANCE, {\n method: 'POST',\n body: JSON.stringify({ instance_id: sandboxId })\n });\n\n // Extract instance ID from the Namespace API response structure\n if (!responseData.metadata?.instanceId) {\n throw new Error('Instance data is missing from Namespace response');\n }\n\n const instanceId = responseData.metadata.instanceId;\n const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;\n\n const sandbox: NamespaceSandbox = {\n instanceId,\n name: `instance-${instanceId}`,\n commandServiceEndpoint,\n token,\n targetContainerName: config.targetContainerName || 'main-container',\n createdAt: responseData.metadata?.createdAt ? new Date(responseData.metadata.createdAt) : new Date(0),\n };\n\n return {\n sandbox,\n sandboxId: instanceId\n };\n } catch (error) {\n // Handle 404 errors by returning null (instance not found)\n if (error instanceof Error && error.message.includes('404')) {\n return null;\n }\n\n throw new Error(\n `Failed to get Namespace instance: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n list: async (config: NamespaceConfig) => {\n const { token } = await getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchNamespace(token, API_ENDPOINTS.LIST_INSTANCES, {\n method: 'POST',\n body: JSON.stringify({})\n });\n\n // Extract instances from the response\n const instances = responseData?.instances || [];\n\n // Filter to instances with valid IDs, then transform\n return instances\n .filter((instanceData: any) => instanceData.instanceId || instanceData.metadata?.instanceId)\n .map((instanceData: any) => {\n const instanceId = instanceData.instanceId || instanceData.metadata.instanceId;\n const commandServiceEndpoint = instanceData.extendedMetadata?.commandServiceEndpoint;\n\n const sandbox: NamespaceSandbox = {\n instanceId,\n name: `instance-${instanceId}`,\n commandServiceEndpoint,\n token,\n targetContainerName: config.targetContainerName || 'main-container',\n createdAt: instanceData.metadata?.createdAt ? new Date(instanceData.metadata.createdAt) : new Date(0),\n };\n\n return {\n sandbox,\n sandboxId: instanceId\n };\n });\n } catch (error) {\n throw new Error(\n `Failed to list Namespace instances: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n destroy: async (config: NamespaceConfig, sandboxId: string) => {\n const { token } = await getAndValidateCredentials(config);\n\n try {\n const data = await fetchNamespace(token, API_ENDPOINTS.DESTROY_INSTANCE, {\n method: 'POST',\n body: JSON.stringify({\n instance_id: sandboxId,\n reason: config.destroyReason || \"ComputeSDK cleanup\"\n })\n });\n\n if (data.error) {\n // Log errors but don't throw for destroy operations\n console.warn(`Namespace destroy warning: ${data.error}`);\n }\n } catch (error) {\n // For destroy operations, we log warnings rather than throwing\n // since the resource may already be gone\n console.warn(`Namespace destroy warning: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n // Command execution via Namespace CommandService\n runCommand: async (sandbox: NamespaceSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n if (!sandbox.commandServiceEndpoint) {\n throw new Error('Command service endpoint not available. The instance may not support command execution.');\n }\n\n const startTime = Date.now();\n\n try {\n // Build the full command with options\n let fullCommand = command;\n\n // Handle environment variables\n if (options?.env && Object.keys(options.env).length > 0) {\n const envPrefix = Object.entries(options.env)\n .map(([k, v]) => `${k}=${escapeShellArg(v)}`)\n .join(' ');\n fullCommand = `${envPrefix} ${fullCommand}`;\n }\n\n // Handle working directory\n if (options?.cwd) {\n fullCommand = `cd ${escapeShellArg(options.cwd)} && ${fullCommand}`;\n }\n\n // Handle background execution\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n // Call CommandService RunCommandSync via Connect protocol\n const result = await fetchNamespace(\n sandbox.token,\n COMMAND_SERVICE.RUN_COMMAND_SYNC,\n {\n method: 'POST',\n body: JSON.stringify({\n instanceId: sandbox.instanceId,\n targetContainerName: sandbox.targetContainerName,\n command: {\n command: ['sh', '-c', fullCommand],\n },\n })\n },\n sandbox.commandServiceEndpoint\n ) as {\n stdout?: string; // base64-encoded\n stderr?: string; // base64-encoded\n exitCode?: number;\n };\n\n // Decode base64-encoded stdout/stderr, falling back to raw string on invalid data\n const decodeBase64 = (data?: string): string => {\n if (!data) return '';\n try {\n return Buffer.from(data, 'base64').toString();\n } catch {\n return data;\n }\n };\n const stdout = decodeBase64(result.stdout);\n const stderr = decodeBase64(result.stderr);\n\n return {\n stdout,\n stderr,\n exitCode: result.exitCode ?? 0,\n durationMs: Date.now() - startTime\n };\n } catch (error) {\n // Re-throw infrastructure errors (network, auth, API) so they propagate\n // rather than being masked as command execution failures\n throw new Error(\n `Namespace command execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Not supported - throw as no-op\n runCode: async (_sandbox: NamespaceSandbox, _code: string, _runtime?: Runtime, _config?: NamespaceConfig): Promise<CodeResult> => {\n throw new Error('Namespace provider does not support runCode. Use runCommand instead.');\n },\n\n getInfo: async (sandbox: NamespaceSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.instanceId,\n provider: 'namespace',\n runtime: 'node',\n status: 'running',\n createdAt: sandbox.createdAt,\n timeout: 0,\n metadata: {\n name: sandbox.name,\n commandServiceEndpoint: sandbox.commandServiceEndpoint,\n }\n };\n },\n\n // Not supported - throw as no-op\n getUrl: async (_sandbox: NamespaceSandbox, _options: { port: number; protocol?: string }): Promise<string> => {\n throw new Error('Namespace provider does not support getUrl.');\n },\n\n getInstance: (sandbox: NamespaceSandbox): NamespaceSandbox => {\n return sandbox;\n },\n }\n }\n});\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,279 @@
1
1
  // src/index.ts
2
- import { defineCompute } from "@computesdk/provider";
3
- var namespace = defineCompute({
4
- provider: "namespace"
2
+ import * as fs from "fs/promises";
3
+ import { defineProvider, escapeShellArg } from "@computesdk/provider";
4
+ var API_ENDPOINTS = {
5
+ CREATE_INSTANCE: "/namespace.cloud.compute.v1beta.ComputeService/CreateInstance",
6
+ DESCRIBE_INSTANCE: "/namespace.cloud.compute.v1beta.ComputeService/DescribeInstance",
7
+ LIST_INSTANCES: "/namespace.cloud.compute.v1beta.ComputeService/ListInstances",
8
+ DESTROY_INSTANCE: "/namespace.cloud.compute.v1beta.ComputeService/DestroyInstance"
9
+ };
10
+ var COMMAND_SERVICE = {
11
+ RUN_COMMAND_SYNC: "/namespace.cloud.compute.v1beta.CommandService/RunCommandSync"
12
+ };
13
+ async function loadTokenFromFile(filePath) {
14
+ const content = await fs.readFile(filePath, "utf8");
15
+ const tokenJson = JSON.parse(content);
16
+ if (!tokenJson.bearer_token) {
17
+ throw new Error(`Token file ${filePath} does not contain a bearer_token`);
18
+ }
19
+ return tokenJson.bearer_token;
20
+ }
21
+ var getAndValidateCredentials = async (config) => {
22
+ let token = config.token || typeof process !== "undefined" && process.env?.NSC_TOKEN || "";
23
+ if (!token) {
24
+ const tokenFile = config.tokenFile || typeof process !== "undefined" && process.env?.NSC_TOKEN_FILE || "";
25
+ if (tokenFile) {
26
+ token = await loadTokenFromFile(tokenFile);
27
+ }
28
+ }
29
+ if (!token) {
30
+ throw new Error(
31
+ "Missing Namespace token. Provide token in config, set NSC_TOKEN, or set NSC_TOKEN_FILE environment variable (or provide tokenFile in config)."
32
+ );
33
+ }
34
+ return { token };
35
+ };
36
+ var handleApiErrors = (response) => {
37
+ if (response.error) {
38
+ throw new Error(`Namespace API error: ${response.error}`);
39
+ }
40
+ };
41
+ var fetchNamespace = async (token, endpoint, options = {}, baseUrl = "https://us.compute.namespaceapis.com") => {
42
+ const response = await fetch(`${baseUrl}${endpoint}`, {
43
+ ...options,
44
+ headers: {
45
+ "Content-Type": "application/json",
46
+ "Authorization": `Bearer ${token}`,
47
+ ...options.headers
48
+ }
49
+ });
50
+ if (!response.ok) {
51
+ throw new Error(`Namespace API error: ${response.status} ${response.statusText}`);
52
+ }
53
+ const data = await response.json();
54
+ handleApiErrors(data);
55
+ return data;
56
+ };
57
+ var namespace = defineProvider({
58
+ name: "namespace",
59
+ methods: {
60
+ sandbox: {
61
+ // Collection operations (map to compute.sandbox.*)
62
+ create: async (config, options) => {
63
+ const { token } = await getAndValidateCredentials(config);
64
+ const containerName = config.targetContainerName || "main-container";
65
+ try {
66
+ const requestBody = {
67
+ shape: {
68
+ virtual_cpu: config.virtualCpu || 2,
69
+ memory_megabytes: config.memoryMegabytes || 4096,
70
+ machine_arch: config.machineArch || "amd64",
71
+ os: config.os || "linux"
72
+ },
73
+ containers: [{
74
+ name: containerName,
75
+ image_ref: options?.image ?? "ubuntu:latest",
76
+ args: ["sleep", "infinity"],
77
+ ...options?.envs && Object.keys(options.envs).length > 0 && {
78
+ environment: options.envs
79
+ }
80
+ }],
81
+ documented_purpose: config.documentedPurpose || "ComputeSDK sandbox",
82
+ deadline: new Date(Date.now() + 60 * 60 * 1e3).toISOString()
83
+ };
84
+ const responseData = await fetchNamespace(token, API_ENDPOINTS.CREATE_INSTANCE, {
85
+ method: "POST",
86
+ body: JSON.stringify(requestBody)
87
+ });
88
+ if (!responseData.metadata?.instanceId) {
89
+ throw new Error(`Instance ID is undefined. Full response object: ${JSON.stringify(responseData, null, 2)}`);
90
+ }
91
+ const instanceId = responseData.metadata.instanceId;
92
+ const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;
93
+ const sandbox = {
94
+ instanceId,
95
+ name: `instance-${instanceId}`,
96
+ commandServiceEndpoint,
97
+ token,
98
+ targetContainerName: containerName,
99
+ createdAt: /* @__PURE__ */ new Date()
100
+ };
101
+ return {
102
+ sandbox,
103
+ sandboxId: instanceId
104
+ };
105
+ } catch (error) {
106
+ throw new Error(
107
+ `Failed to create Namespace instance: ${error instanceof Error ? error.message : String(error)}`
108
+ );
109
+ }
110
+ },
111
+ getById: async (config, sandboxId) => {
112
+ const { token } = await getAndValidateCredentials(config);
113
+ try {
114
+ const responseData = await fetchNamespace(token, API_ENDPOINTS.DESCRIBE_INSTANCE, {
115
+ method: "POST",
116
+ body: JSON.stringify({ instance_id: sandboxId })
117
+ });
118
+ if (!responseData.metadata?.instanceId) {
119
+ throw new Error("Instance data is missing from Namespace response");
120
+ }
121
+ const instanceId = responseData.metadata.instanceId;
122
+ const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;
123
+ const sandbox = {
124
+ instanceId,
125
+ name: `instance-${instanceId}`,
126
+ commandServiceEndpoint,
127
+ token,
128
+ targetContainerName: config.targetContainerName || "main-container",
129
+ createdAt: responseData.metadata?.createdAt ? new Date(responseData.metadata.createdAt) : /* @__PURE__ */ new Date(0)
130
+ };
131
+ return {
132
+ sandbox,
133
+ sandboxId: instanceId
134
+ };
135
+ } catch (error) {
136
+ if (error instanceof Error && error.message.includes("404")) {
137
+ return null;
138
+ }
139
+ throw new Error(
140
+ `Failed to get Namespace instance: ${error instanceof Error ? error.message : String(error)}`
141
+ );
142
+ }
143
+ },
144
+ list: async (config) => {
145
+ const { token } = await getAndValidateCredentials(config);
146
+ try {
147
+ const responseData = await fetchNamespace(token, API_ENDPOINTS.LIST_INSTANCES, {
148
+ method: "POST",
149
+ body: JSON.stringify({})
150
+ });
151
+ const instances = responseData?.instances || [];
152
+ return instances.filter((instanceData) => instanceData.instanceId || instanceData.metadata?.instanceId).map((instanceData) => {
153
+ const instanceId = instanceData.instanceId || instanceData.metadata.instanceId;
154
+ const commandServiceEndpoint = instanceData.extendedMetadata?.commandServiceEndpoint;
155
+ const sandbox = {
156
+ instanceId,
157
+ name: `instance-${instanceId}`,
158
+ commandServiceEndpoint,
159
+ token,
160
+ targetContainerName: config.targetContainerName || "main-container",
161
+ createdAt: instanceData.metadata?.createdAt ? new Date(instanceData.metadata.createdAt) : /* @__PURE__ */ new Date(0)
162
+ };
163
+ return {
164
+ sandbox,
165
+ sandboxId: instanceId
166
+ };
167
+ });
168
+ } catch (error) {
169
+ throw new Error(
170
+ `Failed to list Namespace instances: ${error instanceof Error ? error.message : String(error)}`
171
+ );
172
+ }
173
+ },
174
+ destroy: async (config, sandboxId) => {
175
+ const { token } = await getAndValidateCredentials(config);
176
+ try {
177
+ const data = await fetchNamespace(token, API_ENDPOINTS.DESTROY_INSTANCE, {
178
+ method: "POST",
179
+ body: JSON.stringify({
180
+ instance_id: sandboxId,
181
+ reason: config.destroyReason || "ComputeSDK cleanup"
182
+ })
183
+ });
184
+ if (data.error) {
185
+ console.warn(`Namespace destroy warning: ${data.error}`);
186
+ }
187
+ } catch (error) {
188
+ console.warn(`Namespace destroy warning: ${error instanceof Error ? error.message : String(error)}`);
189
+ }
190
+ },
191
+ // Command execution via Namespace CommandService
192
+ runCommand: async (sandbox, command, options) => {
193
+ if (!sandbox.commandServiceEndpoint) {
194
+ throw new Error("Command service endpoint not available. The instance may not support command execution.");
195
+ }
196
+ const startTime = Date.now();
197
+ try {
198
+ let fullCommand = command;
199
+ if (options?.env && Object.keys(options.env).length > 0) {
200
+ const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}=${escapeShellArg(v)}`).join(" ");
201
+ fullCommand = `${envPrefix} ${fullCommand}`;
202
+ }
203
+ if (options?.cwd) {
204
+ fullCommand = `cd ${escapeShellArg(options.cwd)} && ${fullCommand}`;
205
+ }
206
+ if (options?.background) {
207
+ fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
208
+ }
209
+ const result = await fetchNamespace(
210
+ sandbox.token,
211
+ COMMAND_SERVICE.RUN_COMMAND_SYNC,
212
+ {
213
+ method: "POST",
214
+ body: JSON.stringify({
215
+ instanceId: sandbox.instanceId,
216
+ targetContainerName: sandbox.targetContainerName,
217
+ command: {
218
+ command: ["sh", "-c", fullCommand]
219
+ }
220
+ })
221
+ },
222
+ sandbox.commandServiceEndpoint
223
+ );
224
+ const decodeBase64 = (data) => {
225
+ if (!data) return "";
226
+ try {
227
+ return Buffer.from(data, "base64").toString();
228
+ } catch {
229
+ return data;
230
+ }
231
+ };
232
+ const stdout = decodeBase64(result.stdout);
233
+ const stderr = decodeBase64(result.stderr);
234
+ return {
235
+ stdout,
236
+ stderr,
237
+ exitCode: result.exitCode ?? 0,
238
+ durationMs: Date.now() - startTime
239
+ };
240
+ } catch (error) {
241
+ throw new Error(
242
+ `Namespace command execution failed: ${error instanceof Error ? error.message : String(error)}`
243
+ );
244
+ }
245
+ },
246
+ // Not supported - throw as no-op
247
+ runCode: async (_sandbox, _code, _runtime, _config) => {
248
+ throw new Error("Namespace provider does not support runCode. Use runCommand instead.");
249
+ },
250
+ getInfo: async (sandbox) => {
251
+ return {
252
+ id: sandbox.instanceId,
253
+ provider: "namespace",
254
+ runtime: "node",
255
+ status: "running",
256
+ createdAt: sandbox.createdAt,
257
+ timeout: 0,
258
+ metadata: {
259
+ name: sandbox.name,
260
+ commandServiceEndpoint: sandbox.commandServiceEndpoint
261
+ }
262
+ };
263
+ },
264
+ // Not supported - throw as no-op
265
+ getUrl: async (_sandbox, _options) => {
266
+ throw new Error("Namespace provider does not support getUrl.");
267
+ },
268
+ getInstance: (sandbox) => {
269
+ return sandbox;
270
+ }
271
+ }
272
+ }
5
273
  });
6
274
  export {
275
+ fetchNamespace,
276
+ getAndValidateCredentials,
7
277
  namespace
8
278
  };
9
279
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Namespace Provider - Compute Factory\n *\n * Provides a first-class Namespace provider experience by routing all operations\n * through the ComputeSDK gateway. The gateway handles infrastructure provisioning\n * via @computesdk/gateway and installs the daemon for full sandbox capabilities.\n */\n\nimport { defineCompute, type ComputeConfig } from '@computesdk/provider';\n\n/**\n * Namespace provider configuration\n */\nexport interface NamespaceConfig extends ComputeConfig {\n /** Namespace API token - if not provided, will fallback to NSC_TOKEN environment variable */\n token?: string;\n /** Virtual CPU cores for the instance */\n virtualCpu?: number;\n /** Memory in megabytes for the instance */\n memoryMegabytes?: number;\n /** Machine architecture (default: amd64) */\n machineArch?: string;\n /** Operating system (default: linux) */\n os?: string;\n /** Documented purpose for the instance */\n documentedPurpose?: string;\n /** Reason for destroying instances (default: \"ComputeSDK cleanup\") */\n destroyReason?: string;\n}\n\n/**\n * Namespace compute factory - creates configured compute instances\n *\n * Namespace is an infrastructure provider that becomes a full sandbox provider\n * via the ComputeSDK gateway. The gateway provisions Namespace instances with the\n * daemon pre-installed, enabling full sandbox capabilities.\n *\n * @example\n * ```typescript\n * import { namespace } from '@computesdk/namespace';\n *\n * const compute = namespace({\n * token: 'nsc_xxx'\n * });\n *\n * // Full compute API available (routes through gateway)\n * const sandbox = await compute.sandbox.create();\n *\n * // Execute code\n * const result = await sandbox.runCode('console.log(\"Hello from Namespace!\")');\n * console.log(result.stdout);\n *\n * // Filesystem operations\n * await sandbox.filesystem.writeFile('/tmp/test.txt', 'Hello!');\n * const content = await sandbox.filesystem.readFile('/tmp/test.txt');\n *\n * // Cleanup\n * await sandbox.destroy();\n * ```\n */\nexport const namespace = defineCompute<NamespaceConfig>({\n provider: 'namespace'\n});\n"],"mappings":";AAQA,SAAS,qBAAyC;AAoD3C,IAAM,YAAY,cAA+B;AAAA,EACtD,UAAU;AACZ,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Namespace Provider\n *\n * Full-featured provider using the factory pattern.\n * Supports instance lifecycle management and command execution via Namespace Compute API.\n */\n\nimport * as fs from 'fs/promises';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\nimport type { Runtime, CodeResult, CommandResult, SandboxInfo, CreateSandboxOptions, RunCommandOptions } from '@computesdk/provider';\n\n/**\n * Namespace sandbox instance\n */\nexport interface NamespaceSandbox {\n instanceId: string;\n name: string;\n commandServiceEndpoint?: string;\n token: string;\n targetContainerName: string;\n createdAt: Date;\n}\n\n/**\n * Namespace provider configuration\n */\nexport interface NamespaceConfig {\n /** Namespace API token - if not provided, will fallback to NSC_TOKEN environment variable */\n token?: string;\n /** Path to a JSON token file (e.g. from `nsc login`) containing bearer_token - fallback to NSC_TOKEN_FILE */\n tokenFile?: string;\n /** Virtual CPU cores for the instance */\n virtualCpu?: number;\n /** Memory in megabytes for the instance */\n memoryMegabytes?: number;\n /** Machine architecture (default: amd64) */\n machineArch?: string;\n /** Operating system (default: linux) */\n os?: string;\n /** Documented purpose for the instance */\n documentedPurpose?: string;\n /** Reason for destroying instances (default: \"ComputeSDK cleanup\") */\n destroyReason?: string;\n /** Target container name for command execution (default: \"main-container\") */\n targetContainerName?: string;\n}\n\nconst API_ENDPOINTS = {\n CREATE_INSTANCE: '/namespace.cloud.compute.v1beta.ComputeService/CreateInstance',\n DESCRIBE_INSTANCE: '/namespace.cloud.compute.v1beta.ComputeService/DescribeInstance',\n LIST_INSTANCES: '/namespace.cloud.compute.v1beta.ComputeService/ListInstances',\n DESTROY_INSTANCE: '/namespace.cloud.compute.v1beta.ComputeService/DestroyInstance'\n};\n\nconst COMMAND_SERVICE = {\n RUN_COMMAND_SYNC: '/namespace.cloud.compute.v1beta.CommandService/RunCommandSync',\n};\n\n/**\n * Load bearer token from a JSON token file (e.g. from `nsc login`)\n */\nasync function loadTokenFromFile(filePath: string): Promise<string> {\n const content = await fs.readFile(filePath, 'utf8');\n const tokenJson: { bearer_token?: string } = JSON.parse(content);\n if (!tokenJson.bearer_token) {\n throw new Error(`Token file ${filePath} does not contain a bearer_token`);\n }\n return tokenJson.bearer_token;\n}\n\n/**\n * Get and validate Namespace credentials from config and environment.\n * Supports:\n * - config.token (direct bearer token)\n * - NSC_TOKEN env var (direct bearer token)\n * - NSC_TOKEN_FILE env var (path to JSON file with bearer_token field)\n */\nexport const getAndValidateCredentials = async (config: NamespaceConfig) => {\n // 1. Direct token from config or env\n let token = config.token || (typeof process !== 'undefined' && process.env?.NSC_TOKEN) || '';\n\n // 2. If no direct token, try loading from token file\n if (!token) {\n const tokenFile = config.tokenFile || (typeof process !== 'undefined' && process.env?.NSC_TOKEN_FILE) || '';\n if (tokenFile) {\n token = await loadTokenFromFile(tokenFile);\n }\n }\n\n if (!token) {\n throw new Error(\n 'Missing Namespace token. Provide token in config, set NSC_TOKEN, or set NSC_TOKEN_FILE environment variable (or provide tokenFile in config).'\n );\n }\n\n return { token };\n};\n\nconst handleApiErrors = (response: any) => {\n if (response.error) {\n throw new Error(`Namespace API error: ${response.error}`);\n }\n};\n\nexport const fetchNamespace = async (\n token: string,\n endpoint: string,\n options: RequestInit = {},\n baseUrl: string = 'https://us.compute.namespaceapis.com'\n) => {\n const response = await fetch(`${baseUrl}${endpoint}`, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n ...options.headers\n }\n });\n\n if (!response.ok) {\n throw new Error(`Namespace API error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n // Standard error handling for all operations\n handleApiErrors(data);\n\n return data;\n};\n\n/**\n * Namespace provider\n *\n * Creates Namespace instances and supports command execution via CommandService.\n */\nexport const namespace = defineProvider<NamespaceSandbox, NamespaceConfig>({\n name: 'namespace',\n\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: NamespaceConfig, options?: CreateSandboxOptions) => {\n const { token } = await getAndValidateCredentials(config);\n const containerName = config.targetContainerName || 'main-container';\n\n try {\n const requestBody = {\n shape: {\n virtual_cpu: config.virtualCpu || 2,\n memory_megabytes: config.memoryMegabytes || 4096,\n machine_arch: config.machineArch || 'amd64',\n os: config.os || 'linux'\n },\n containers: [{\n name: containerName,\n image_ref: options?.image ?? 'ubuntu:latest',\n args: ['sleep', 'infinity'],\n ...(options?.envs && Object.keys(options.envs).length > 0 && {\n environment: options.envs\n })\n }],\n documented_purpose: config.documentedPurpose || 'ComputeSDK sandbox',\n deadline: new Date(Date.now() + 60 * 60 * 1000).toISOString()\n };\n\n const responseData = await fetchNamespace(token, API_ENDPOINTS.CREATE_INSTANCE, {\n method: 'POST',\n body: JSON.stringify(requestBody)\n });\n\n // Extract instance ID from the Namespace API response structure\n if (!responseData.metadata?.instanceId) {\n throw new Error(`Instance ID is undefined. Full response object: ${JSON.stringify(responseData, null, 2)}`);\n }\n\n const instanceId = responseData.metadata.instanceId;\n const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;\n\n const sandbox: NamespaceSandbox = {\n instanceId,\n name: `instance-${instanceId}`,\n commandServiceEndpoint,\n token,\n targetContainerName: containerName,\n createdAt: new Date(),\n };\n\n return {\n sandbox,\n sandboxId: instanceId\n };\n } catch (error) {\n throw new Error(\n `Failed to create Namespace instance: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: NamespaceConfig, sandboxId: string) => {\n const { token } = await getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchNamespace(token, API_ENDPOINTS.DESCRIBE_INSTANCE, {\n method: 'POST',\n body: JSON.stringify({ instance_id: sandboxId })\n });\n\n // Extract instance ID from the Namespace API response structure\n if (!responseData.metadata?.instanceId) {\n throw new Error('Instance data is missing from Namespace response');\n }\n\n const instanceId = responseData.metadata.instanceId;\n const commandServiceEndpoint = responseData.extendedMetadata?.commandServiceEndpoint;\n\n const sandbox: NamespaceSandbox = {\n instanceId,\n name: `instance-${instanceId}`,\n commandServiceEndpoint,\n token,\n targetContainerName: config.targetContainerName || 'main-container',\n createdAt: responseData.metadata?.createdAt ? new Date(responseData.metadata.createdAt) : new Date(0),\n };\n\n return {\n sandbox,\n sandboxId: instanceId\n };\n } catch (error) {\n // Handle 404 errors by returning null (instance not found)\n if (error instanceof Error && error.message.includes('404')) {\n return null;\n }\n\n throw new Error(\n `Failed to get Namespace instance: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n list: async (config: NamespaceConfig) => {\n const { token } = await getAndValidateCredentials(config);\n\n try {\n const responseData = await fetchNamespace(token, API_ENDPOINTS.LIST_INSTANCES, {\n method: 'POST',\n body: JSON.stringify({})\n });\n\n // Extract instances from the response\n const instances = responseData?.instances || [];\n\n // Filter to instances with valid IDs, then transform\n return instances\n .filter((instanceData: any) => instanceData.instanceId || instanceData.metadata?.instanceId)\n .map((instanceData: any) => {\n const instanceId = instanceData.instanceId || instanceData.metadata.instanceId;\n const commandServiceEndpoint = instanceData.extendedMetadata?.commandServiceEndpoint;\n\n const sandbox: NamespaceSandbox = {\n instanceId,\n name: `instance-${instanceId}`,\n commandServiceEndpoint,\n token,\n targetContainerName: config.targetContainerName || 'main-container',\n createdAt: instanceData.metadata?.createdAt ? new Date(instanceData.metadata.createdAt) : new Date(0),\n };\n\n return {\n sandbox,\n sandboxId: instanceId\n };\n });\n } catch (error) {\n throw new Error(\n `Failed to list Namespace instances: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n destroy: async (config: NamespaceConfig, sandboxId: string) => {\n const { token } = await getAndValidateCredentials(config);\n\n try {\n const data = await fetchNamespace(token, API_ENDPOINTS.DESTROY_INSTANCE, {\n method: 'POST',\n body: JSON.stringify({\n instance_id: sandboxId,\n reason: config.destroyReason || \"ComputeSDK cleanup\"\n })\n });\n\n if (data.error) {\n // Log errors but don't throw for destroy operations\n console.warn(`Namespace destroy warning: ${data.error}`);\n }\n } catch (error) {\n // For destroy operations, we log warnings rather than throwing\n // since the resource may already be gone\n console.warn(`Namespace destroy warning: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n // Command execution via Namespace CommandService\n runCommand: async (sandbox: NamespaceSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n if (!sandbox.commandServiceEndpoint) {\n throw new Error('Command service endpoint not available. The instance may not support command execution.');\n }\n\n const startTime = Date.now();\n\n try {\n // Build the full command with options\n let fullCommand = command;\n\n // Handle environment variables\n if (options?.env && Object.keys(options.env).length > 0) {\n const envPrefix = Object.entries(options.env)\n .map(([k, v]) => `${k}=${escapeShellArg(v)}`)\n .join(' ');\n fullCommand = `${envPrefix} ${fullCommand}`;\n }\n\n // Handle working directory\n if (options?.cwd) {\n fullCommand = `cd ${escapeShellArg(options.cwd)} && ${fullCommand}`;\n }\n\n // Handle background execution\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n // Call CommandService RunCommandSync via Connect protocol\n const result = await fetchNamespace(\n sandbox.token,\n COMMAND_SERVICE.RUN_COMMAND_SYNC,\n {\n method: 'POST',\n body: JSON.stringify({\n instanceId: sandbox.instanceId,\n targetContainerName: sandbox.targetContainerName,\n command: {\n command: ['sh', '-c', fullCommand],\n },\n })\n },\n sandbox.commandServiceEndpoint\n ) as {\n stdout?: string; // base64-encoded\n stderr?: string; // base64-encoded\n exitCode?: number;\n };\n\n // Decode base64-encoded stdout/stderr, falling back to raw string on invalid data\n const decodeBase64 = (data?: string): string => {\n if (!data) return '';\n try {\n return Buffer.from(data, 'base64').toString();\n } catch {\n return data;\n }\n };\n const stdout = decodeBase64(result.stdout);\n const stderr = decodeBase64(result.stderr);\n\n return {\n stdout,\n stderr,\n exitCode: result.exitCode ?? 0,\n durationMs: Date.now() - startTime\n };\n } catch (error) {\n // Re-throw infrastructure errors (network, auth, API) so they propagate\n // rather than being masked as command execution failures\n throw new Error(\n `Namespace command execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Not supported - throw as no-op\n runCode: async (_sandbox: NamespaceSandbox, _code: string, _runtime?: Runtime, _config?: NamespaceConfig): Promise<CodeResult> => {\n throw new Error('Namespace provider does not support runCode. Use runCommand instead.');\n },\n\n getInfo: async (sandbox: NamespaceSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.instanceId,\n provider: 'namespace',\n runtime: 'node',\n status: 'running',\n createdAt: sandbox.createdAt,\n timeout: 0,\n metadata: {\n name: sandbox.name,\n commandServiceEndpoint: sandbox.commandServiceEndpoint,\n }\n };\n },\n\n // Not supported - throw as no-op\n getUrl: async (_sandbox: NamespaceSandbox, _options: { port: number; protocol?: string }): Promise<string> => {\n throw new Error('Namespace provider does not support getUrl.');\n },\n\n getInstance: (sandbox: NamespaceSandbox): NamespaceSandbox => {\n return sandbox;\n },\n }\n }\n});\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/namespace",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Namespace provider for ComputeSDK - cloud-native sandboxes with optional GPU support",
5
5
  "author": "ComputeSDK Team",
6
6
  "license": "MIT",
@@ -18,8 +18,8 @@
18
18
  "dist"
19
19
  ],
20
20
  "dependencies": {
21
- "@computesdk/provider": "1.0.27",
22
- "computesdk": "2.2.1"
21
+ "@computesdk/provider": "1.0.28",
22
+ "computesdk": "2.3.0"
23
23
  },
24
24
  "keywords": [
25
25
  "computesdk",