workato-dev-api 1.2.0 → 1.2.1
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/README.md +49 -59
- package/cli.js +4 -4
- package/lib.js +2 -2
- package/package.json +1 -1
- package/test/cli.test.js +6 -6
package/README.md
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
# workato-dev-api
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Zero-dependency CLI and SDK for the [Workato Developer API](https://docs.workato.com/workato-api.html). Built for use with AI coding assistants and programmatic tooling — read and write recipes, connections, data tables, projects, folders, and jobs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Claude Code / Cursor / Windsurf / ...
|
|
8
|
+
|
|
9
|
+
In a clean working directory, run these two commands once before opening your AI assistant:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npx workato-dev-api auth YOUR_API_TOKEN
|
|
13
|
+
npx workato-dev-api bootstrap
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The first saves your token to `.env`. The second drops a `CLAUDE.md` into the directory — picked up automatically by Claude Code, Cursor, Windsurf, and other assistants that support project context files — giving it full Workato context: recipe structure, wiring syntax, data table column naming, and how to use this CLI.
|
|
17
|
+
|
|
18
|
+
Then open your assistant in that directory and start working.
|
|
19
|
+
|
|
20
|
+
> **Workato free sandbox?** Just tell your assistant — it will update your `package.json` automatically so the CLI points at the right URL.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## SDK / CLI Reference
|
|
25
|
+
|
|
26
|
+
### Install
|
|
6
27
|
|
|
7
28
|
```sh
|
|
8
29
|
npm install -g workato-dev-api
|
|
@@ -14,44 +35,42 @@ Or use without installing:
|
|
|
14
35
|
npx workato-dev-api <command>
|
|
15
36
|
```
|
|
16
37
|
|
|
17
|
-
|
|
38
|
+
### Authentication
|
|
18
39
|
|
|
19
|
-
Set `WORKATO_API_TOKEN` in a `.env` file
|
|
20
|
-
|
|
21
|
-
1. `<package-dir>/.env` — lowest priority (rarely used)
|
|
22
|
-
2. `~/.env` — your home directory default
|
|
23
|
-
3. `./.env` (cwd) — **highest priority**, project-specific override
|
|
40
|
+
Set `WORKATO_API_TOKEN` in a `.env` file, or run:
|
|
24
41
|
|
|
25
42
|
```sh
|
|
26
|
-
|
|
27
|
-
WORKATO_API_TOKEN=your_token_here
|
|
43
|
+
workato auth YOUR_API_TOKEN
|
|
28
44
|
```
|
|
29
45
|
|
|
30
|
-
|
|
46
|
+
The CLI checks `.env` files in this order, with later files winning:
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
1. `<package-dir>/.env`
|
|
49
|
+
2. `~/.env`
|
|
50
|
+
3. `./.env` (cwd) — highest priority
|
|
33
51
|
|
|
34
|
-
|
|
52
|
+
### Sandbox configuration
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
npx workato-dev-api auth YOUR_API_TOKEN
|
|
38
|
-
npx workato-dev-api bootstrap-claude
|
|
39
|
-
```
|
|
54
|
+
By default the CLI targets `app.workato.com`. For a Workato free sandbox (trial account), set in your `package.json`:
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"workato": { "sandbox": true }
|
|
59
|
+
}
|
|
60
|
+
```
|
|
42
61
|
|
|
43
|
-
|
|
62
|
+
This switches the base URL to `app.trial.workato.com`.
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
### Commands
|
|
46
65
|
|
|
47
|
-
|
|
66
|
+
#### Setup
|
|
48
67
|
|
|
49
68
|
| Command | Description |
|
|
50
69
|
|---|---|
|
|
51
|
-
| `workato
|
|
52
|
-
| `workato
|
|
70
|
+
| `workato auth <token>` | Save API token to `.env` in the current directory |
|
|
71
|
+
| `workato bootstrap` | Copy `CLAUDE.md` into the current directory |
|
|
53
72
|
|
|
54
|
-
|
|
73
|
+
#### Read
|
|
55
74
|
|
|
56
75
|
| Command | Description |
|
|
57
76
|
|---|---|
|
|
@@ -65,7 +84,7 @@ Then open Claude Code in that directory and start working. If you're on a **Work
|
|
|
65
84
|
| `workato get-jobs <recipe_id>` | List recent jobs. Filters: `--limit <n>`, `--status <status>` |
|
|
66
85
|
| `workato get-job <recipe_id> <job_id>` | Fetch a single job |
|
|
67
86
|
|
|
68
|
-
|
|
87
|
+
#### Write
|
|
69
88
|
|
|
70
89
|
| Command | Description |
|
|
71
90
|
|---|---|
|
|
@@ -77,48 +96,19 @@ Then open Claude Code in that directory and start working. If you're on a **Work
|
|
|
77
96
|
| `workato stop <recipe_id>` | Stop a recipe |
|
|
78
97
|
| `workato delete <recipe_id>` | Delete a recipe |
|
|
79
98
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
```sh
|
|
83
|
-
# Fetch recipe code and save to file
|
|
84
|
-
workato get 167603
|
|
85
|
-
|
|
86
|
-
# List all recipes in a project
|
|
87
|
-
workato list-recipes --project 14318
|
|
88
|
-
|
|
89
|
-
# List jobs that failed
|
|
90
|
-
workato get-jobs 167603 --limit 20 --status failed
|
|
91
|
-
|
|
92
|
-
# Start a recipe
|
|
93
|
-
workato start 167603
|
|
94
|
-
|
|
95
|
-
# Patch a single step's input fields
|
|
96
|
-
cat > patch.json <<'EOF'
|
|
97
|
-
{
|
|
98
|
-
"input": {
|
|
99
|
-
"language": "fr"
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
EOF
|
|
103
|
-
workato update-step 167603 5df21cfd patch.json
|
|
104
|
-
|
|
105
|
-
# Replace entire recipe code
|
|
106
|
-
workato put-code 167603 recipe_167603_code.json
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Recipe code structure
|
|
99
|
+
### Recipe code structure
|
|
110
100
|
|
|
111
101
|
A recipe's code is a JSON object. The top-level object is the **trigger** step; action steps live in `code.block[]`. Each step has a unique `as` field (8-char hex) used for cross-step wiring (datapills).
|
|
112
102
|
|
|
113
|
-
`workato get <id>` saves the code to `recipe_<id>_code.json`
|
|
103
|
+
`workato get <id>` saves the code to `recipe_<id>_code.json` for inspection and editing before pushing back with `put-code`.
|
|
114
104
|
|
|
115
|
-
|
|
105
|
+
### Development
|
|
116
106
|
|
|
117
107
|
```sh
|
|
118
|
-
git clone
|
|
108
|
+
git clone https://github.com/bill-bishop/workato-dev-api
|
|
119
109
|
cd workato-dev-api
|
|
120
110
|
cp .env.example .env # add your token
|
|
121
|
-
npm test #
|
|
111
|
+
npm test # 110 unit tests, no network required
|
|
122
112
|
```
|
|
123
113
|
|
|
124
114
|
Tests use Node's built-in `node:test` runner — no extra dependencies.
|
package/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ const os = require('os');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const {
|
|
7
7
|
loadEnv, setConfig, resolveBaseUrl, readProjectConfig,
|
|
8
|
-
|
|
8
|
+
cmdBootstrap, cmdAuth,
|
|
9
9
|
cmdGet, cmdListRecipes, cmdListProjects, cmdListFolders,
|
|
10
10
|
cmdListConnections, cmdListDataTables, cmdGetDataTable,
|
|
11
11
|
cmdGetJobs, cmdGetJob,
|
|
@@ -15,8 +15,8 @@ const {
|
|
|
15
15
|
|
|
16
16
|
// Setup commands run before env/token setup
|
|
17
17
|
const _setupCmd = process.argv[2];
|
|
18
|
-
if (_setupCmd === 'bootstrap
|
|
19
|
-
|
|
18
|
+
if (_setupCmd === 'bootstrap') {
|
|
19
|
+
cmdBootstrap(process.cwd());
|
|
20
20
|
process.exit(0);
|
|
21
21
|
}
|
|
22
22
|
if (_setupCmd === 'auth') {
|
|
@@ -71,7 +71,7 @@ function usage() {
|
|
|
71
71
|
workato <command> [options]
|
|
72
72
|
|
|
73
73
|
Setup:
|
|
74
|
-
bootstrap
|
|
74
|
+
bootstrap Copy CLAUDE.md into the current directory
|
|
75
75
|
auth <token> Save API token to .env in the current directory
|
|
76
76
|
|
|
77
77
|
Read commands:
|
package/lib.js
CHANGED
|
@@ -160,7 +160,7 @@ function apiTriggerConfig() {
|
|
|
160
160
|
|
|
161
161
|
// ── Setup commands ────────────────────────────────────────────────────────────
|
|
162
162
|
|
|
163
|
-
function
|
|
163
|
+
function cmdBootstrap(destDir) {
|
|
164
164
|
const src = path.join(__dirname, 'CLAUDE.md');
|
|
165
165
|
const dest = path.join(destDir ?? process.cwd(), 'CLAUDE.md');
|
|
166
166
|
fs.copyFileSync(src, dest);
|
|
@@ -353,7 +353,7 @@ module.exports = {
|
|
|
353
353
|
findStep, deepMerge, extractCode,
|
|
354
354
|
apiTriggerCode, apiTriggerConfig,
|
|
355
355
|
// setup commands
|
|
356
|
-
|
|
356
|
+
cmdBootstrap, cmdAuth,
|
|
357
357
|
// read commands
|
|
358
358
|
cmdGet, cmdListRecipes, cmdListProjects, cmdListFolders,
|
|
359
359
|
cmdListConnections, cmdListDataTables, cmdGetDataTable,
|
package/package.json
CHANGED
package/test/cli.test.js
CHANGED
|
@@ -1083,9 +1083,9 @@ describe('readProjectConfig', () => {
|
|
|
1083
1083
|
});
|
|
1084
1084
|
});
|
|
1085
1085
|
|
|
1086
|
-
// ──
|
|
1086
|
+
// ── cmdBootstrap ────────────────────────────────────────────────────────
|
|
1087
1087
|
|
|
1088
|
-
describe('
|
|
1088
|
+
describe('cmdBootstrap', () => {
|
|
1089
1089
|
function tmpDir() {
|
|
1090
1090
|
const d = path.join(os.tmpdir(), `workato-test-${Date.now()}-${Math.random()}`);
|
|
1091
1091
|
fs.mkdirSync(d, { recursive: true });
|
|
@@ -1095,7 +1095,7 @@ describe('cmdBootstrapClaude', () => {
|
|
|
1095
1095
|
test('copies CLAUDE.md into the destination directory', () => {
|
|
1096
1096
|
const dir = tmpDir();
|
|
1097
1097
|
try {
|
|
1098
|
-
lib.
|
|
1098
|
+
lib.cmdBootstrap(dir);
|
|
1099
1099
|
assert.ok(fs.existsSync(path.join(dir, 'CLAUDE.md')), 'CLAUDE.md should exist in dest dir');
|
|
1100
1100
|
} finally {
|
|
1101
1101
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -1105,7 +1105,7 @@ describe('cmdBootstrapClaude', () => {
|
|
|
1105
1105
|
test('written file content matches the source CLAUDE.md', () => {
|
|
1106
1106
|
const dir = tmpDir();
|
|
1107
1107
|
try {
|
|
1108
|
-
lib.
|
|
1108
|
+
lib.cmdBootstrap(dir);
|
|
1109
1109
|
const srcPath = path.join(__dirname, '..', 'CLAUDE.md');
|
|
1110
1110
|
const src = fs.readFileSync(srcPath, 'utf8');
|
|
1111
1111
|
const dest = fs.readFileSync(path.join(dir, 'CLAUDE.md'), 'utf8');
|
|
@@ -1118,7 +1118,7 @@ describe('cmdBootstrapClaude', () => {
|
|
|
1118
1118
|
test('returns the destination file path', () => {
|
|
1119
1119
|
const dir = tmpDir();
|
|
1120
1120
|
try {
|
|
1121
|
-
const result = lib.
|
|
1121
|
+
const result = lib.cmdBootstrap(dir);
|
|
1122
1122
|
assert.equal(result, path.join(dir, 'CLAUDE.md'));
|
|
1123
1123
|
} finally {
|
|
1124
1124
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -1129,7 +1129,7 @@ describe('cmdBootstrapClaude', () => {
|
|
|
1129
1129
|
const dir = tmpDir();
|
|
1130
1130
|
try {
|
|
1131
1131
|
fs.writeFileSync(path.join(dir, 'CLAUDE.md'), 'old content');
|
|
1132
|
-
lib.
|
|
1132
|
+
lib.cmdBootstrap(dir);
|
|
1133
1133
|
const content = fs.readFileSync(path.join(dir, 'CLAUDE.md'), 'utf8');
|
|
1134
1134
|
assert.notEqual(content, 'old content');
|
|
1135
1135
|
} finally {
|