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

138 lines
5.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# __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<ExecuteResponse> {
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<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:
```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.