Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

5.0 KiB
Raw Permalink Blame History

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.

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):

npm install
npm run build    # runs: alga build

Or directly with the CLI:

alga build

The final component artifact will be written to dist/main.wasm.

Packaging

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:

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<ExecuteResponse> {
  return userHandler(request, host);
}

Rename your handler to src/handler-impl.ts and update the signature:

import { ExecuteRequest, ExecuteResponse, HostBindings, jsonResponse } from '@alga-psa/extension-runtime';

export async function handler(request: ExecuteRequest, host: HostBindings): Promise<ExecuteResponse> {
  // 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:

{
  "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, Scheduler Host API Guide, and Invoicing Host API Guide 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.