Applet Guide: Sandboxed Execution, Typed CSV Output # Overview An applet is a flat, reusable `.applet.js` script stored in the VFS that queries Dashback REST endpoints and computes tabular data. Applets return structured, semicolon-separated (`;`) typed CSV conforming to output metadata headers. Applets can be executed by: 1. `javascript_execute` tool using `{ "appletvfsfile": ".applet.js", "applet_input": { ... } }`. 2. REST API endpoint `POST /vfs/.applet.js` with `{ "input": { ... } }`. --- # Every `.applet.js` file MUST start with three metadata lines: ``` // @applet-input-schema {"type":"object","properties":{...},"required":[...]} // @applet-output-schema name:type;name:type // @applet-description "Lorem ipsum" ``` `@applet-input-schema` - JSON Schema object (`"type": "object"`). - Parameter descriptions in the schema are optional `@applet-output-schema` - Semicolon-separated (`col1:type;col2:type;...`) column declarations. - Bare column names without `:type` default to `string`. - Allowed data types: - `string`: plain text or serialized object. - `integer`: truncated integer number. - `number`: floating-point number. - `boolean`: boolean value (`true`, `false`, `1`, `0`, `"true"`, `"false"`). - `date`: Date object or ISO string. `@applet-description` - Short human-readable summary of what the applet computes (e.g. `"Article catalogue with net prices"`). --- # Execution Environment & Globals Applets run in an isolated worker thread pool sandbox. - **Entry point**: Export an async function taking `applet_input`: ```javascript module.exports = async function (applet_input) { ... }; ``` - **No `require()` or `import`**: Attempting to import modules throws an error. - **Pre-injected Globals**: - `fetch(path, options)`: Authenticated `fetch` pre-configured with a JWT scoped to the current user and selected company. Use root-relative API routes, e.g. `fetch('/article/42000009')`. - `fs`: Sandboxed filesystem interface for reading/writing local company files. - `ExcelJS`: Pre-injected spreadsheet library. - `PDFDocument`: Pre-injected PDFKit library. - `sharp`: Pre-injected image manipulation library. - `crypto`: Node / WebCrypto API. - `console.log(...)`: returned in the tool response --- # Return Value & Typed CSV Mapping The exported function must return: - An **Array of row objects**: `[ { col1: 'val1', col2: 10 }, { col1: 'val2', col2: 20 } ]` - Or a **Single row object**: `{ col1: 'val1', col2: 10 }` (treated as a 1-row table) --- # Standard Applet Template ```javascript // @applet-input-schema {"type":"object","properties":{"sku":{"type":"string","title":"Article SKU","description":"SKU to lookup"}},"required":["sku"]} // @applet-output-schema sku:string;name:string;netPrice:number;tracked:boolean;brand:string // @applet-description "Lorem ipsum" module.exports = async function (applet_input) { const sku = String(applet_input?.sku || '').trim(); if (!sku) { throw new Error('Missing required parameter: sku'); } const res = await fetch(`/article/${encodeURIComponent(sku)}`); if (res.status === 404) throw new Error(`Article "${sku}" not found.`); if (!res.ok) throw new Error(`GET /article/${sku} failed with status ${res.status}`); const { article } = await res.json(); const price = (article.prices || [])[0]; console.log(`Found article ${article.sku}: ${article.name}`); return [{ sku: article.sku, name: article.name || '', netPrice: price?.net ?? '', tracked: Boolean(article.track_stock), brand: article.brand?.name || '' }]; }; ``` --- # Common Implementation Patterns ### 1. Paging List Endpoints Page using `offset` and `limit` until all items are loaded or `limit` is reached: ```javascript const items = []; let offset = 0; while (true) { const res = await fetch(`/order?offset=${offset}&limit=100`); if (!res.ok) throw new Error(`Fetch failed: ${res.status}`); const data = await res.json(); const page = data.orders || []; items.push(...page); offset += page.length; if (page.length === 0 || offset >= (data.total ?? items.length)) break; } ``` --- # Shipped Reference Applets Pre-installed examples in the VFS root provide working reference code: - `v1-article-lookup.applet.js`: Single entity lookup and key/value sheet generation. - `v1-article-catalogue.applet.js`: Walking category trees and joining category article lists. - `v1-category-inventory.applet.js`: Recursive tree flattening and depth calculation. - `v1-delivery-register.applet.js`: Paged list fetching with batched detail requests. - `v1-order-revenue-by-month.applet.js`: Paged order retrieval with calendar month aggregation.