windmill-cli 1.700.0 → 1.700.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/main.js +157 -105
- package/package.json +1 -1
package/esm/main.js
CHANGED
|
@@ -16752,7 +16752,7 @@ var init_OpenAPI = __esm(() => {
|
|
|
16752
16752
|
PASSWORD: undefined,
|
|
16753
16753
|
TOKEN: getEnv3("WM_TOKEN"),
|
|
16754
16754
|
USERNAME: undefined,
|
|
16755
|
-
VERSION: "1.700.
|
|
16755
|
+
VERSION: "1.700.2",
|
|
16756
16756
|
WITH_CREDENTIALS: true,
|
|
16757
16757
|
interceptors: {
|
|
16758
16758
|
request: new Interceptors,
|
|
@@ -84945,9 +84945,9 @@ name: raw-app
|
|
|
84945
84945
|
description: MUST use when creating raw apps.
|
|
84946
84946
|
---
|
|
84947
84947
|
|
|
84948
|
-
# Windmill Raw Apps
|
|
84948
|
+
# Windmill Raw Apps — CLI workflow
|
|
84949
84949
|
|
|
84950
|
-
|
|
84950
|
+
This guide covers raw apps from the terminal: scaffolding via \`wmill app new\`, the on-disk layout, and the file-based conventions the CLI uses to represent backend runnables and data table configuration. The platform shape (how a raw app behaves at runtime — frontend bundling, runnable types, datatable SDK calls) is covered in the companion authoring guide.
|
|
84951
84951
|
|
|
84952
84952
|
## Creating a Raw App
|
|
84953
84953
|
|
|
@@ -85016,7 +85016,7 @@ wmill app new
|
|
|
85016
85016
|
|
|
85017
85017
|
This is the wizard. It only works when run by a human in a real terminal. Don't call it this way from an agent.
|
|
85018
85018
|
|
|
85019
|
-
##
|
|
85019
|
+
## On-disk app layout
|
|
85020
85020
|
|
|
85021
85021
|
\`\`\`
|
|
85022
85022
|
my_app{{RAW_APP_SUFFIX}}/
|
|
@@ -85036,11 +85036,7 @@ my_app{{RAW_APP_SUFFIX}}/
|
|
|
85036
85036
|
└── *.sql # SQL files to apply via dev server
|
|
85037
85037
|
\`\`\`
|
|
85038
85038
|
|
|
85039
|
-
## Backend
|
|
85040
|
-
|
|
85041
|
-
Backend runnables are server-side scripts that your frontend can call. They live in the \`backend/\` folder.
|
|
85042
|
-
|
|
85043
|
-
### Creating a Backend Runnable
|
|
85039
|
+
## Backend runnables on disk
|
|
85044
85040
|
|
|
85045
85041
|
Add a code file to the \`backend/\` folder:
|
|
85046
85042
|
|
|
@@ -85050,7 +85046,7 @@ backend/<id>.<ext>
|
|
|
85050
85046
|
|
|
85051
85047
|
The runnable ID is the filename without extension. For example, \`get_user.ts\` creates a runnable with ID \`get_user\`.
|
|
85052
85048
|
|
|
85053
|
-
### Supported
|
|
85049
|
+
### Supported languages (extension-driven)
|
|
85054
85050
|
|
|
85055
85051
|
| Language | Extension | Example |
|
|
85056
85052
|
|------------------|--------------|------------------|
|
|
@@ -85072,27 +85068,14 @@ The runnable ID is the filename without extension. For example, \`get_user.ts\`
|
|
|
85072
85068
|
| C# | \`.cs\` | \`myFunc.cs\` |
|
|
85073
85069
|
| Java | \`.java\` | \`myFunc.java\` |
|
|
85074
85070
|
|
|
85075
|
-
|
|
85076
|
-
|
|
85077
|
-
**backend/get_user.ts:**
|
|
85078
|
-
\`\`\`typescript
|
|
85079
|
-
import * as wmill from 'windmill-client';
|
|
85080
|
-
|
|
85081
|
-
export async function main(user_id: string) {
|
|
85082
|
-
const sql = wmill.datatable();
|
|
85083
|
-
const user = await sql\`SELECT * FROM users WHERE id = \${user_id}\`.fetchOne();
|
|
85084
|
-
return user;
|
|
85085
|
-
}
|
|
85086
|
-
\`\`\`
|
|
85087
|
-
|
|
85088
|
-
After creating, tell the user they can generate lock files by running:
|
|
85071
|
+
After creating a runnable, tell the user they can generate lock files by running:
|
|
85089
85072
|
\`\`\`bash
|
|
85090
85073
|
wmill generate-metadata
|
|
85091
85074
|
\`\`\`
|
|
85092
85075
|
|
|
85093
|
-
### Optional YAML
|
|
85076
|
+
### Optional YAML configuration
|
|
85094
85077
|
|
|
85095
|
-
Add a \`<id>.yaml\` file to configure fields or static values:
|
|
85078
|
+
Add a \`<id>.yaml\` file alongside the code to configure fields or static values:
|
|
85096
85079
|
|
|
85097
85080
|
**backend/get_user.yaml:**
|
|
85098
85081
|
\`\`\`yaml
|
|
@@ -85103,7 +85086,7 @@ fields:
|
|
|
85103
85086
|
value: "default_user"
|
|
85104
85087
|
\`\`\`
|
|
85105
85088
|
|
|
85106
|
-
### Referencing
|
|
85089
|
+
### Referencing existing scripts
|
|
85107
85090
|
|
|
85108
85091
|
To use an existing Windmill script instead of inline code:
|
|
85109
85092
|
|
|
@@ -85119,32 +85102,9 @@ type: flow
|
|
|
85119
85102
|
path: f/my_folder/my_flow
|
|
85120
85103
|
\`\`\`
|
|
85121
85104
|
|
|
85122
|
-
|
|
85123
|
-
|
|
85124
|
-
Import from the auto-generated \`wmill.ts\`:
|
|
85105
|
+
## Data tables — \`raw_app.yaml\` config
|
|
85125
85106
|
|
|
85126
|
-
|
|
85127
|
-
import { backend } from './wmill';
|
|
85128
|
-
|
|
85129
|
-
// Call a backend runnable
|
|
85130
|
-
const user = await backend.get_user({ user_id: '123' });
|
|
85131
|
-
\`\`\`
|
|
85132
|
-
|
|
85133
|
-
The \`wmill.ts\` file provides type-safe access to all backend runnables.
|
|
85134
|
-
|
|
85135
|
-
## Data Tables
|
|
85136
|
-
|
|
85137
|
-
Raw apps can query Windmill datatables (PostgreSQL databases managed by Windmill).
|
|
85138
|
-
|
|
85139
|
-
### Critical Rules
|
|
85140
|
-
|
|
85141
|
-
1. **ONLY USE WHITELISTED TABLES**: You can ONLY query tables listed in \`raw_app.yaml\` → \`data.tables\`. Tables not in this list are NOT accessible.
|
|
85142
|
-
|
|
85143
|
-
2. **ADD TABLES BEFORE USING**: To use a new table, first add it to \`data.tables\` in \`raw_app.yaml\`.
|
|
85144
|
-
|
|
85145
|
-
3. **USE CONFIGURED DATATABLE/SCHEMA**: Check the app's \`raw_app.yaml\` for the default datatable and schema.
|
|
85146
|
-
|
|
85147
|
-
### Configuration in raw_app.yaml
|
|
85107
|
+
The \`data\` block in \`raw_app.yaml\` controls which tables the app can query.
|
|
85148
85108
|
|
|
85149
85109
|
\`\`\`yaml
|
|
85150
85110
|
data:
|
|
@@ -85156,48 +85116,9 @@ data:
|
|
|
85156
85116
|
\`\`\`
|
|
85157
85117
|
|
|
85158
85118
|
**Table reference formats:**
|
|
85159
|
-
- \`<datatable>\`
|
|
85160
|
-
- \`<datatable>/<table>\`
|
|
85161
|
-
- \`<datatable>/<schema>:<table>\`
|
|
85162
|
-
|
|
85163
|
-
### Querying in TypeScript (Bun/Deno)
|
|
85164
|
-
|
|
85165
|
-
\`\`\`typescript
|
|
85166
|
-
import * as wmill from 'windmill-client';
|
|
85167
|
-
|
|
85168
|
-
export async function main(user_id: string) {
|
|
85169
|
-
const sql = wmill.datatable(); // Or: wmill.datatable('other_datatable')
|
|
85170
|
-
|
|
85171
|
-
// Parameterized queries (safe from SQL injection)
|
|
85172
|
-
const user = await sql\`SELECT * FROM users WHERE id = \${user_id}\`.fetchOne();
|
|
85173
|
-
const users = await sql\`SELECT * FROM users WHERE active = \${true}\`.fetch();
|
|
85174
|
-
|
|
85175
|
-
// Insert/Update
|
|
85176
|
-
await sql\`INSERT INTO users (name, email) VALUES (\${name}, \${email})\`;
|
|
85177
|
-
await sql\`UPDATE users SET name = \${newName} WHERE id = \${user_id}\`;
|
|
85178
|
-
|
|
85179
|
-
return user;
|
|
85180
|
-
}
|
|
85181
|
-
\`\`\`
|
|
85182
|
-
|
|
85183
|
-
### Querying in Python
|
|
85184
|
-
|
|
85185
|
-
\`\`\`python
|
|
85186
|
-
import wmill
|
|
85187
|
-
|
|
85188
|
-
def main(user_id: str):
|
|
85189
|
-
db = wmill.datatable() # Or: wmill.datatable('other_datatable')
|
|
85190
|
-
|
|
85191
|
-
# Use $1, $2, etc. for parameters
|
|
85192
|
-
user = db.query('SELECT * FROM users WHERE id = $1', user_id).fetch_one()
|
|
85193
|
-
users = db.query('SELECT * FROM users WHERE active = $1', True).fetch()
|
|
85194
|
-
|
|
85195
|
-
# Insert/Update
|
|
85196
|
-
db.query('INSERT INTO users (name, email) VALUES ($1, $2)', name, email)
|
|
85197
|
-
db.query('UPDATE users SET name = $1 WHERE id = $2', new_name, user_id)
|
|
85198
|
-
|
|
85199
|
-
return user
|
|
85200
|
-
\`\`\`
|
|
85119
|
+
- \`<datatable>\` — All tables in the datatable
|
|
85120
|
+
- \`<datatable>/<table>\` — Specific table in public schema
|
|
85121
|
+
- \`<datatable>/<schema>:<table>\` — Table in specific schema
|
|
85201
85122
|
|
|
85202
85123
|
## SQL Migrations (sql_to_apply/)
|
|
85203
85124
|
|
|
@@ -85206,11 +85127,11 @@ The \`sql_to_apply/\` folder is for creating/modifying database tables during de
|
|
|
85206
85127
|
### Workflow
|
|
85207
85128
|
|
|
85208
85129
|
1. Create \`.sql\` files in \`sql_to_apply/\`
|
|
85209
|
-
2. Run \`wmill app dev\`
|
|
85130
|
+
2. Run \`wmill app dev\` — the dev server watches this folder
|
|
85210
85131
|
3. When SQL files change, a modal appears in the browser to confirm execution
|
|
85211
85132
|
4. After creating tables, **add them to \`data.tables\`** in \`raw_app.yaml\`
|
|
85212
85133
|
|
|
85213
|
-
### Example
|
|
85134
|
+
### Example migration
|
|
85214
85135
|
|
|
85215
85136
|
**sql_to_apply/001_create_users.sql:**
|
|
85216
85137
|
\`\`\`sql
|
|
@@ -85229,12 +85150,12 @@ data:
|
|
|
85229
85150
|
- main/users
|
|
85230
85151
|
\`\`\`
|
|
85231
85152
|
|
|
85232
|
-
### Migration
|
|
85153
|
+
### Migration best practices
|
|
85233
85154
|
|
|
85234
85155
|
- **Use idempotent SQL**: \`CREATE TABLE IF NOT EXISTS\`, etc.
|
|
85235
85156
|
- **Number files**: \`001_\`, \`002_\` for ordering
|
|
85236
85157
|
- **Always whitelist tables** after creation
|
|
85237
|
-
- This folder is NOT synced
|
|
85158
|
+
- This folder is NOT synced — it's for local development only
|
|
85238
85159
|
|
|
85239
85160
|
## CLI Commands
|
|
85240
85161
|
|
|
@@ -85250,14 +85171,145 @@ For everything else, tell the user which command fits their intent and let them
|
|
|
85250
85171
|
| \`wmill sync push\` | Deploy app to Windmill |
|
|
85251
85172
|
| \`wmill sync pull\` | Pull latest from Windmill |
|
|
85252
85173
|
|
|
85174
|
+
|
|
85175
|
+
|
|
85176
|
+
# Windmill Raw Apps
|
|
85177
|
+
|
|
85178
|
+
Raw apps let you build custom frontends with React, Svelte, or Vue that connect to Windmill backend runnables and datatables.
|
|
85179
|
+
|
|
85180
|
+
## App shape
|
|
85181
|
+
|
|
85182
|
+
A raw app has three logical parts:
|
|
85183
|
+
|
|
85184
|
+
- **Frontend** — bundled with esbuild from \`index.tsx\` as the entrypoint. Files include the entrypoint, components (\`App.tsx\`), styles, etc.
|
|
85185
|
+
- **Backend runnables** — server-side scripts the frontend calls, each addressed by a unique key.
|
|
85186
|
+
- **Data** — optional whitelisted datatables (managed PostgreSQL) that the backend runnables can query. The frontend never queries the database directly; backend runnables are the only bridge.
|
|
85187
|
+
|
|
85188
|
+
## Frontend
|
|
85189
|
+
|
|
85190
|
+
### Entrypoint
|
|
85191
|
+
|
|
85192
|
+
\`index.tsx\` is the bundling entrypoint. It typically renders a top-level \`App\` component. The bundler is esbuild.
|
|
85193
|
+
|
|
85194
|
+
### Generated bindings (\`wmill.d.ts\` / \`wmill.ts\`)
|
|
85195
|
+
|
|
85196
|
+
The frontend imports a generated module that mirrors the backend runnables. **Never write to it directly** — it gets regenerated whenever backend runnables change. Modifying it by hand will be overwritten.
|
|
85197
|
+
|
|
85198
|
+
### Calling backend runnables
|
|
85199
|
+
|
|
85200
|
+
Import the generated bindings and call the runnable like a function:
|
|
85201
|
+
|
|
85202
|
+
\`\`\`typescript
|
|
85203
|
+
import { backend } from './wmill';
|
|
85204
|
+
|
|
85205
|
+
// Call a backend runnable
|
|
85206
|
+
const user = await backend.get_user({ user_id: '123' });
|
|
85207
|
+
\`\`\`
|
|
85208
|
+
|
|
85209
|
+
The frontend cannot reach datatables, workspace items, or external services on its own — it goes through \`backend.<key>(args)\` for everything server-side.
|
|
85210
|
+
|
|
85211
|
+
## Backend runnables
|
|
85212
|
+
|
|
85213
|
+
Each runnable has a unique key (used to call it from the frontend) and one of four types:
|
|
85214
|
+
|
|
85215
|
+
| Type | What it is |
|
|
85216
|
+
|---|---|
|
|
85217
|
+
| \`inline\` | Custom code stored on the app itself. Most common for app-specific logic. |
|
|
85218
|
+
| \`script\` | Reference to an existing workspace script by path. |
|
|
85219
|
+
| \`flow\` | Reference to an existing workspace flow by path. |
|
|
85220
|
+
| \`hubscript\` | Reference to a hub script by path. |
|
|
85221
|
+
|
|
85222
|
+
### Inline runnables
|
|
85223
|
+
|
|
85224
|
+
Inline runnables carry their own source code. For file-based raw apps, the runnable language is determined by the backend file extension. The script must expose a \`main\` function as its entrypoint.
|
|
85225
|
+
|
|
85226
|
+
**TypeScript example** (\`backend/get_user.ts\`):
|
|
85227
|
+
|
|
85228
|
+
\`\`\`typescript
|
|
85229
|
+
import * as wmill from 'windmill-client';
|
|
85230
|
+
|
|
85231
|
+
export async function main(user_id: string) {
|
|
85232
|
+
const sql = wmill.datatable();
|
|
85233
|
+
const user = await sql\`SELECT * FROM users WHERE id = \${user_id}\`.fetchOne();
|
|
85234
|
+
return user;
|
|
85235
|
+
}
|
|
85236
|
+
\`\`\`
|
|
85237
|
+
|
|
85238
|
+
**Python example** (\`backend/get_user.py\`):
|
|
85239
|
+
|
|
85240
|
+
\`\`\`python
|
|
85241
|
+
import wmill
|
|
85242
|
+
|
|
85243
|
+
def main(user_id: str):
|
|
85244
|
+
db = wmill.datatable()
|
|
85245
|
+
user = db.query('SELECT * FROM users WHERE id = $1', user_id).fetch_one()
|
|
85246
|
+
return user
|
|
85247
|
+
\`\`\`
|
|
85248
|
+
|
|
85249
|
+
### Path runnables (script / flow / hubscript)
|
|
85250
|
+
|
|
85251
|
+
When \`type\` is \`script\`, \`flow\`, or \`hubscript\`, the runnable just stores a \`path\` to an existing workspace or hub item — no inline code. The referenced item's input/output schema becomes the runnable's surface.
|
|
85252
|
+
|
|
85253
|
+
### Static inputs
|
|
85254
|
+
|
|
85255
|
+
\`staticInputs\` is an optional \`Record<string, any>\` for arguments not overridable from the frontend. Useful with path runnables to pre-fill some args while leaving the rest to the frontend caller.
|
|
85256
|
+
|
|
85257
|
+
## Data Tables
|
|
85258
|
+
|
|
85259
|
+
Data tables are PostgreSQL databases managed by Windmill. Backend runnables query them via the \`wmill\` client; the frontend never queries them directly.
|
|
85260
|
+
|
|
85261
|
+
### Critical rules
|
|
85262
|
+
|
|
85263
|
+
1. **Whitelisted tables only**: a runnable can only query tables listed in the app's \`data.tables\` config. Tables not in this list are not accessible.
|
|
85264
|
+
2. **Add tables before using**: queries against unlisted tables fail at runtime. When you introduce a new table, register it in \`data.tables\` first.
|
|
85265
|
+
3. **Use the configured datatable/schema**: the app's \`data\` config sets the default datatable and schema; reference them consistently across runnables.
|
|
85266
|
+
|
|
85267
|
+
### Querying in TypeScript (Bun/Deno)
|
|
85268
|
+
|
|
85269
|
+
\`\`\`typescript
|
|
85270
|
+
import * as wmill from 'windmill-client';
|
|
85271
|
+
|
|
85272
|
+
export async function main(user_id: string) {
|
|
85273
|
+
const sql = wmill.datatable(); // Or: wmill.datatable('other_datatable')
|
|
85274
|
+
|
|
85275
|
+
// Parameterized queries (safe from SQL injection)
|
|
85276
|
+
const user = await sql\`SELECT * FROM users WHERE id = \${user_id}\`.fetchOne();
|
|
85277
|
+
const users = await sql\`SELECT * FROM users WHERE active = \${true}\`.fetch();
|
|
85278
|
+
|
|
85279
|
+
// Insert/Update
|
|
85280
|
+
await sql\`INSERT INTO users (name, email) VALUES (\${name}, \${email})\`;
|
|
85281
|
+
await sql\`UPDATE users SET name = \${newName} WHERE id = \${user_id}\`;
|
|
85282
|
+
|
|
85283
|
+
return user;
|
|
85284
|
+
}
|
|
85285
|
+
\`\`\`
|
|
85286
|
+
|
|
85287
|
+
### Querying in Python
|
|
85288
|
+
|
|
85289
|
+
\`\`\`python
|
|
85290
|
+
import wmill
|
|
85291
|
+
|
|
85292
|
+
def main(user_id: str):
|
|
85293
|
+
db = wmill.datatable() # Or: wmill.datatable('other_datatable')
|
|
85294
|
+
|
|
85295
|
+
# Use $1, $2, etc. for parameters
|
|
85296
|
+
user = db.query('SELECT * FROM users WHERE id = $1', user_id).fetch_one()
|
|
85297
|
+
users = db.query('SELECT * FROM users WHERE active = $1', True).fetch()
|
|
85298
|
+
|
|
85299
|
+
# Insert/Update
|
|
85300
|
+
db.query('INSERT INTO users (name, email) VALUES ($1, $2)', name, email)
|
|
85301
|
+
db.query('UPDATE users SET name = $1 WHERE id = $2', new_name, user_id)
|
|
85302
|
+
|
|
85303
|
+
return user
|
|
85304
|
+
\`\`\`
|
|
85305
|
+
|
|
85253
85306
|
## Best Practices
|
|
85254
85307
|
|
|
85255
|
-
1. **Check
|
|
85256
|
-
2. **Use parameterized queries**
|
|
85257
|
-
3. **Keep runnables focused**
|
|
85258
|
-
4. **Use descriptive
|
|
85259
|
-
5. **Always whitelist tables**
|
|
85260
|
-
6. **Generate locks** - tell the user to run \`wmill generate-metadata\` after adding/modifying backend runnables
|
|
85308
|
+
1. **Check existing tables** before creating new ones — reuse beats schema growth.
|
|
85309
|
+
2. **Use parameterized queries** — never concatenate user input into SQL.
|
|
85310
|
+
3. **Keep runnables focused** — one function per runnable; small surface area.
|
|
85311
|
+
4. **Use descriptive keys** — \`get_user\`, not \`a\`.
|
|
85312
|
+
5. **Always whitelist tables** — adding a runnable that queries a new table requires the table to be in \`data.tables\` first.
|
|
85261
85313
|
`,
|
|
85262
85314
|
triggers: `---
|
|
85263
85315
|
name: triggers
|
|
@@ -89624,7 +89676,7 @@ var config_default = command35;
|
|
|
89624
89676
|
|
|
89625
89677
|
// src/main.ts
|
|
89626
89678
|
await init_context();
|
|
89627
|
-
var VERSION = "1.700.
|
|
89679
|
+
var VERSION = "1.700.2";
|
|
89628
89680
|
async function checkVersionSafe(cmd) {
|
|
89629
89681
|
const mainCommand = cmd.getMainCommand();
|
|
89630
89682
|
const upgradeCommand = mainCommand.getCommand("upgrade");
|