MUST use when writing Bun/TypeScript scripts.
Place scripts in a folder. After writing, tell the user they can run:
wmill generate-metadata - Generate .script.yaml and .lock fileswmill sync push - Deploy to WindmillDo NOT run these commands yourself. Instead, inform the user that they should run them.
Use wmill resource-type list --schema to discover available resource types.
Bun runtime with full npm ecosystem and fastest execution.
Export a single async function called main:
export async function main(param1: string, param2: number) {
// Your code here
return { result: param1, count: param2 };
}
Do not call the main function. Libraries are installed automatically.
On Windmill, credentials and configuration are stored in resources and passed as parameters to main.
Use the RT namespace for resource types:
export async function main(stripe: RT.Stripe) {
// stripe contains API key and config from the resource
}
Only use resource types if you need them to satisfy the instructions. Always use the RT namespace.
Before using a resource type, check the rt.d.ts file in the project root to see all available resource types and their fields. This file is generated by wmill resource-type generate-namespace.
import Stripe from "stripe";
import { someFunction } from "some-package";
Import the windmill client for platform interactions:
import * as wmill from "windmill-client";
See the SDK documentation for available methods.
For preprocessor scripts, the function should be named preprocessor and receives an event parameter:
type Event = {
kind:
| "webhook"
| "http"
| "websocket"
| "kafka"
| "email"
| "nats"
| "postgres"
| "sqs"
| "mqtt"
| "gcp";
body: any;
headers: Record<string, string>;
query: Record<string, string>;
};
export async function preprocessor(event: Event) {
return {
param1: event.body.field1,
param2: event.query.id,
};
}
Windmill provides built-in support for S3-compatible storage operations.
The S3Object type represents a file in S3 storage:
type S3Object = {
s3: string; // Path within the bucket
};
import * as wmill from "windmill-client";
// Load file content from S3
const content: Uint8Array = await wmill.loadS3File(s3object);
// Load file as stream
const blob: Blob = await wmill.loadS3FileStream(s3object);
// Write file to S3
const result: S3Object = await wmill.writeS3File(
s3object, // Target path (or undefined to auto-generate)
fileContent, // string or Blob
s3ResourcePath // Optional: specific S3 resource to use
);
Import: import * as wmill from 'windmill-client'
workerHasInternalServer(): boolean
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
$res:path/**
/**
/**
/**
getStatePath().
*/
async setState(state: any, path?: string): Promise<void>/**
/**
/**
/**
/**
/**
getStatePath().
*/
async getState(path?: string): Promise<any>/**
/**
/**
async polarsConnectionSettings(s3_resource_path: string | undefined): Promise<any>
async duckdbConnectionSettings(s3_resource_path: string | undefined): Promise<any>
/**
/**
*/ async loadS3File(s3object: S3Object, s3ResourcePath: string | undefined = undefined): Promise<Uint8Array | undefined>
/**
*/ async loadS3FileStream(s3object: S3Object, s3ResourcePath: string | undefined = undefined): Promise<Blob | undefined>
/**
*/ async writeS3File(s3object: S3Object | undefined, fileContent: string | Blob, s3ResourcePath: string | undefined = undefined, contentType: string | undefined = undefined, contentDisposition: string | undefined = undefined): Promise<S3Object>
/**
/**
/**
/**
/**
This allows pre-approvals that can be consumed by any later suspend step in the same flow.
/**
/**
/**
/**
/**
/**
JobService.getSlackApprovalPayload call fails.
/**
JobService.getTeamsApprovalPayload call fails.
/**
setWorkflowCtx(ctx: WorkflowCtx | null): void
async sleep(seconds: number): Promise<void>
async step<T>(name: string, fn: () => T | Promise<T>): Promise<T>
/**
/**
/**
step() to/**
getResumeUrls() (wrapped in step()) to obtain resume/cancel/approvalPage/**
fn(item), which should be a task().concurrency (default: all at once)./**
/**
WHERE name = ${name} AND age = ${age}::int
/**
WHERE name = ${name} AND age = ${age}