−25%

на годовую оплату Windows, до 31.10. К тарифам

EQVPS
Начать

SDK для песочниц на TypeScript за 5 минут: от npm i @eqvps/sdk до первого запуска

Установите @eqvps/sdk, запустите песочницу на Firecracker из Node.js, Deno или Bun, выполните в ней код на Python, Node и shell, передайте файлы и следите за долгой задачей в реальном времени. Шесть шагов, весь код на месте.

Это руководство запускает песочницу из JavaScript или TypeScript. Вы поднимете изолированную микро-VM на Firecracker, выполните код на трёх языках, передадите файлы и будете получать вывод долгой задачи. Каждый шаг — короткий фрагмент кода.

Нужны Node.js 18+ (или Deno, или Bun) и аккаунт EQVPS.

1. Получите токен

SDK авторизуется обычным токеном аккаунта. Как получить его в кабинете, через API или MCP-сервер, показано на странице подключение аккаунта.

export EQVPS_API_KEY="your-token"

Новый аккаунт без баланса получает $1 кредита на песочницы, когда впервые создаёт песочницу. Этого с запасом хватит на всё руководство много раз.

2. Установите SDK

npm i @eqvps/sdk

Примеры используют ES-модули и await на верхнем уровне. Сохраняйте их как файлы .mjs или как .ts и запускайте через npx tsx.

3. Запустите песочницу и выполните код

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);
});

В выводе будет id песочницы (sb_ и ещё 24 символа), затем 0 3.12.x. Sandbox.with удаляет песочницу, когда колбэк завершился, в том числе если он бросил исключение.

По умолчанию язык — Python. Два других — одна опция:

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);
});

Упавший скрипт исключения не бросает. Проверяйте r.ok: он равен true, когда exit_code равен 0 и команда не упёрлась в таймаут.

4. Команды shell и пакеты

exec принимает строку для shell или массив argv. У песочницы есть доступ в интернет, так что установка через npm и pip работает:

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);
});

Синхронный вызов длится не больше 55 секунд. Всё, что дольше, уходит в фоновую задачу (шаг 6).

5. Файлы

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 принимает строку или Uint8Array. download возвращает Uint8Array, downloadText — строку. Одна передача ограничена 5 MB.

6. Долгие задачи с живым выводом

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
});

Задача возвращается сразу, и ограничения в 55 секунд у неё нет. wait по умолчанию опрашивает каждые 2 секунды (это меняет pollIntervalMs). task.kill() останавливает задачу, sb.task(id) подключается к ней из другого процесса.

Ошибки

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;
}

SDK сам повторяет 429 и 503 до трёх раз, если сервер прислал Retry-After. Самый частый 429 — больше двух одновременных команд на одном аккаунте. Все классы есть в справочнике SDK.

Сколько стоит это руководство

Каждый пример жил несколько секунд, и за него списан минимум в 60 секунд: $0.00055 на small, $0.0011 на standard. Задача из шага 6 работала около 100 секунд на standard, это примерно $0.002. Всё вместе — заметно меньше цента. Полный прайс — в разделе лимиты и оплата песочниц.

Что дальше

Частые вопросы

Какие среды поддерживает @eqvps/sdk?

Node.js 18 и новее, Deno и Bun. Зависимостей нет, используется встроенный fetch, поэтому SDK работает и в браузере, но токен аккаунта во фронтенд-код не кладите.

Может ли песочница выполнять Python, если моё приложение на TypeScript?

Да. Язык вашего приложения и язык кода в песочнице не связаны. run принимает language python, node или bash, а exec выполняет любую команду shell.

Как гарантировать, что песочница удалится?

Используйте Sandbox.with(options, fn): песочница удаляется, когда fn завершилась или бросила исключение. В TypeScript 5.2 и новее можно писать await using sb = await Sandbox.create().

Что возвращает run, если код упал?

ExecResult с ненулевым exit_code и ошибкой в stderr. Исключения нет. Исключения бывают только при ошибках API, например при неверном токене или пустом балансе.

Комментарии

Пока нет комментариев. Будьте первым.

Оставить комментарий

Комментарии проходят модерацию перед публикацией.