workato-dev-api 1.0.1 → 1.1.0

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 CHANGED
@@ -31,13 +31,16 @@ You can also export it directly in your shell environment.
31
31
 
32
32
  ## Claude Code setup
33
33
 
34
- In a clean working directory, run this once before starting Claude Code:
34
+ In a clean working directory, run these two commands once before starting Claude Code:
35
35
 
36
36
  ```sh
37
+ npx workato-dev-api auth YOUR_API_TOKEN
37
38
  npx workato-dev-api bootstrap-claude
38
39
  ```
39
40
 
40
- This writes a `CLAUDE.md` with full context — recipe code structure, wiring syntax, data table column naming, and project reference IDs — directly into your working directory where Claude Code will pick it up automatically.
41
+ That's it. The first command saves your token to `.env`. The second drops a `CLAUDE.md` into the directory so Claude Code automatically has full context — recipe structure, wiring syntax, data table column names, and project reference IDs.
42
+
43
+ Then just open Claude Code in that directory and start working.
41
44
 
42
45
  ## Commands
43
46
 
@@ -46,6 +49,7 @@ This writes a `CLAUDE.md` with full context — recipe code structure, wiring sy
46
49
  | Command | Description |
47
50
  |---|---|
48
51
  | `workato bootstrap-claude` | Copy `CLAUDE.md` into the current directory |
52
+ | `workato auth <token>` | Save your API token to `.env` in the current directory |
49
53
 
50
54
  ### Read
51
55
 
package/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- const fs = require('fs');
5
4
  const os = require('os');
6
5
  const path = require('path');
7
6
  const {
8
7
  loadEnv,
8
+ cmdBootstrapClaude, cmdAuth,
9
9
  cmdGet, cmdListRecipes, cmdListProjects, cmdListFolders,
10
10
  cmdListConnections, cmdListDataTables, cmdGetDataTable,
11
11
  cmdGetJobs, cmdGetJob,
@@ -13,12 +13,19 @@ const {
13
13
  cmdStart, cmdStop, cmdDelete,
14
14
  } = require('./lib');
15
15
 
16
- // bootstrap-claude runs before env/token setup — handle it immediately
17
- if (process.argv[2] === 'bootstrap-claude') {
18
- const src = path.join(__dirname, 'CLAUDE.md');
19
- const dest = path.join(process.cwd(), 'CLAUDE.md');
20
- fs.copyFileSync(src, dest);
21
- console.log(`CLAUDE.md written to ${dest}`);
16
+ // Setup commands run before env/token setup
17
+ const _setupCmd = process.argv[2];
18
+ if (_setupCmd === 'bootstrap-claude') {
19
+ cmdBootstrapClaude(process.cwd());
20
+ process.exit(0);
21
+ }
22
+ if (_setupCmd === 'auth') {
23
+ const token = process.argv[3];
24
+ if (!token) {
25
+ console.error('Usage: workato auth <token>');
26
+ process.exit(1);
27
+ }
28
+ cmdAuth(token, process.cwd());
22
29
  process.exit(0);
23
30
  }
24
31
 
@@ -29,7 +36,7 @@ loadEnv(path.join(os.homedir(), '.env'));
29
36
  loadEnv(path.join(process.cwd(), '.env'));
30
37
 
31
38
  if (!process.env.WORKATO_API_TOKEN) {
32
- console.error('Error: WORKATO_API_TOKEN not set.\nCreate a .env file in your current directory with:\n WORKATO_API_TOKEN=your_token_here');
39
+ console.error('Error: WORKATO_API_TOKEN not set.\nRun: workato auth <your_token>\nOr create a .env file with: WORKATO_API_TOKEN=your_token_here');
33
40
  process.exit(1);
34
41
  }
35
42
 
@@ -61,6 +68,7 @@ workato <command> [options]
61
68
 
62
69
  Setup:
63
70
  bootstrap-claude Copy CLAUDE.md into the current directory
71
+ auth <token> Save API token to .env in the current directory
64
72
 
65
73
  Read commands:
66
74
  get <recipe_id> Fetch recipe code → recipe_<id>_code.json
package/lib.js CHANGED
@@ -143,6 +143,30 @@ function apiTriggerConfig() {
143
143
  ];
144
144
  }
145
145
 
146
+ // ── Setup commands ────────────────────────────────────────────────────────────
147
+
148
+ function cmdBootstrapClaude(destDir) {
149
+ const src = path.join(__dirname, 'CLAUDE.md');
150
+ const dest = path.join(destDir ?? process.cwd(), 'CLAUDE.md');
151
+ fs.copyFileSync(src, dest);
152
+ console.log(`CLAUDE.md written to ${dest}`);
153
+ return dest;
154
+ }
155
+
156
+ function cmdAuth(token, destDir) {
157
+ const envPath = path.join(destDir ?? process.cwd(), '.env');
158
+ let content = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
159
+ const line = `WORKATO_API_TOKEN=${token}`;
160
+ if (/^WORKATO_API_TOKEN=/m.test(content)) {
161
+ content = content.replace(/^WORKATO_API_TOKEN=.*/m, line);
162
+ } else {
163
+ content = content ? content.trimEnd() + '\n' + line + '\n' : line + '\n';
164
+ }
165
+ fs.writeFileSync(envPath, content);
166
+ console.log(`Token saved to ${envPath}`);
167
+ return envPath;
168
+ }
169
+
146
170
  // ── Read commands ─────────────────────────────────────────────────────────────
147
171
 
148
172
  async function cmdGet(recipeId) {
@@ -313,6 +337,8 @@ module.exports = {
313
337
  // helpers
314
338
  findStep, deepMerge, extractCode,
315
339
  apiTriggerCode, apiTriggerConfig,
340
+ // setup commands
341
+ cmdBootstrapClaude, cmdAuth,
316
342
  // read commands
317
343
  cmdGet, cmdListRecipes, cmdListProjects, cmdListFolders,
318
344
  cmdListConnections, cmdListDataTables, cmdGetDataTable,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workato-dev-api",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "CLI for the Workato Developer API — recipes, connections, data tables, and more",
5
5
  "bin": {
6
6
  "workato": "cli.js"
package/test/cli.test.js CHANGED
@@ -982,6 +982,144 @@ describe('cmdUpdateStep — deeply nested step', () => {
982
982
  });
983
983
  });
984
984
 
985
+ // ── cmdBootstrapClaude ────────────────────────────────────────────────────────
986
+
987
+ describe('cmdBootstrapClaude', () => {
988
+ function tmpDir() {
989
+ const d = path.join(os.tmpdir(), `workato-test-${Date.now()}-${Math.random()}`);
990
+ fs.mkdirSync(d, { recursive: true });
991
+ return d;
992
+ }
993
+
994
+ test('copies CLAUDE.md into the destination directory', () => {
995
+ const dir = tmpDir();
996
+ try {
997
+ lib.cmdBootstrapClaude(dir);
998
+ assert.ok(fs.existsSync(path.join(dir, 'CLAUDE.md')), 'CLAUDE.md should exist in dest dir');
999
+ } finally {
1000
+ fs.rmSync(dir, { recursive: true, force: true });
1001
+ }
1002
+ });
1003
+
1004
+ test('written file content matches the source CLAUDE.md', () => {
1005
+ const dir = tmpDir();
1006
+ try {
1007
+ lib.cmdBootstrapClaude(dir);
1008
+ const srcPath = path.join(__dirname, '..', 'CLAUDE.md');
1009
+ const src = fs.readFileSync(srcPath, 'utf8');
1010
+ const dest = fs.readFileSync(path.join(dir, 'CLAUDE.md'), 'utf8');
1011
+ assert.equal(dest, src);
1012
+ } finally {
1013
+ fs.rmSync(dir, { recursive: true, force: true });
1014
+ }
1015
+ });
1016
+
1017
+ test('returns the destination file path', () => {
1018
+ const dir = tmpDir();
1019
+ try {
1020
+ const result = lib.cmdBootstrapClaude(dir);
1021
+ assert.equal(result, path.join(dir, 'CLAUDE.md'));
1022
+ } finally {
1023
+ fs.rmSync(dir, { recursive: true, force: true });
1024
+ }
1025
+ });
1026
+
1027
+ test('overwrites an existing CLAUDE.md', () => {
1028
+ const dir = tmpDir();
1029
+ try {
1030
+ fs.writeFileSync(path.join(dir, 'CLAUDE.md'), 'old content');
1031
+ lib.cmdBootstrapClaude(dir);
1032
+ const content = fs.readFileSync(path.join(dir, 'CLAUDE.md'), 'utf8');
1033
+ assert.notEqual(content, 'old content');
1034
+ } finally {
1035
+ fs.rmSync(dir, { recursive: true, force: true });
1036
+ }
1037
+ });
1038
+ });
1039
+
1040
+ // ── cmdAuth ───────────────────────────────────────────────────────────────────
1041
+
1042
+ describe('cmdAuth', () => {
1043
+ function tmpDir() {
1044
+ const d = path.join(os.tmpdir(), `workato-auth-test-${Date.now()}-${Math.random()}`);
1045
+ fs.mkdirSync(d, { recursive: true });
1046
+ return d;
1047
+ }
1048
+
1049
+ test('creates .env with token when file does not exist', () => {
1050
+ const dir = tmpDir();
1051
+ try {
1052
+ lib.cmdAuth('mytoken123', dir);
1053
+ const content = fs.readFileSync(path.join(dir, '.env'), 'utf8');
1054
+ assert.ok(content.includes('WORKATO_API_TOKEN=mytoken123'));
1055
+ } finally {
1056
+ fs.rmSync(dir, { recursive: true, force: true });
1057
+ }
1058
+ });
1059
+
1060
+ test('returns the .env file path', () => {
1061
+ const dir = tmpDir();
1062
+ try {
1063
+ const result = lib.cmdAuth('tok', dir);
1064
+ assert.equal(result, path.join(dir, '.env'));
1065
+ } finally {
1066
+ fs.rmSync(dir, { recursive: true, force: true });
1067
+ }
1068
+ });
1069
+
1070
+ test('updates existing WORKATO_API_TOKEN line in .env', () => {
1071
+ const dir = tmpDir();
1072
+ try {
1073
+ fs.writeFileSync(path.join(dir, '.env'), 'WORKATO_API_TOKEN=oldtoken\n');
1074
+ lib.cmdAuth('newtoken', dir);
1075
+ const content = fs.readFileSync(path.join(dir, '.env'), 'utf8');
1076
+ assert.ok(content.includes('WORKATO_API_TOKEN=newtoken'), 'should have new token');
1077
+ assert.ok(!content.includes('oldtoken'), 'should not have old token');
1078
+ assert.equal((content.match(/WORKATO_API_TOKEN=/g) || []).length, 1, 'only one token line');
1079
+ } finally {
1080
+ fs.rmSync(dir, { recursive: true, force: true });
1081
+ }
1082
+ });
1083
+
1084
+ test('appends token to .env that has other keys but no WORKATO_API_TOKEN', () => {
1085
+ const dir = tmpDir();
1086
+ try {
1087
+ fs.writeFileSync(path.join(dir, '.env'), 'OTHER_KEY=value\n');
1088
+ lib.cmdAuth('mytoken', dir);
1089
+ const content = fs.readFileSync(path.join(dir, '.env'), 'utf8');
1090
+ assert.ok(content.includes('OTHER_KEY=value'), 'existing key preserved');
1091
+ assert.ok(content.includes('WORKATO_API_TOKEN=mytoken'), 'token appended');
1092
+ } finally {
1093
+ fs.rmSync(dir, { recursive: true, force: true });
1094
+ }
1095
+ });
1096
+
1097
+ test('token value containing = is preserved verbatim', () => {
1098
+ const dir = tmpDir();
1099
+ try {
1100
+ lib.cmdAuth('tok==extra==', dir);
1101
+ const content = fs.readFileSync(path.join(dir, '.env'), 'utf8');
1102
+ assert.ok(content.includes('WORKATO_API_TOKEN=tok==extra=='));
1103
+ } finally {
1104
+ fs.rmSync(dir, { recursive: true, force: true });
1105
+ }
1106
+ });
1107
+
1108
+ test('preserves other keys in .env when updating token', () => {
1109
+ const dir = tmpDir();
1110
+ try {
1111
+ fs.writeFileSync(path.join(dir, '.env'), 'FOO=bar\nWORKATO_API_TOKEN=old\nBAZ=qux\n');
1112
+ lib.cmdAuth('updated', dir);
1113
+ const content = fs.readFileSync(path.join(dir, '.env'), 'utf8');
1114
+ assert.ok(content.includes('FOO=bar'), 'FOO preserved');
1115
+ assert.ok(content.includes('BAZ=qux'), 'BAZ preserved');
1116
+ assert.ok(content.includes('WORKATO_API_TOKEN=updated'), 'token updated');
1117
+ } finally {
1118
+ fs.rmSync(dir, { recursive: true, force: true });
1119
+ }
1120
+ });
1121
+ });
1122
+
985
1123
  // Restore console at end
986
1124
  process.on('exit', () => {
987
1125
  console.log = origLog;