@ computesdk/ 北风
计算SDK的Northflank供应商.
每个沙盒都是你Northflank计划中的部署服务. 通过Northflank的Exec API在容器中运行的指令;端口通过服务的公共DNS被曝光.
安装
npm install @computesdk/northflank
设置
- 获取您的 API 令牌 : 团队设置 → API → 托肯斯 → 创建 API 令牌
- 创建( 或选择) Northflank 项目
- 设置环境变量 :
export NORTHFLANK_TOKEN=your_api_token_here
export NORTHFLANK_PROJECT_ID=your_project_id
快速启动
import { northflank } from '@computesdk/northflank';
const compute = northflank({
token: process.env.NORTHFLANK_TOKEN!,
projectId: process.env.NORTHFLANK_PROJECT_ID!,
runtime: 'node',
});
const sandbox = await compute.instances.create();
const result = await sandbox.runCommand(`node -e "console.log('hello from northflank')"`);
console.log(result.stdout);
await sandbox.destroy();
配置
interface NorthflankConfig {
/** Northflank API token */
token: string;
/** Project ID (slug, e.g. "my-project") */
projectId: string;
/** Team ID — required for organization API tokens */
teamId?: string;
/** API host — defaults to https://api.northflank.com */
host?: string;
/** Service name prefix used to identify managed sandboxes — defaults to "computesdk-" */
servicePrefix?: string;
/** Container image — overrides the default for the runtime */
image?: string;
/** Default runtime label when none is passed to create() — any string; defaults to "node". "node" and "python" map to built-in image defaults; anything else needs `image` or `internalDeployment` */
runtime?: string;
/** Northflank deployment plan — defaults to "nf-compute-50" */
deploymentPlan?: string;
/** Default ports to expose on every sandbox */
ports?: { name: string; internalPort: number; public?: boolean; protocol?: 'HTTP' | 'HTTP/2' | 'TCP' | 'UDP' }[];
/** Budget in ms for the first exec to retry while the container starts (default: 120000) */
timeout?: number;
/** Deploy from a Northflank build service instead of an external image */
internalDeployment?: { id: string; branch?: string; buildSHA?: string };
/** Ephemeral storage per container in MB (e.g. 5120 for 5 GiB) */
ephemeralStorageSize?: number;
}
内部部署(建议生产)
默认情况下, 沙盒拉 node:20-slim 编号 : python:3.11-slim (或你的电话) image)来自外部登记册。 关于生产工作量,我们建议从 北岸建筑服务 在同一项目中——内部部署被优化,以更快地冷起而不用依赖外部注册.
const compute = northflank({
token: process.env.NORTHFLANK_TOKEN!,
projectId: process.env.NORTHFLANK_PROJECT_ID!,
internalDeployment: {
id: 'my-build-service', // build service ID in the same project
branch: 'main', // optional — defaults to "main"
buildSHA: 'latest', // optional — defaults to "latest"
},
});
也可以通过 internalDeployment 以每盒为单位 create();它覆盖了配置级别值。 外部图像继续工作—— internalDeployment 只是推荐的路径.
每盒选项
create() 在标准选项之上接受这些针对提供者的选项:
await compute.instances.create({
runtime: 'python', // overrides config.runtime
image: 'my-registry/custom:tag', // overrides config.image and the runtime default
ports: [{ name: 'app', internalPort: 3000 }], // overrides config.ports
deploymentPlan: 'nf-compute-200', // overrides config.deploymentPlan
timeout: 180000, // overrides config.timeout
envs: { LOG_LEVEL: 'debug' }, // merged into runtimeEnvironment
name: 'my-sandbox', // service name (auto-prefixed)
ephemeralStorageSize: 5120, // 5 GiB ephemeral storage per container
});
内建图像默认值 : node → node:20-slim, (中文(简体) ), python → python:3.11-slim。任何其他运行时标签都被接受,但您必须提供 image 或者说 internalDeployment ——没有默认退后.
运行代码
没有 runCode ——直接通过运行时间 runCommand数字 :
// Python
const py = await sandbox.runCommand(`python -c "import json; print(json.dumps({'hello': 'world'}))"`);
// Node.js
const js = await sandbox.runCommand(`node -e "console.log(JSON.stringify({hello: 'world'}))"`);
对于多行脚本,请先写出文件后再引用:
await sandbox.filesystem.writeFile('/tmp/script.py', `
import pandas as pd
print(pd.__version__)
`);
const result = await sandbox.runCommand('python /tmp/script.py');
图标
// Simple command
await sandbox.runCommand('ls -la');
// Working directory
await sandbox.runCommand('npm install', { cwd: '/app' });
// Environment variables
await sandbox.runCommand('echo $MY_VAR', { env: { MY_VAR: 'hello' } });
// Background execution
await sandbox.runCommand('python server.py', { background: true });
文件系统
await sandbox.filesystem.writeFile('/tmp/hello.txt', 'hello world');
const content = await sandbox.filesystem.readFile('/tmp/hello.txt');
await sandbox.filesystem.mkdir('/tmp/data');
const entries = await sandbox.filesystem.readdir('/tmp');
const exists = await sandbox.filesystem.exists('/tmp/hello.txt');
await sandbox.filesystem.remove('/tmp/hello.txt');
文件系统操作向exec代理发送路径作为plain argv元素(例如. ['mkdir', '-p', '--', path])或者通过Northflank's fileCopy API——没有涉及外壳剖析,因此路径不需要逃跑. 仅 runCommand (实际上引用了外壳) env 编号 : cwd 值它会插入.
沙盒管理
// List managed sandboxes (filtered by servicePrefix)
const sandboxes = await compute.instances.list();
// Look up by service ID (slug of the service name)
const sandbox = await compute.instances.getById('computesdk-1700000000-abc123');
// Inspect — refetches the live deployment status
const info = await sandbox.getInfo();
console.log(info.id, info.status, info.createdAt);
// Get the public URL for a port — exposes it dynamically if not already public
const url = await sandbox.getUrl({ port: 3000 });
await sandbox.destroy();
页:1
- 服务名称
<servicePrefix><timestamp>-<random>(或<servicePrefix><name>如果你通过了name) (中文(简体) ).list, (中文(简体) ),getById财务报告和审定财务报表destroy只运行于名称以前缀开头的服务. create在创建服务的 Northflank API 呼叫之后立即返回 没有 等待容器准备好。 第一个runCommand因此,(或文件系统调用)可能需要更长的时间:它重复瞬变执行失败(最多到timeoutms),而吊舱完成开始. 一旦一个Exec成功,之后的电话直接运行,没有重试.list返回每个前缀服务,无论部署状态如何。 使用getInfo检查每个人的状态,并在必要时过滤客户端.getInfo从API的每通电话中重新读取服务——running表示部署状态是COMPLETED服务没有暂停;stopped意味着暂停,PENDING,或IN_PROGRESS· ;error表示FAILED。 。 。 .getUrl将补补服务端口配置, 如果尚未将请求的端口公开, 然后返回其端口dns。 。 。 .
限制
- 启动时间 ——Northflank拉出并启动图像;期望数十秒.
- 内存和 CPU - 以选定的
deploymentPlan。 。 。 . - 文件持久性 ——文件存放于容器内,服务被破坏后会丢失.
支助
许可证
麻省理工学院