{"version":3,"file":"index.mjs","names":["events: ProcessOutputEvent[]","status: \"running\" | \"exited\""],"sources":["../../../src/providers/upstash/index.ts"],"sourcesContent":["import { Box, type BoxConfig, type ExecStreamChunk } from \"@upstash/box\";\nimport { SandboxError } from \"../../core/errors\";\nimport type { SandboxNetworkPolicy, SandboxProvider } from \"../../core/provider\";\nimport type {\n  CommandInput,\n  ProcessOutputEvent,\n  RunOptions,\n  SandboxProcess,\n  SandboxSnapshot,\n} from \"../../core/types\";\nimport { withManagedSessions } from \"../../internal/managed-provider\";\nimport {\n  commandString,\n  portResult,\n  toUint8Array,\n  unsupported,\n} from \"../../internal/provider-utils\";\nimport { upstashCapabilities } from \"../capabilities\";\n\nexport type UpstashOptions = Omit<BoxConfig, \"env\"> & {\n  /** Expose ports publicly. Set to false to return bearer-token URLs. */\n  public?: boolean;\n};\n\nexport { upstashCapabilities } from \"../capabilities\";\n\nexport function upstash(options: UpstashOptions = {}): SandboxProvider<Box> {\n  const { public: publicPorts = true, ...boxOptions } = options;\n\n  return withManagedSessions(\n    {\n      id: \"upstash\",\n      capabilities: upstashCapabilities,\n      async create(createOptions) {\n        assertNotAborted(createOptions.signal);\n        const raw = await Box.create({\n          ...boxOptions,\n          env: { ...createOptions.env },\n          timeout: boxOptions.timeout ?? createOptions.timeout,\n        });\n        const remoteCwd = raw.cwd;\n        const toRemotePath = (path: string) =>\n          replacePathPrefix(path, createOptions.cwd, remoteCwd);\n        const toVirtualPath = (path: string) =>\n          replacePathPrefix(path, remoteCwd, createOptions.cwd);\n\n        return {\n          id: raw.id,\n          raw,\n          capabilities: upstashCapabilities,\n          files: {\n            async write(path, value) {\n              const content = Buffer.from(await toUint8Array(value)).toString(\"base64\");\n              await raw.files.write({\n                path: toRemotePath(path),\n                content,\n                encoding: \"base64\",\n              });\n            },\n            async read(path) {\n              const content = await raw.files.read(toRemotePath(path), {\n                encoding: \"base64\",\n              });\n              return new Uint8Array(Buffer.from(content, \"base64\"));\n            },\n            async list(path) {\n              return (await raw.files.list(toRemotePath(path))).map((entry) => ({\n                name: entry.name,\n                path: toVirtualPath(entry.path),\n                type: entry.is_dir ? (\"directory\" as const) : (\"file\" as const),\n                size: entry.size,\n              }));\n            },\n            async mkdir(path) {\n              const result = await raw.exec.command(`mkdir -p ${shellQuote(toRemotePath(path))}`);\n              assertCommandSucceeded(result.exitCode, result.result, \"files.mkdir\");\n            },\n            async remove(path) {\n              const result = await raw.exec.command(`rm -rf -- ${shellQuote(toRemotePath(path))}`);\n              assertCommandSucceeded(result.exitCode, result.result, \"files.remove\");\n            },\n            async exists(path) {\n              const result = await raw.exec.command(`test -e ${shellQuote(toRemotePath(path))}`);\n              return result.exitCode === 0;\n            },\n          },\n          async run(command, runOptions) {\n            assertNotAborted(runOptions.signal);\n            const started = performance.now();\n            const run = await raw.exec.command(\n              scopedCommand(command, runOptions, createOptions.cwd, remoteCwd),\n            );\n            if (runOptions.timeout !== undefined && run.exitCode === 124) {\n              throw new SandboxError({\n                code: \"timeout\",\n                provider: \"upstash\",\n                operation: \"process.run\",\n                message: `Command timed out after ${runOptions.timeout}ms`,\n              });\n            }\n            return {\n              stdout: run.result,\n              stderr: \"\",\n              exitCode: run.exitCode ?? 1,\n              success: run.exitCode === 0,\n              durationMs: Math.round(performance.now() - started),\n            };\n          },\n          async start(command, runOptions) {\n            assertNotAborted(runOptions.signal);\n            const handle = await raw.exec.stream(\n              scopedCommand(command, runOptions, createOptions.cwd, remoteCwd),\n            );\n            const events: ProcessOutputEvent[] = [];\n            const waiters = new Set<() => void>();\n            let status: \"running\" | \"exited\" = \"running\";\n            let exitCode = 1;\n            const wake = () => {\n              for (const waiter of waiters) waiter();\n              waiters.clear();\n            };\n            const streamCompleted = consumeStream(handle, (chunk) => {\n              if (chunk.type === \"output\") {\n                events.push({\n                  stream: \"stdout\",\n                  data: chunk.data,\n                  timestamp: new Date(),\n                });\n                wake();\n              } else {\n                exitCode = chunk.exitCode;\n              }\n            })\n              .then(() => {\n                if (status === \"running\") status = \"exited\";\n                return { exitCode };\n              })\n              .catch((error: unknown) => {\n                status = \"exited\";\n                throw error;\n              })\n              .finally(() => {\n                wake();\n              });\n\n            return {\n              id: handle.id,\n              async status() {\n                return status;\n              },\n              async *output() {\n                let index = 0;\n                while (status === \"running\" || index < events.length) {\n                  while (index < events.length) yield events[index++]!;\n                  if (status !== \"running\") break;\n                  await new Promise<void>((resolve) => waiters.add(resolve));\n                }\n              },\n              async write() {\n                unsupported(\"upstash\", \"process.stdin\");\n              },\n              wait: () => streamCompleted,\n              async kill() {\n                unsupported(\"upstash\", \"process.cancel\");\n              },\n            } satisfies SandboxProcess;\n          },\n          async expose(port) {\n            const preview = await raw.getPublicURL(\n              port,\n              publicPorts ? undefined : { bearerToken: true },\n            );\n            const token = preview.token;\n            return portResult(\n              port,\n              preview.url,\n              !token,\n              Boolean(token),\n              token\n                ? (path = \"/\", init = {}) =>\n                    fetch(new URL(path, preview.url), {\n                      ...init,\n                      headers: {\n                        ...Object.fromEntries(new Headers(init.headers)),\n                        authorization: `Bearer ${token}`,\n                      },\n                    })\n                : undefined,\n            );\n          },\n          snapshots: {\n            async create(snapshotOptions) {\n              const snapshot = await raw.snapshot({\n                name: snapshotOptions?.name ?? `sandbox-sdk-${Date.now()}`,\n              });\n              return {\n                id: snapshot.id,\n                name: snapshot.name,\n                mode: \"filesystem\",\n                createdAt: timestamp(snapshot.created_at),\n              } satisfies SandboxSnapshot;\n            },\n            async delete(snapshot) {\n              await raw.deleteSnapshot(typeof snapshot === \"string\" ? snapshot : snapshot.id);\n            },\n            async restore() {\n              unsupported(\"upstash\", \"snapshot.restore\");\n            },\n          },\n          async stop() {\n            await raw.delete();\n          },\n        };\n      },\n    },\n    [],\n    {\n      stop: (sandbox) => sandbox.raw.pause(),\n      resume: (sandbox) => sandbox.raw.resume(),\n      destroy: (sandbox) => sandbox.raw.delete(),\n      setNetworkPolicy: (sandbox, policy) => sandbox.raw.updateNetworkPolicy(networkPolicy(policy)),\n    },\n  );\n}\n\nasync function consumeStream(\n  stream: AsyncIterable<ExecStreamChunk>,\n  onChunk: (chunk: ExecStreamChunk) => void,\n): Promise<void> {\n  for await (const chunk of stream) onChunk(chunk);\n}\n\nfunction scopedCommand(\n  input: CommandInput,\n  options: RunOptions,\n  virtualCwd: string,\n  remoteCwd: string,\n): string {\n  const environment = Object.entries(options.env ?? {}).map(([key, value]) =>\n    shellQuote(`${key}=${value}`),\n  );\n  const command = commandString(input);\n  const shell = `sh -c ${shellQuote(command)}`;\n  const timed = options.timeout\n    ? `timeout ${Math.max(1, Math.ceil(options.timeout / 1_000))}s ${shell}`\n    : shell;\n  const cwd = replacePathPrefix(options.cwd ?? virtualCwd, virtualCwd, remoteCwd);\n  return `cd ${shellQuote(cwd)} && ${\n    environment.length ? `env ${environment.join(\" \")} ` : \"\"\n  }${timed} 2>&1`;\n}\n\nfunction replacePathPrefix(path: string, from: string, to: string): string {\n  if (path === from) return to;\n  if (path.startsWith(`${from}/`)) return `${to}${path.slice(from.length)}`;\n  return path;\n}\n\nfunction shellQuote(value: string): string {\n  return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction assertNotAborted(signal?: AbortSignal): void {\n  if (signal?.aborted) throw signal.reason ?? new DOMException(\"Aborted\", \"AbortError\");\n}\n\nfunction assertCommandSucceeded(exitCode: number | null, output: string, operation: string): void {\n  if (exitCode === 0) return;\n  throw new Error(`${operation} failed${output ? `: ${output}` : \"\"}`);\n}\n\nfunction timestamp(value: number): Date {\n  return new Date(value < 1_000_000_000_000 ? value * 1_000 : value);\n}\n\nfunction networkPolicy(policy: SandboxNetworkPolicy): import(\"@upstash/box\").NetworkPolicy {\n  if (policy.mode === \"allow-all\" || policy.mode === \"deny-all\") return { mode: policy.mode };\n  if (policy.mode === \"native\") return policy.value as import(\"@upstash/box\").NetworkPolicy;\n  return {\n    mode: \"custom\",\n    allowedDomains: [...(policy.allowedHosts ?? [])],\n    allowedCidrs: [...(policy.allowedCIDRs ?? [])],\n    deniedCidrs: [...(policy.deniedCIDRs ?? [])],\n  };\n}\n\nexport type UpstashBox = Box;\n"],"mappings":"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"}