−25%

auf Windows bei Jahreszahlung, bis 31.10. Zu den Tarifen

EQVPS
Loslegen

TypeScript-SDK für Sandboxes in 5 Minuten: von npm i @eqvps/sdk zum ersten Lauf

Installieren Sie @eqvps/sdk, starten Sie eine Firecracker-Sandbox aus Node.js, Deno oder Bun, führen Sie darin Python-, Node- und Shell-Code aus, übertragen Sie Dateien und streamen Sie einen langen Job. Sechs Schritte mit jeder Codezeile.

Diese Anleitung bringt eine Sandbox aus JavaScript oder TypeScript zum Laufen. Sie starten eine isolierte Firecracker-MicroVM, führen Code in drei Sprachen aus, übertragen Dateien und streamen die Ausgabe eines langen Jobs. Jeder Schritt ist ein kurzes Snippet.

Sie brauchen Node.js 18+ (oder Deno, oder Bun) und ein EQVPS-Konto.

1. Token besorgen

Das SDK authentifiziert sich mit einem gewöhnlichen Konto-Token. Konto verbinden zeigt, wie Sie ihn über Dashboard, API oder MCP-Server bekommen.

export EQVPS_API_KEY="your-token"

Ein neues Konto ohne Guthaben erhält $1 Sandbox-Guthaben, wenn es zum ersten Mal eine Sandbox erstellt. Das reicht für diese Anleitung um ein Vielfaches.

2. SDK installieren

npm i @eqvps/sdk

Die Beispiele nutzen ES-Module und Top-Level-await. Speichern Sie sie als .mjs-Dateien oder als .ts und starten Sie sie mit npx tsx.

3. Sandbox starten und Code ausführen

import { Sandbox } from "@eqvps/sdk";

await Sandbox.with({ tariff: "small" }, async (sb) => {
  console.log(sb.id);
  const r = await sb.run("import platform; print(platform.python_version())");
  console.log(r.exit_code, r.stdout);
});

Die Ausgabe ist die Sandbox-ID (sb_ und 24 weitere Zeichen), dann 0 3.12.x. Sandbox.with löscht die Sandbox, wenn der Callback endet, auch wenn er wirft.

Die Standardsprache ist Python. Die anderen beiden sind eine Option entfernt:

await Sandbox.with({}, async (sb) => {
  const js = await sb.run("console.log(process.version)", { language: "node" });
  const sh = await sb.run("uname -r && nproc", { language: "bash" });
  console.log(js.stdout, sh.stdout);
});

Ein fehlschlagendes Skript wirft nicht. Prüfen Sie r.ok, das true ist, wenn exit_code 0 ist und der Befehl nicht ins Timeout lief.

4. Shell-Befehle und Pakete

exec nimmt einen Shell-String oder ein argv-Array. Die Sandbox hat Internetzugang, npm- und pip-Installationen funktionieren also:

await Sandbox.with({ tariff: "small" }, async (sb) => {
  await sb.exec("mkdir -p /root/app && cd /root/app && npm init -y && npm i lodash", { timeout: 55 });
  const r = await sb.exec(["node", "-e", "console.log(require('/root/app/node_modules/lodash').VERSION)"]);
  console.log(r.stdout);
});

Ein synchroner Aufruf darf höchstens 55 Sekunden laufen. Alles Längere gehört in einen Hintergrund-Task (Schritt 6).

5. Dateien

await Sandbox.with({}, async (sb) => {
  await sb.upload("/root/input.json", JSON.stringify({ values: [3, 5, 8] }));
  await sb.run("import json; d = json.load(open('/root/input.json')); open('/root/out.txt', 'w').write(str(sum(d['values'])))");
  console.log(await sb.downloadText("/root/out.txt"));   // 16
});

upload nimmt einen String oder ein Uint8Array. download liefert ein Uint8Array, downloadText einen String. Eine Übertragung ist auf 5 MB begrenzt.

6. Lange Jobs mit Live-Ausgabe

await Sandbox.with({ tariff: "standard" }, async (sb) => {
  const task = await sb.exec("for i in 1 2 3 4 5; do echo step $i; sleep 20; done", { background: true });
  const res = await task.wait({ onOutput: (out) => process.stdout.write(out) });
  console.log(res.state, res.exit_code);   // done 0
});

Der Task kehrt sofort zurück und hat keine 55-Sekunden-Grenze. wait fragt standardmäßig alle 2 Sekunden ab (pollIntervalMs ändert das). task.kill() stoppt ihn, sb.task(id) verbindet sich aus einem anderen Prozess erneut.

Fehler

import { Sandbox, InsufficientBalanceError, RateLimitError } from "@eqvps/sdk";

try {
  await Sandbox.with({}, async (sb) => console.log((await sb.run("print(1)")).stdout));
} catch (e) {
  if (e instanceof InsufficientBalanceError) console.log("Top up the balance");
  else if (e instanceof RateLimitError) console.log("Busy, retry in", e.retryAfter);
  else throw e;
}

Das SDK wiederholt 429 und 503 selbst bis zu dreimal, wenn der Server Retry-After schickt. Das häufigste 429 entsteht, wenn auf einem Konto mehr als zwei Befehle gleichzeitig laufen. Jede Klasse steht in der SDK-Referenz.

Kosten dieser Anleitung

Jedes Beispiel lebte ein paar Sekunden und wurde mit dem 60-Sekunden-Minimum abgerechnet: $0.00055 auf small, $0.0011 auf standard. Der Job aus Schritt 6 lief etwa 100 Sekunden auf standard, rund $0.002. Alles zusammen ist deutlich unter einem Cent. Die vollständige Preisliste steht unter Sandbox-Limits und Abrechnung.

Nächste Schritte

FAQ

Welche Laufzeiten unterstützt @eqvps/sdk?

Node.js 18 und neuer, Deno und Bun. Es hat keine Abhängigkeiten und nutzt das eingebaute fetch, läuft also auch im Browser, aber Ihr Konto-Token gehört nicht in Frontend-Code.

Kann die Sandbox Python ausführen, wenn meine App in TypeScript ist?

Ja. Die Sprache Ihrer App und die Sprache des Sandbox-Codes sind unabhängig. run akzeptiert language python, node oder bash, und exec führt jeden Shell-Befehl aus.

Wie stelle ich sicher, dass die Sandbox gelöscht wird?

Mit Sandbox.with(options, fn): Die Sandbox wird gelöscht, wenn fn endet oder wirft. Ab TypeScript 5.2 geht auch await using sb = await Sandbox.create().

Was gibt run zurück, wenn der Code fehlschlägt?

Ein ExecResult mit einem exit_code ungleich null und dem Fehler in stderr. Es wird nichts geworfen. Exceptions gibt es nur für API-Fehler wie einen ungültigen Token oder leeres Guthaben.

Kommentare

Noch keine Kommentare. Sei der Erste.

Kommentar hinterlassen

Kommentare werden vor der Anzeige moderiert.