# __PACKAGE_NAME__ Component Template This project was generated with `alga create component`. It targets the Alga extension runner using the WebAssembly Component Model and [`componentize-js`](https://github.com/bytecodealliance/componentize-js). ## Available scripts - `npm run build` – build the extension using the Alga CLI (compiles TypeScript and produces WASM) - `npm run pack` – package the extension into a distributable bundle - `npm run clean` – remove build artifacts ## Project structure - `src/` – TypeScript sources implementing the `handler` export defined in `wit/extension-runner.wit`. - `src/types.ts` – convenience copies of the WIT data structures for use in TypeScript. - `wit/extension-runner.wit` – WIT world definitions describing the host capabilities exposed by the runner. - `dist/` – build output (`dist/js` for the intermediate JS bundle, `dist/main.wasm` for the component artifact). ## Building **Using the Alga CLI (recommended):** ```bash npm install npm run build # runs: alga build ``` Or directly with the CLI: ```bash alga build ``` The final component artifact will be written to `dist/main.wasm`. ## Packaging ```bash npm run pack # runs: alga pack ``` This creates a `bundle.tar.zst` archive containing the manifest, WASM component, and any UI assets. ## Using Host Capabilities To use host capabilities like logging, user info, secrets, or storage, you need to: 1. **Create a wrapper `index.ts`** that imports WIT functions and builds `HostBindings` 2. **Use a custom build script** with external imports ### Example: Accessing User Info Create `src/index.ts`: ```typescript import { handler as userHandler } from './handler-impl.js'; import { ExecuteRequest, ExecuteResponse, HostBindings, normalizeUserData } from '@alga-psa/extension-runtime'; // @ts-ignore - WIT imports resolved at runtime import { getUser } from 'alga:extension/user-v2'; // @ts-ignore import { logInfo, logWarn, logError } from 'alga:extension/logging'; // @ts-ignore import { getContext } from 'alga:extension/context'; const host: HostBindings = { context: { get: async () => getContext() }, logging: { info: async (msg) => logInfo(msg), warn: async (msg) => logWarn(msg), error: async (msg) => logError(msg), }, user: { getUser: async () => normalizeUserData(await getUser()) }, // Add other bindings as needed }; export async function handler(request: ExecuteRequest): Promise { return userHandler(request, host); } ``` Rename your handler to `src/handler-impl.ts` and update the signature: ```typescript import { ExecuteRequest, ExecuteResponse, HostBindings, jsonResponse } from '@alga-psa/extension-runtime'; export async function handler(request: ExecuteRequest, host: HostBindings): Promise { // Now you can use host bindings const user = await host.user.getUser(); await host.logging.info(`Request from ${user.userName}`); return jsonResponse({ ok: true, user: { name: user.userName, type: user.userType }, }); } ``` Update `package.json` with a custom build: ```json { "scripts": { "build:backend": "esbuild src/index.ts --bundle --format=esm --platform=neutral --outfile=dist/js/index.js --external:alga:extension/secrets --external:alga:extension/http --external:alga:extension/storage --external:alga:extension/logging --external:alga:extension/ui-proxy --external:alga:extension/context --external:alga:extension/user --external:alga:extension/user-v2", "build:component": "jco componentize dist/js/index.js --wit ./wit/extension-runner.wit --world-name runner --disable all --out dist/main.wasm", "build": "npm run build:backend && npm run build:component" }, "devDependencies": { "@bytecodealliance/jco": "^1.8.0", "esbuild": "^0.20.0" } } ``` ## Available Host Capabilities | Capability | Interface | Description | |------------|-----------|-------------| | `cap:context.read` | `context` | Execution context (tenant, extension IDs) | | `cap:secrets.get` | `secrets` | Install-scoped secrets | | `cap:http.fetch` | `http` | Outbound HTTP requests | | `cap:storage.kv` | `storage` | Key-value storage | | `cap:log.emit` | `logging` | Structured logging | | `cap:ui.proxy` | `ui-proxy` | UI proxy routes | | `cap:user.read` | `user` | Current user info (default) | | `cap:scheduler.manage` | `scheduler` | Scheduled tasks | | `cap:invoice.manual.create` | `invoicing` | Create draft manual invoices | See the [User Host API Guide](../../../docs/guides/user-host-api.md), [Scheduler Host API Guide](../../../docs/guides/scheduler-host-api.md), and [Invoicing Host API Guide](../../../docs/guides/invoicing-host-api.md) for detailed usage. ## Next steps - Implement your business logic inside `src/handler.ts` (or `src/handler-impl.ts` if using host bindings). - Use the host capabilities to interact with secrets, storage, user info, etc. - Add tests (e.g., using Vitest) that exercise your handler logic. - When ready, run `npm run build` and `npm run pack` to create a distributable bundle. - Use `alga extension publish` to upload your extension to an Alga instance.