AssemblyScript SDK

0.4 NEW — пишем плагин на AssemblyScript (TypeScript-подобный синтаксис), компилируем через asc.

Установка тулчейна

brew install node               # Node 18+ обязателен (top-level await в asc)

assemblyscript сам подтянется через npm install в проект.

Минимальный плагин

wasm_modules/hello-as/manifest.json:

{
  "id": "hello_as",
  "name": "Hello (AssemblyScript)",
  "version": "0.1.0",
  "target": "server",
  "language": "as",
  "abi_version": 1
}

wasm_modules/hello-as/package.json:

{
  "name": "hello_as",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "build": "asc assembly/index.ts -o plugin.wasm --runtime stub --optimize --use abort= --exportRuntime"
  },
  "devDependencies": { "assemblyscript": "^0.27.0" },
  "dependencies": { "@lampac/sdk": "file:../../wasm_sdk/assemblyscript" }
}

wasm_modules/hello-as/assembly/index.ts:

import * as lampac from "@lampac/sdk/assembly/lampac";

export function alloc(size: u32): usize { return lampac.alloc(size); }
export function abi_version(): u32 { return 1; }

export function handle(ptr: usize, length: u32): u64 {
    const inv = lampac.readInvocation(ptr, length);
    lampac.info("hello from AS, path=" + inv.path);
    const q = lampac.queryGet(inv, "q");
    return lampac.writeJSON(`{"type":"movie","data":[{"name":"Hello, ${q}"}]}`);
}

Сборка:

npm install
npm run build
# Output: plugin.wasm — ~12 KB

API SDK

wasm_sdk/assemblyscript/assembly/lampac.ts экспортирует:

Логирование

lampac.debug("…");
lampac.info("…");
lampac.warn("…");
lampac.error("…");

HTTP

const req = new lampac.HTTPRequest();
req.url = "https://api.example.com/x";
req.method = "GET";              // optional, default GET
req.timeoutMs = 5000;            // optional
req.headers.set("User-Agent", "lampac");
const resp = lampac.http(req);
// resp.status, resp.body (Uint8Array), resp.error

Proxy URL

const url = lampac.proxyURL(
    "https://cdn.example.com/movie.m3u8",
    "hello_as",
    new Map<string, string>()  // headers, may be empty
);

Кеш

lampac.cacheSet("key", new TextEncoder().encode("value"), 60);
const v = lampac.cacheGet("key");  // Uint8Array | null

Invocation

const inv = lampac.readInvocation(ptr, length);
// inv.raw, inv.path, inv.requestIP, inv.config (JSON-substring)
const q = lampac.queryGet(inv, "id");

Ответ

return lampac.writeResponse(bytes);   // Uint8Array
return lampac.writeJSON("{\"type\":\"movie\"}"); // shortcut for JSON strings

Размер бинарника

AssemblyScript плагин уровня echo (HTTP + cache + proxy + log) собирается в ~15 КБ. С опцией --optimize это в 25-30 раз меньше TinyGo’шного эквивалента.

Подводные камни

  • Node 18+ обязателенasc использует await import("child_process") на верхнем уровне модуля. Node 12 / 14 не запустит сборку (SyntaxError: Unexpected reserved word).
  • --use abort= в опциях сборки — без него asc эмитит abort-импорт, который наш host не предоставляет (плагин не загрузится).
  • Mini-JSON — наш SDK не тащит полноценный JSON-парсер. Для глубокого парсинга подключи as-json или похожее.
  • Map<string, string> в asc — это полноценная коллекция, но String.UTF8.encode возвращает ArrayBuffer, а не Uint8Array; SDK обёртки скрывают этот мисматч.

Полный пример

См. wasm_modules/echo_as — все host-импорты разом, ровно та же логика что в echo (TinyGo) и echo_c.