@nimbus-sh/sdk 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @nimbus-sh/sdk
2
2
 
3
- SDK for Nimbus — programmatic sandbox handles, token mint/verify, typed
4
- errors, and session URL helpers.
3
+ SDK for Nimbus — Worker embedder, programmatic sandbox handles,
4
+ token mint/verify, typed errors, and session URL helpers.
5
5
 
6
6
  ## Install
7
7
 
@@ -9,41 +9,85 @@ errors, and session URL helpers.
9
9
  npm install @nimbus-sh/sdk @nimbus-sh/worker @nimbus-sh/config
10
10
  ```
11
11
 
12
- The sandbox SDK is meant to run inside the Worker or Durable Object that owns
13
- the `NIMBUS_SESSION` binding. A minimal project setup is:
12
+ Use `@nimbus-sh/sdk/worker` as the public Worker embedder entrypoint.
13
+ `@nimbus-sh/worker` is still installed because it carries the runtime assets
14
+ and Durable Object implementation, but application code imports the
15
+ deploy-time API through the SDK.
16
+
17
+ Create a deployable Nimbus Worker:
14
18
 
15
19
  ```bash
16
- npx @nimbus-sh/cli init my-nimbus-worker
20
+ npx create-nimbus-app my-nimbus-worker
17
21
  cd my-nimbus-worker
18
22
  npm install
19
- wrangler secret put JWT_SECRET
20
- wrangler deploy
23
+ CLOUDFLARE_ACCOUNT_ID=<account-id> npx @nimbus-sh/cli setup cloudflare --name my-nimbus-worker
24
+ npx wrangler secret put JWT_SECRET
25
+ npx wrangler deploy
21
26
  ```
22
27
 
23
- From this repository, use the source CLI:
28
+ `src/index.ts`:
24
29
 
25
- ```bash
26
- bun packages/cli/src/bin.ts init my-nimbus-worker
27
- cd my-nimbus-worker
28
- bun install
29
- wrangler secret put JWT_SECRET
30
- wrangler deploy
30
+ ```ts
31
+ import {
32
+ NimbusSession,
33
+ SupervisorRPC,
34
+ NimbusAssetsRPC,
35
+ NimbusLoaderRPC,
36
+ NimbusLoadedWorker,
37
+ NimbusLoadedEntrypoint,
38
+ NimbusDurableObjectNamespace,
39
+ NimbusDOStub,
40
+ CirrusHmrRPC,
41
+ createNimbusHandler,
42
+ } from '@nimbus-sh/sdk/worker';
43
+ import { defineNimbusConfig } from '@nimbus-sh/config';
44
+
45
+ export {
46
+ NimbusSession,
47
+ SupervisorRPC,
48
+ NimbusAssetsRPC,
49
+ NimbusLoaderRPC,
50
+ NimbusLoadedWorker,
51
+ NimbusLoadedEntrypoint,
52
+ NimbusDurableObjectNamespace,
53
+ NimbusDOStub,
54
+ CirrusHmrRPC,
55
+ };
56
+
57
+ const nimbusConfig = defineNimbusConfig({
58
+ sandboxes: {
59
+ default: {
60
+ root: '/home/user',
61
+ runtimes: { preinstall: ['python'], onDemand: true },
62
+ tools: { namespace: 'sandbox', kind: 'sandbox' },
63
+ },
64
+ },
65
+ });
66
+
67
+ export default createNimbusHandler({
68
+ sdk: {
69
+ remote: true,
70
+ config: nimbusConfig,
71
+ },
72
+ });
31
73
  ```
32
74
 
33
75
  ## Programmatic sandbox quickstart
34
76
 
35
- Use `@nimbus-sh/sdk/sandbox` inside the Worker or Durable Object that embeds
36
- Nimbus. The SDK talks to the `NIMBUS_SESSION` Durable Object binding via DO
37
- RPC; it does not need a browser WebSocket.
77
+ The same sandbox handle API works in two modes:
78
+
79
+ - `Nimbus.fromEnv(env, config)` for a Worker or Durable Object with the
80
+ `NIMBUS_SESSION` binding.
81
+ - `Nimbus.connect({ endpoint, token, config })` for any backend that can reach
82
+ a deployed Nimbus Worker.
38
83
 
39
84
  ```ts
40
- import { Nimbus } from '@nimbus-sh/sdk/sandbox';
85
+ import { Nimbus } from '@nimbus-sh/sdk';
41
86
  import { defineNimbusConfig } from '@nimbus-sh/config';
42
87
 
43
88
  const nimbusConfig = defineNimbusConfig({
44
- endpoint: 'https://my-nimbus.workers.dev',
45
89
  sandboxes: {
46
- proteus: {
90
+ default: {
47
91
  root: '/home/user',
48
92
  tools: { namespace: 'sandbox', kind: 'sandbox' },
49
93
  runtimes: {
@@ -58,7 +102,6 @@ const nimbusConfig = defineNimbusConfig({
58
102
  export default {
59
103
  async fetch(_request: Request, env: Env) {
60
104
  const box = Nimbus.fromEnv(env, nimbusConfig).sandbox('job-123', {
61
- profile: 'proteus',
62
105
  tenant: 'acme',
63
106
  subject: 'agent',
64
107
  });
@@ -72,10 +115,50 @@ export default {
72
115
  };
73
116
  ```
74
117
 
118
+ Remote use:
119
+
120
+ ```ts
121
+ import { Nimbus, issueNimbusToken } from '@nimbus-sh/sdk';
122
+
123
+ const token = await issueNimbusToken(env, {
124
+ tn: 'acme',
125
+ sub: 'agent',
126
+ scopes: ['sandbox:use'],
127
+ sid: 'job-123',
128
+ });
129
+
130
+ const box = Nimbus.connect({
131
+ endpoint: 'https://my-nimbus.workers.dev',
132
+ token,
133
+ config: nimbusConfig,
134
+ }).sandbox('job-123');
135
+
136
+ const result = await box.exec('python -c "print(2 + 2)"');
137
+ ```
138
+
139
+ Enable the remote API in the Nimbus Worker:
140
+
141
+ ```ts
142
+ export default createNimbusHandler({
143
+ sdk: {
144
+ remote: true,
145
+ config: nimbusConfig,
146
+ },
147
+ });
148
+ ```
149
+
150
+ `Nimbus.connect()` calls the versioned `/api/nimbus/v1` API internally. The
151
+ Worker verifies the JWT, enforces `sid` pins and `sandbox:use` scope, applies
152
+ the configured runtime policy, and delegates to the same `NimbusSession` RPC
153
+ methods used by `Nimbus.fromEnv()`.
154
+
75
155
  ## Sandbox handle API
76
156
 
77
157
  ```ts
78
158
  const nimbus = Nimbus.fromEnv(env, config, { binding: 'NIMBUS_SESSION' });
159
+ // or:
160
+ const nimbus = Nimbus.connect({ endpoint, token, config });
161
+
79
162
  const box = nimbus.sandbox('session-or-job-id', {
80
163
  profile: 'default',
81
164
  tenant: 'acme',
@@ -213,6 +296,7 @@ const { token, url } = await mintAndAttach(
213
296
  | `@nimbus-sh/sdk/errors` | `NimbusAuthError` class hierarchy. |
214
297
  | `@nimbus-sh/sdk/session` | `sessionAttachUrl`, `mintAndAttach`. |
215
298
  | `@nimbus-sh/sdk/sandbox` | `Nimbus`, `NimbusSandbox`, programmatic exec/files/runtimes/processes/ports/tools. |
299
+ | `@nimbus-sh/sdk/worker` | Worker embedder entrypoint: `NimbusSession`, RPC classes, `createNimbusHandler`, auth helpers. |
216
300
 
217
301
  ## Token wire format
218
302
 
package/dist/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  /**
2
- * @nimbus-sh/sdk — Client SDK for Nimbus.
2
+ * @nimbus-sh/sdk — Public SDK for Nimbus.
3
3
  *
4
- * The SDK is the **environment-agnostic** half of Nimbus: token mint /
5
- * verify, typed errors, session-handle types, and the HTTP fallback for
6
- * non-Worker consumers. Everything in this package is safe to import
7
- * from a Node SSR layer, a Worker, an Edge function, or a browser
8
- * build.
4
+ * The SDK is the public surface for Nimbus applications: token mint /
5
+ * verify, typed errors, session-handle helpers, programmatic sandboxes,
6
+ * and the Worker embedder subpath.
9
7
  *
10
- * For the Worker runtime itself (the Durable Object, the router, the
11
- * facet machinery), see `@nimbus-sh/worker`.
8
+ * Import the deployed Worker embedder from `@nimbus-sh/sdk/worker`.
9
+ * The Durable Object, router, assets, VFS, and facet implementation live
10
+ * in `@nimbus-sh/worker` and are re-exported through that public SDK
11
+ * subpath.
12
12
  *
13
13
  * @example mint a token in your Worker's `/api/auth/mint` route
14
14
  * ```ts
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  /**
2
- * @nimbus-sh/sdk — Client SDK for Nimbus.
2
+ * @nimbus-sh/sdk — Public SDK for Nimbus.
3
3
  *
4
- * The SDK is the **environment-agnostic** half of Nimbus: token mint /
5
- * verify, typed errors, session-handle types, and the HTTP fallback for
6
- * non-Worker consumers. Everything in this package is safe to import
7
- * from a Node SSR layer, a Worker, an Edge function, or a browser
8
- * build.
4
+ * The SDK is the public surface for Nimbus applications: token mint /
5
+ * verify, typed errors, session-handle helpers, programmatic sandboxes,
6
+ * and the Worker embedder subpath.
9
7
  *
10
- * For the Worker runtime itself (the Durable Object, the router, the
11
- * facet machinery), see `@nimbus-sh/worker`.
8
+ * Import the deployed Worker embedder from `@nimbus-sh/sdk/worker`.
9
+ * The Durable Object, router, assets, VFS, and facet implementation live
10
+ * in `@nimbus-sh/worker` and are re-exported through that public SDK
11
+ * subpath.
12
12
  *
13
13
  * @example mint a token in your Worker's `/api/auth/mint` route
14
14
  * ```ts
package/dist/sandbox.d.ts CHANGED
@@ -28,6 +28,21 @@ export interface NimbusFromEnvOptions {
28
28
  binding?: string;
29
29
  endpoint?: string;
30
30
  }
31
+ export type NimbusHeaders = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
32
+ export interface NimbusConnectOptions {
33
+ /** Base URL of a Nimbus deployment, for example `https://nimbus.example.com`. */
34
+ endpoint: string;
35
+ /** Nimbus JWT. Sent as `Authorization: Bearer <token>` when provided. */
36
+ token?: string;
37
+ /** Additional headers, or a callback for rotating credentials. */
38
+ headers?: NimbusHeaders;
39
+ /** Custom fetch implementation. Defaults to global `fetch`. */
40
+ fetch?: typeof fetch;
41
+ /** Remote API base path. Defaults to `/api/nimbus/v1`. */
42
+ basePath?: string;
43
+ /** Sandbox profiles used by this client. The deployment should use the same config. */
44
+ config?: NimbusConfig;
45
+ }
31
46
  export interface NimbusSandboxOptions {
32
47
  profile?: string;
33
48
  tenant?: string;
@@ -88,26 +103,50 @@ export interface NimbusAvailableRuntime {
88
103
  }>;
89
104
  }
90
105
  type NimbusSessionNamespace = DurableObjectNamespace<any>;
106
+ type NimbusTarget = {
107
+ kind: 'binding';
108
+ namespace: NimbusSessionNamespace;
109
+ } | {
110
+ kind: 'remote';
111
+ endpoint: string;
112
+ basePath: string;
113
+ token?: string;
114
+ headers?: NimbusHeaders;
115
+ fetch: typeof fetch;
116
+ };
117
+ export declare class NimbusRemoteError extends Error {
118
+ readonly status: number;
119
+ readonly code: string | undefined;
120
+ readonly body: unknown;
121
+ constructor(message: string, options: {
122
+ status: number;
123
+ code?: string;
124
+ body?: unknown;
125
+ });
126
+ }
91
127
  export declare class Nimbus {
92
- private readonly namespace;
93
128
  private readonly config;
94
129
  static fromEnv(env: Record<string, unknown>, config?: NimbusConfig, options?: NimbusFromEnvOptions): Nimbus;
95
- constructor(namespace: NimbusSessionNamespace, config?: NimbusConfig);
130
+ static connect(options: NimbusConnectOptions): Nimbus;
131
+ private readonly target;
132
+ constructor(target: NimbusSessionNamespace | NimbusTarget, config?: NimbusConfig);
96
133
  sandbox(id: string, options?: NimbusSandboxOptions): NimbusSandbox;
97
134
  }
98
135
  export declare class NimbusSandbox {
99
- private readonly namespace;
136
+ private readonly target;
100
137
  private readonly options;
101
138
  private readonly config;
102
139
  readonly id: string;
103
140
  readonly profileName: string;
104
141
  private readonly profile;
105
142
  private readyPromise;
106
- constructor(namespace: NimbusSessionNamespace, id: string, options: NimbusSandboxOptions, config: NimbusConfig);
143
+ constructor(target: NimbusTarget, id: string, options: NimbusSandboxOptions, config: NimbusConfig);
107
144
  private get tenantSegment();
108
145
  private get doName();
109
146
  private get root();
110
147
  private stub;
148
+ private remoteStub;
149
+ private remoteRpc;
111
150
  ready(): Promise<void>;
112
151
  exec(command: string, options?: NimbusExecOptions): Promise<NimbusExecResult>;
113
152
  startProcess(command: string, options?: NimbusExecOptions): Promise<NimbusStartResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
package/dist/sandbox.js CHANGED
@@ -1,8 +1,19 @@
1
1
  /**
2
2
  * @nimbus-sh/sdk/sandbox - programmatic Nimbus sandbox handle.
3
3
  */
4
+ export class NimbusRemoteError extends Error {
5
+ status;
6
+ code;
7
+ body;
8
+ constructor(message, options) {
9
+ super(message);
10
+ this.name = 'NimbusRemoteError';
11
+ this.status = options.status;
12
+ this.code = options.code;
13
+ this.body = options.body;
14
+ }
15
+ }
4
16
  export class Nimbus {
5
- namespace;
6
17
  config;
7
18
  static fromEnv(env, config = {}, options = {}) {
8
19
  const bindingName = options.binding ?? 'NIMBUS_SESSION';
@@ -10,38 +21,62 @@ export class Nimbus {
10
21
  if (!binding) {
11
22
  throw new Error(`Nimbus.fromEnv: env.${bindingName} Durable Object binding is missing`);
12
23
  }
13
- return new Nimbus(binding, {
24
+ return new Nimbus({ kind: 'binding', namespace: binding }, {
14
25
  ...config,
15
26
  endpoint: options.endpoint ?? config.endpoint,
16
27
  });
17
28
  }
18
- constructor(namespace, config = {}) {
19
- this.namespace = namespace;
29
+ static connect(options) {
30
+ if (!options.endpoint) {
31
+ throw new Error('Nimbus.connect: endpoint is required');
32
+ }
33
+ const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
34
+ if (typeof fetchImpl !== 'function') {
35
+ throw new Error('Nimbus.connect: fetch is unavailable; pass a custom fetch implementation');
36
+ }
37
+ const config = {
38
+ ...(options.config ?? {}),
39
+ endpoint: options.endpoint,
40
+ };
41
+ return new Nimbus({
42
+ kind: 'remote',
43
+ endpoint: trimTrailingSlashes(options.endpoint),
44
+ basePath: normalizeBasePath(options.basePath ?? '/api/nimbus/v1'),
45
+ token: options.token,
46
+ headers: options.headers,
47
+ fetch: fetchImpl,
48
+ }, config);
49
+ }
50
+ target;
51
+ constructor(target, config = {}) {
20
52
  this.config = config;
53
+ this.target = isNimbusTarget(target)
54
+ ? target
55
+ : { kind: 'binding', namespace: target };
21
56
  }
22
57
  sandbox(id, options = {}) {
23
- return new NimbusSandbox(this.namespace, String(id), options, this.config);
58
+ return new NimbusSandbox(this.target, String(id), options, this.config);
24
59
  }
25
60
  }
26
61
  export class NimbusSandbox {
27
- namespace;
62
+ target;
28
63
  options;
29
64
  config;
30
65
  id;
31
66
  profileName;
32
67
  profile;
33
68
  readyPromise = null;
34
- constructor(namespace, id, options, config) {
35
- this.namespace = namespace;
69
+ constructor(target, id, options, config) {
70
+ this.target = target;
36
71
  this.options = options;
37
72
  this.config = config;
38
- this.id = id;
73
+ this.id = idComponent(id, 'sandbox id');
39
74
  this.profileName = options.profile ?? 'default';
40
75
  this.profile = config.sandboxes?.[this.profileName] ?? config.sandboxes?.default ?? {};
41
76
  }
42
77
  get tenantSegment() {
43
- const tenant = sanitizeSegment(this.options.tenant ?? 'default');
44
- const subject = sanitizeSegment(this.options.subject ?? '_');
78
+ const tenant = idComponent(this.options.tenant ?? 'default', 'tenant');
79
+ const subject = idComponent(this.options.subject ?? '_', 'subject');
45
80
  return `${tenant}:${subject}`;
46
81
  }
47
82
  get doName() {
@@ -51,10 +86,81 @@ export class NimbusSandbox {
51
86
  return this.options.root ?? this.profile.root ?? '/home/user';
52
87
  }
53
88
  stub() {
54
- const namespace = this.namespace;
89
+ if (this.target.kind === 'remote')
90
+ return this.remoteStub();
91
+ const namespace = this.target.namespace;
55
92
  const id = namespace.idFromName(this.doName);
56
93
  return namespace.get(id);
57
94
  }
95
+ remoteStub() {
96
+ return {
97
+ _rpcReady: (options) => this.remoteRpc('ready', [options]),
98
+ _rpcExec: (command, options) => this.remoteRpc('exec', [command, options]),
99
+ _rpcStartProcess: (command, options) => this.remoteRpc('startProcess', [command, options]),
100
+ _rpcRunCode: (code, options) => this.remoteRpc('runCode', [code, options]),
101
+ _rpcReadFile: (path) => this.remoteRpc('readFile', [path]),
102
+ _rpcReadFileBytes: (path) => this.remoteRpc('readFileBytes', [path]),
103
+ _rpcWriteFile: (path, content) => this.remoteRpc('writeFile', [path, content]),
104
+ _rpcReaddir: (path) => this.remoteRpc('readdir', [path]),
105
+ _rpcExists: (path) => this.remoteRpc('exists', [path]),
106
+ _rpcMkdir: (path) => this.remoteRpc('mkdir', [path]),
107
+ _rpcDeleteFile: (path, options) => this.remoteRpc('deleteFile', [path, options]),
108
+ _rpcInstallRuntime: (spec, options) => this.remoteRpc('installRuntime', [spec, options]),
109
+ _rpcEnsureRuntimes: (specs, options) => this.remoteRpc('ensureRuntimes', [specs, options]),
110
+ _rpcListRuntimes: () => this.remoteRpc('listRuntimes', []),
111
+ _rpcListProcesses: () => this.remoteRpc('listProcesses', []),
112
+ _rpcKillProcess: (pid) => this.remoteRpc('killProcess', [pid]),
113
+ _rpcProcessLogs: (pid, options) => this.remoteRpc('processLogs', [pid, options]),
114
+ _rpcListPorts: () => this.remoteRpc('listPorts', []),
115
+ _rpcExposePort: (port) => this.remoteRpc('exposePort', [port]),
116
+ _rpcUnexposePort: (port) => this.remoteRpc('unexposePort', [port]),
117
+ };
118
+ }
119
+ async remoteRpc(op, args) {
120
+ if (this.target.kind !== 'remote') {
121
+ throw new Error('Nimbus internal error: remoteRpc called on non-remote target');
122
+ }
123
+ const headers = new Headers(await resolveHeaders(this.target.headers));
124
+ headers.set('Accept', 'application/json');
125
+ headers.set('Content-Type', 'application/json');
126
+ if (this.target.token && !headers.has('Authorization')) {
127
+ headers.set('Authorization', `Bearer ${this.target.token}`);
128
+ }
129
+ const response = await this.target.fetch(`${this.target.endpoint}${this.target.basePath}/sandboxes/${encodeURIComponent(this.id)}/rpc`, {
130
+ method: 'POST',
131
+ headers,
132
+ body: JSON.stringify(encodeWire({
133
+ profile: this.profileName,
134
+ tenant: this.options.tenant,
135
+ subject: this.options.subject,
136
+ root: this.root,
137
+ op,
138
+ args,
139
+ })),
140
+ });
141
+ const text = await response.text();
142
+ let payload = null;
143
+ if (text) {
144
+ try {
145
+ payload = JSON.parse(text);
146
+ }
147
+ catch {
148
+ throw new NimbusRemoteError(`Nimbus remote API returned non-JSON response (${response.status})`, {
149
+ status: response.status,
150
+ body: text,
151
+ });
152
+ }
153
+ }
154
+ if (!response.ok || payload?.ok !== true) {
155
+ const message = payload?.error ?? payload?.message ?? `Nimbus remote API request failed (${response.status})`;
156
+ throw new NimbusRemoteError(message, {
157
+ status: response.status,
158
+ code: payload?.code,
159
+ body: payload,
160
+ });
161
+ }
162
+ return decodeWire(payload.result);
163
+ }
58
164
  async ready() {
59
165
  if (!this.readyPromise) {
60
166
  const preinstall = this.profile.runtimes?.preinstall ?? [];
@@ -245,15 +351,125 @@ export class NimbusSandbox {
245
351
  portUrl(port) {
246
352
  const explicit = this.profile.preview?.baseUrl;
247
353
  if (explicit) {
248
- const base = explicit.replace('{sessionId}', encodeURIComponent(this.id)).replace(/\/+$/, '');
354
+ const base = trimTrailingSlashes(explicit.replace('{sessionId}', encodeURIComponent(this.id)));
249
355
  return `${base}/port/${port}/`;
250
356
  }
251
- const endpoint = this.config.endpoint?.replace(/\/+$/, '');
357
+ const endpoint = this.config.endpoint ? trimTrailingSlashes(this.config.endpoint) : '';
252
358
  if (!endpoint)
253
359
  return undefined;
254
360
  return `${endpoint}/s/${encodeURIComponent(this.id)}/port/${port}/`;
255
361
  }
256
362
  }
257
- function sanitizeSegment(value) {
258
- return String(value).replace(/[^A-Za-z0-9_.:-]/g, '_') || '_';
363
+ function idComponent(value, field) {
364
+ const text = String(value);
365
+ if (!isIdComponent(text)) {
366
+ throw new Error(`Nimbus ${field} must be 1-128 ASCII letters, digits, dot, underscore, or hyphen`);
367
+ }
368
+ return text;
369
+ }
370
+ function isIdComponent(value) {
371
+ if (value.length < 1 || value.length > 128)
372
+ return false;
373
+ for (let i = 0; i < value.length; i++) {
374
+ const code = value.charCodeAt(i);
375
+ const isDigit = code >= 48 && code <= 57;
376
+ const isUpper = code >= 65 && code <= 90;
377
+ const isLower = code >= 97 && code <= 122;
378
+ const isPunctuation = code === 45 || code === 46 || code === 95;
379
+ if (!isDigit && !isUpper && !isLower && !isPunctuation)
380
+ return false;
381
+ }
382
+ return true;
383
+ }
384
+ function isNimbusTarget(value) {
385
+ return !!value && typeof value === 'object' && 'kind' in value;
386
+ }
387
+ function normalizeBasePath(path) {
388
+ const trimmed = trimSlashes(String(path || '/api/nimbus/v1'));
389
+ return `/${trimmed}`;
390
+ }
391
+ function trimSlashes(value) {
392
+ let start = 0;
393
+ let end = value.length;
394
+ while (start < end && value[start] === '/')
395
+ start++;
396
+ while (end > start && value[end - 1] === '/')
397
+ end--;
398
+ return value.slice(start, end);
399
+ }
400
+ function trimTrailingSlashes(value) {
401
+ let end = value.length;
402
+ while (end > 0 && value[end - 1] === '/')
403
+ end--;
404
+ return value.slice(0, end);
405
+ }
406
+ async function resolveHeaders(input) {
407
+ if (!input)
408
+ return undefined;
409
+ return typeof input === 'function' ? await input() : input;
410
+ }
411
+ function encodeWire(value) {
412
+ if (value instanceof Uint8Array) {
413
+ return {
414
+ __nimbusWireType: 'bytes',
415
+ base64: bytesToBase64(value),
416
+ };
417
+ }
418
+ if (value instanceof ArrayBuffer) {
419
+ return {
420
+ __nimbusWireType: 'bytes',
421
+ base64: bytesToBase64(new Uint8Array(value)),
422
+ };
423
+ }
424
+ if (ArrayBuffer.isView(value)) {
425
+ const view = value;
426
+ return {
427
+ __nimbusWireType: 'bytes',
428
+ base64: bytesToBase64(new Uint8Array(view.buffer, view.byteOffset, view.byteLength)),
429
+ };
430
+ }
431
+ if (Array.isArray(value))
432
+ return value.map(encodeWire);
433
+ if (value && typeof value === 'object') {
434
+ const out = {};
435
+ for (const [key, item] of Object.entries(value)) {
436
+ if (item !== undefined)
437
+ out[key] = encodeWire(item);
438
+ }
439
+ return out;
440
+ }
441
+ return value;
442
+ }
443
+ function decodeWire(value) {
444
+ if (value
445
+ && typeof value === 'object'
446
+ && value.__nimbusWireType === 'bytes'
447
+ && typeof value.base64 === 'string') {
448
+ return base64ToBytes(value.base64);
449
+ }
450
+ if (Array.isArray(value))
451
+ return value.map(decodeWire);
452
+ if (value && typeof value === 'object') {
453
+ const out = {};
454
+ for (const [key, item] of Object.entries(value)) {
455
+ out[key] = decodeWire(item);
456
+ }
457
+ return out;
458
+ }
459
+ return value;
460
+ }
461
+ function bytesToBase64(bytes) {
462
+ let binary = '';
463
+ const chunk = 0x8000;
464
+ for (let i = 0; i < bytes.length; i += chunk) {
465
+ binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
466
+ }
467
+ return btoa(binary);
468
+ }
469
+ function base64ToBytes(base64) {
470
+ const binary = atob(base64);
471
+ const bytes = new Uint8Array(binary.length);
472
+ for (let i = 0; i < binary.length; i++)
473
+ bytes[i] = binary.charCodeAt(i);
474
+ return bytes;
259
475
  }
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,MAAM,CAGR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EACpE,IAAI,EAAE,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzC"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,MAAM,CAIR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EACpE,IAAI,EAAE,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzC"}
package/dist/session.js CHANGED
@@ -26,8 +26,9 @@ import { issueNimbusToken } from '@nimbus-sh/worker/auth';
26
26
  * ```
27
27
  */
28
28
  export function sessionAttachUrl(endpoint, sessionId, token) {
29
- const base = endpoint.replace(/\/+$/, '');
30
- return `${base}/s/${sessionId}/?nimbus_token=${encodeURIComponent(token)}`;
29
+ const url = new URL(`/s/${encodeURIComponent(sessionId)}/`, endpoint);
30
+ url.searchParams.set('nimbus_token', token);
31
+ return url.toString();
31
32
  }
32
33
  /**
33
34
  * Convenience: mint a token AND build the attach URL in one call.
package/dist/token.d.ts CHANGED
@@ -5,10 +5,9 @@
5
5
  * Why a re-export and not a copy? The auth module is the single source
6
6
  * of truth — both Worker (verify) and SDK (mint) call the same code
7
7
  * paths so wire-format drift is structurally impossible. The
8
- * `@nimbus-sh/worker` peer-dependency is OPTIONAL (declared in
9
- * package.json#peerDependenciesMeta); consumers who only mint tokens
10
- * outside a Worker can install just `@nimbus-sh/sdk` and the
11
- * worker peer-dep is tree-shaken to its auth subpath.
8
+ * `@nimbus-sh/worker` provides the shared auth implementation. The SDK
9
+ * package depends on that single source of truth so token wire-format
10
+ * drift is structurally impossible.
12
11
  *
13
12
  * @example mint
14
13
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC"}
package/dist/token.js CHANGED
@@ -5,10 +5,9 @@
5
5
  * Why a re-export and not a copy? The auth module is the single source
6
6
  * of truth — both Worker (verify) and SDK (mint) call the same code
7
7
  * paths so wire-format drift is structurally impossible. The
8
- * `@nimbus-sh/worker` peer-dependency is OPTIONAL (declared in
9
- * package.json#peerDependenciesMeta); consumers who only mint tokens
10
- * outside a Worker can install just `@nimbus-sh/sdk` and the
11
- * worker peer-dep is tree-shaken to its auth subpath.
8
+ * `@nimbus-sh/worker` provides the shared auth implementation. The SDK
9
+ * package depends on that single source of truth so token wire-format
10
+ * drift is structurally impossible.
12
11
  *
13
12
  * @example mint
14
13
  * ```ts
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @nimbus-sh/sdk/worker - Cloudflare Worker embedder surface.
3
+ *
4
+ * This is the public entrypoint for deploying Nimbus itself inside a
5
+ * Worker. The implementation is provided by @nimbus-sh/worker, but apps
6
+ * should import through the SDK so the interactive app and programmatic
7
+ * sandbox APIs share one public package surface.
8
+ */
9
+ export { NimbusSession, SupervisorRPC, NimbusAssetsRPC, NimbusLoaderRPC, NimbusLoadedWorker, NimbusLoadedEntrypoint, NimbusDurableObjectNamespace, NimbusDOStub, CirrusHmrRPC, createNimbusHandler, issueNimbusToken, verifyNimbusToken, NimbusAuthError, } from '@nimbus-sh/worker';
10
+ export type { NimbusHandler, NimbusHooks, NimbusHookContext, CustomRoutes, CreateNimbusHandlerOptions, NimbusRemoteApiConfig, NimbusRuntimePolicy, NimbusSandboxProfile, NimbusSdkConfig, NimbusSdkRouterConfig, AuthMode, NimbusAuthConfig, NimbusAuthEnv, NimbusTokenClaims, VerifiedNimbusToken, } from '@nimbus-sh/worker';
11
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,4BAA4B,EAC5B,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC"}
package/dist/worker.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @nimbus-sh/sdk/worker - Cloudflare Worker embedder surface.
3
+ *
4
+ * This is the public entrypoint for deploying Nimbus itself inside a
5
+ * Worker. The implementation is provided by @nimbus-sh/worker, but apps
6
+ * should import through the SDK so the interactive app and programmatic
7
+ * sandbox APIs share one public package surface.
8
+ */
9
+ export { NimbusSession, SupervisorRPC, NimbusAssetsRPC, NimbusLoaderRPC, NimbusLoadedWorker, NimbusLoadedEntrypoint, NimbusDurableObjectNamespace, NimbusDOStub, CirrusHmrRPC, createNimbusHandler, issueNimbusToken, verifyNimbusToken, NimbusAuthError, } from '@nimbus-sh/worker';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nimbus-sh/sdk",
3
- "version": "0.1.0",
4
- "description": "Nimbus SDK — programmatic sandboxes, token mint, types, and Worker client helpers.",
3
+ "version": "0.1.2",
4
+ "description": "Nimbus SDK — Worker embedder, programmatic sandboxes, token mint, and client helpers.",
5
5
  "homepage": "https://github.com/AshishKumar4/Nimbus",
6
6
  "repository": {
7
7
  "type": "git",
@@ -35,6 +35,11 @@
35
35
  "types": "./dist/sandbox.d.ts",
36
36
  "import": "./dist/sandbox.js"
37
37
  },
38
+ "./worker": {
39
+ "workspace": "./src/worker.ts",
40
+ "types": "./dist/worker.d.ts",
41
+ "import": "./dist/worker.js"
42
+ },
38
43
  "./errors": {
39
44
  "workspace": "./src/errors.ts",
40
45
  "types": "./dist/errors.d.ts",
@@ -52,14 +57,11 @@
52
57
  "typecheck": "tsc --noEmit"
53
58
  },
54
59
  "peerDependencies": {
55
- "@nimbus-sh/worker": "^0.1.0"
56
- },
57
- "peerDependenciesMeta": {
58
- "@nimbus-sh/worker": { "optional": true }
60
+ "@nimbus-sh/worker": "^0.1.2"
59
61
  },
60
62
  "devDependencies": {
61
63
  "@cloudflare/workers-types": "^4.20250327.0",
62
- "@nimbus-sh/worker": "^0.1.0",
64
+ "@nimbus-sh/worker": "^0.1.2",
63
65
  "typescript": "^5.7.0"
64
66
  },
65
67
  "publishConfig": {