@openfn/cli 0.0.28 → 0.0.29

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
@@ -46,7 +46,7 @@ openfn path/to/job.js -ia adaptor-name
46
46
 
47
47
  You MUST specify which adaptor to use. Pass the `-i` flag to auto-install that adaptor (it's safe to do this redundantly).
48
48
 
49
- If output.json and state.json are not passed, the CLI will look for them next to the job.js file. You can pass a path to state by adding `-s path/to/state.json`, and output by passing `-o path/to/output.json`. You can use `-S` and `-O` to pass state through stdin and return the output through stdout.
49
+ If output.json is not passed, the CLI will create an `output.json` next to the job file. You can pass a path to state by adding `-s path/to/state.json`, and output by passing `-o path/to/output.json`. You can use `-S` and `-O` to pass state through stdin and return the output through stdout.
50
50
 
51
51
  The CLI can auto-install language adaptors to its own privately maintained repo. Run `openfn repo list` to see where the repo is, and what's in it. Set the `OPENFN_REPO_DIR` env var to specify the repo folder. When autoinstalling, the CLI will check to see if a matching version is found in the repo.
52
52
 
@@ -94,6 +94,7 @@ function ensureOpts(basePath = ".", opts) {
94
94
  specifier: opts.specifier,
95
95
  stateStdin: opts.stateStdin,
96
96
  strictOutput: opts.strictOutput ?? true,
97
+ statePath: opts.statePath,
97
98
  timeout: opts.timeout
98
99
  };
99
100
  const set = (key, value) => {
@@ -109,7 +110,6 @@ function ensureOpts(basePath = ".", opts) {
109
110
  } else {
110
111
  set("jobPath", `${baseDir}/job.js`);
111
112
  }
112
- set("statePath", `${baseDir}/state.json`);
113
113
  if (!opts.outputStdout) {
114
114
  set(
115
115
  "outputPath",
@@ -123,31 +123,34 @@ function ensureOpts(basePath = ".", opts) {
123
123
  // src/execute/load-state.ts
124
124
  import fs from "node:fs/promises";
125
125
  var load_state_default = async (opts, log) => {
126
+ const { stateStdin, statePath } = opts;
126
127
  log.debug("Load state...");
127
- if (opts.stateStdin) {
128
+ if (stateStdin) {
128
129
  try {
129
- const json = JSON.parse(opts.stateStdin);
130
+ const json = JSON.parse(stateStdin);
130
131
  log.success("Read state from stdin");
131
132
  log.debug("state:", json);
132
133
  return json;
133
134
  } catch (e) {
134
135
  log.error("Failed to load state from stdin");
135
- log.error(opts.stateStdin);
136
+ log.error(stateStdin);
136
137
  log.error(e);
137
138
  process.exit(1);
138
139
  }
139
140
  }
140
- try {
141
- const str = await fs.readFile(opts.statePath, "utf8");
142
- const json = JSON.parse(str);
143
- log.success(`Loaded state from ${opts.statePath}`);
144
- log.debug("state:", json);
145
- return json;
146
- } catch (e) {
147
- log.warn(`Error loading state from ${opts.statePath}`);
148
- log.warn(e);
141
+ if (statePath) {
142
+ try {
143
+ const str = await fs.readFile(statePath, "utf8");
144
+ const json = JSON.parse(str);
145
+ log.success(`Loaded state from ${statePath}`);
146
+ log.debug("state:", json);
147
+ return json;
148
+ } catch (e) {
149
+ log.warn(`Error loading state from ${statePath}`);
150
+ log.warn(e);
151
+ }
149
152
  }
150
- log.warn("Using default state { data: {}, configuration: {}");
153
+ log.info("No state provided - using default state { data: {}, configuration: {}");
151
154
  return {
152
155
  data: {},
153
156
  configuration: {}
@@ -171,11 +174,11 @@ var execute_default = (code, state, opts) => {
171
174
  function parseAdaptors(opts) {
172
175
  const adaptors = {};
173
176
  opts.adaptors.reduce((obj, exp) => {
174
- const [module, path4] = exp.split("=");
177
+ const [module, path5] = exp.split("=");
175
178
  const { name, version } = getNameAndVersion(module);
176
179
  const info = {};
177
- if (path4) {
178
- info.path = path4;
180
+ if (path5) {
181
+ info.path = path5;
179
182
  }
180
183
  if (version) {
181
184
  info.version = version;
@@ -200,7 +203,7 @@ var compile_default = async (opts, log) => {
200
203
  } else {
201
204
  const complilerOptions = await loadTransformOptions(opts, log);
202
205
  complilerOptions.logger = logger_default(COMPILER, opts);
203
- job = compile(opts.jobPath, complilerOptions);
206
+ job = compile(opts.jobSource || opts.jobPath, complilerOptions);
204
207
  if (opts.jobPath) {
205
208
  log.success(`Compiled job from ${opts.jobPath}`);
206
209
  } else {
@@ -217,10 +220,10 @@ var stripVersionSpecifier = (specifier) => {
217
220
  return specifier;
218
221
  };
219
222
  var resolveSpecifierPath = async (pattern, repoDir, log) => {
220
- const [specifier, path4] = pattern.split("=");
221
- if (path4) {
222
- log.debug(`Resolved ${specifier} to path: ${path4}`);
223
- return path4;
223
+ const [specifier, path5] = pattern.split("=");
224
+ if (path5) {
225
+ log.debug(`Resolved ${specifier} to path: ${path5}`);
226
+ return path5;
224
227
  }
225
228
  const repoPath = await getModulePath(specifier, repoDir, log);
226
229
  if (repoPath) {
@@ -237,15 +240,15 @@ var loadTransformOptions = async (opts, log) => {
237
240
  const [pattern] = opts.adaptors;
238
241
  const [specifier] = pattern.split("=");
239
242
  log.debug(`Attempting to preload typedefs for ${specifier}`);
240
- const path4 = await resolveSpecifierPath(pattern, opts.repoDir, log);
241
- if (path4) {
243
+ const path5 = await resolveSpecifierPath(pattern, opts.repoDir, log);
244
+ if (path5) {
242
245
  try {
243
- exports = await preloadAdaptorExports(path4);
246
+ exports = await preloadAdaptorExports(path5);
244
247
  if (exports) {
245
248
  log.info(`Loaded typedefs for ${specifier}`);
246
249
  }
247
250
  } catch (e) {
248
- log.error(`Failed to load adaptor typedefs from path ${path4}`);
251
+ log.error(`Failed to load adaptor typedefs from path ${path5}`);
249
252
  log.error(e);
250
253
  }
251
254
  }
@@ -448,20 +451,18 @@ var compileHandler = async (options, logger) => {
448
451
  var handler_default2 = compileHandler;
449
452
 
450
453
  // src/test/handler.ts
454
+ var sillyMessage = "Calculating the answer to life, the universe, and everything...";
451
455
  var testHandler = async (options, logger) => {
452
456
  logger.log("Running test job...");
453
- options.jobPath = `const fn = () => state => state * 2; fn()`;
457
+ options.jobSource = `const fn = () => state => { console.log('${sillyMessage}'); return state * 2; } ; fn()`;
458
+ delete options.jobPath;
454
459
  if (!options.stateStdin) {
455
- logger.warn("No state detected: pass -S <number> to provide some state");
460
+ logger.debug("No state provided: try -S <number> to provide some state");
456
461
  options.stateStdin = "21";
457
462
  }
458
463
  const silentLogger = createNullLogger();
459
464
  const state = await load_state_default(options, silentLogger);
460
465
  const code = await compile_default(options, logger);
461
- logger.break();
462
- logger.info("Compiled job:", "\n", code);
463
- logger.break();
464
- logger.info("Running job...");
465
466
  const result = await execute_default(code, state, options);
466
467
  logger.success(`Result: ${result}`);
467
468
  return result;
@@ -479,20 +480,20 @@ var RETRY_COUNT = 20;
479
480
  var TIMEOUT_MS = 1e3 * 60;
480
481
  var actualDocGen = (specifier) => describePackage(specifier, {});
481
482
  var ensurePath = (filePath) => mkdirSync(path2.dirname(filePath), { recursive: true });
482
- var generatePlaceholder = (path4) => {
483
- writeFileSync(path4, `{ "loading": true, "timestamp": ${Date.now()}}`);
483
+ var generatePlaceholder = (path5) => {
484
+ writeFileSync(path5, `{ "loading": true, "timestamp": ${Date.now()}}`);
484
485
  };
485
486
  var finish = (logger, resultPath) => {
486
487
  logger.success("Done! Docs can be found at:\n");
487
488
  logger.print(` ${path2.resolve(resultPath)}`);
488
489
  };
489
- var generateDocs = async (specifier, path4, docgen, logger) => {
490
+ var generateDocs = async (specifier, path5, docgen, logger) => {
490
491
  const result = await docgen(specifier);
491
- await writeFile3(path4, JSON.stringify(result, null, 2));
492
- finish(logger, path4);
493
- return path4;
492
+ await writeFile3(path5, JSON.stringify(result, null, 2));
493
+ finish(logger, path5);
494
+ return path5;
494
495
  };
495
- var waitForDocs = async (docs, path4, logger, retryDuration = RETRY_DURATION) => {
496
+ var waitForDocs = async (docs, path5, logger, retryDuration = RETRY_DURATION) => {
496
497
  try {
497
498
  if (docs.hasOwnProperty("loading")) {
498
499
  logger.info("Docs are being loaded by another process. Waiting.");
@@ -504,19 +505,19 @@ var waitForDocs = async (docs, path4, logger, retryDuration = RETRY_DURATION) =>
504
505
  clearInterval(i);
505
506
  reject(new Error("Timed out waiting for docs to load"));
506
507
  }
507
- const updated = JSON.parse(readFileSync(path4, "utf8"));
508
+ const updated = JSON.parse(readFileSync(path5, "utf8"));
508
509
  if (!updated.hasOwnProperty("loading")) {
509
510
  logger.info("Docs found!");
510
511
  clearInterval(i);
511
- resolve(path4);
512
+ resolve(path5);
512
513
  }
513
514
  count++;
514
515
  }, retryDuration);
515
516
  });
516
517
  } else {
517
- logger.info(`Docs already written to cache at ${path4}`);
518
- finish(logger, path4);
519
- return path4;
518
+ logger.info(`Docs already written to cache at ${path5}`);
519
+ finish(logger, path5);
520
+ return path5;
520
521
  }
521
522
  } catch (e) {
522
523
  logger.error("Existing doc JSON corrupt. Aborting");
@@ -533,28 +534,28 @@ var docgenHandler = (options, logger, docgen = actualDocGen, retryDuration = RET
533
534
  process.exit(9);
534
535
  }
535
536
  logger.success(`Generating docs for ${specifier}`);
536
- const path4 = `${repoDir}/docs/${specifier}.json`;
537
- ensurePath(path4);
537
+ const path5 = `${repoDir}/docs/${specifier}.json`;
538
+ ensurePath(path5);
538
539
  const handleError = () => {
539
540
  logger.info("Removing placeholder");
540
- rmSync(path4);
541
+ rmSync(path5);
541
542
  };
542
543
  try {
543
- const existing = readFileSync(path4, "utf8");
544
+ const existing = readFileSync(path5, "utf8");
544
545
  const json = JSON.parse(existing);
545
546
  if (json && json.timeout && Date.now() - json.timeout >= TIMEOUT_MS) {
546
547
  logger.info(`Expired placeholder found. Removing.`);
547
- rmSync(path4);
548
+ rmSync(path5);
548
549
  throw new Error("TIMEOUT");
549
550
  }
550
- return waitForDocs(json, path4, logger, retryDuration);
551
+ return waitForDocs(json, path5, logger, retryDuration);
551
552
  } catch (e) {
552
553
  if (e.message !== "TIMEOUT") {
553
- logger.info(`Docs JSON not found at ${path4}`);
554
+ logger.info(`Docs JSON not found at ${path5}`);
554
555
  }
555
556
  logger.debug("Generating placeholder");
556
- generatePlaceholder(path4);
557
- return generateDocs(specifier, path4, docgen, logger).catch((e2) => {
557
+ generatePlaceholder(path5);
558
+ return generateDocs(specifier, path5, docgen, logger).catch((e2) => {
558
559
  logger.error("Error generating documentation");
559
560
  logger.error(e2);
560
561
  handleError();
@@ -602,15 +603,15 @@ var docsHandler = async (options, logger) => {
602
603
  logger.success(`Showing docs for ${adaptorName} v${version}`);
603
604
  }
604
605
  logger.info("Generating/loading documentation...");
605
- const path4 = await handler_default4(
606
+ const path5 = await handler_default4(
606
607
  {
607
608
  specifier: `${name}@${version}`,
608
609
  repoDir
609
610
  },
610
611
  createNullLogger()
611
612
  );
612
- if (path4) {
613
- const source = await readFile(path4, "utf8");
613
+ if (path5) {
614
+ const source = await readFile(path5, "utf8");
614
615
  const data = JSON.parse(source);
615
616
  let desc;
616
617
  if (operation) {
@@ -673,25 +674,56 @@ var useAdaptorsRepo = async (adaptors, repoPath, log) => {
673
674
  var use_adaptors_repo_default = useAdaptorsRepo;
674
675
 
675
676
  // src/util/print-versions.ts
676
- import { mainSymbols } from "figures";
677
+ import { readFileSync as readFileSync2 } from "node:fs";
678
+ import path4 from "node:path";
677
679
  import { getNameAndVersion as getNameAndVersion5 } from "@openfn/runtime";
680
+ import { mainSymbols } from "figures";
681
+ var NODE = "node.js";
682
+ var CLI2 = "cli";
683
+ var RUNTIME2 = "runtime";
684
+ var COMPILER2 = "compiler";
678
685
  var { triangleRightSmall: t } = mainSymbols;
686
+ var loadVersionFromPath = (adaptorPath) => {
687
+ try {
688
+ const pkg = JSON.parse(readFileSync2(path4.resolve(adaptorPath, "package.json"), "utf8"));
689
+ return pkg.version;
690
+ } catch (e) {
691
+ return "unknown";
692
+ }
693
+ };
679
694
  var printVersions = async (logger, options = {}) => {
680
- const prefix = (str) => ` ${t} ${str.padEnd(options.adaptors ? 16 : 8, " ")}`;
695
+ const { adaptors, logJson } = options;
696
+ let adaptor = "";
697
+ if (adaptors && adaptors.length) {
698
+ adaptor = adaptors[0];
699
+ }
700
+ const longest = Math.max(...[
701
+ NODE,
702
+ CLI2,
703
+ RUNTIME2,
704
+ COMPILER2,
705
+ adaptor
706
+ ].map((s) => s.length));
707
+ const prefix = (str) => ` ${t} ${str.padEnd(longest + 4, " ")}`;
681
708
  const pkg = await import("../../package.json", { assert: { type: "json" } });
682
709
  const { version, dependencies } = pkg.default;
683
710
  const compilerVersion = dependencies["@openfn/compiler"];
684
711
  const runtimeVersion = dependencies["@openfn/runtime"];
685
- const { adaptors } = options;
686
- let adaptorName, adaptorVersion;
687
- if (adaptors && adaptors.length === 1) {
688
- const [a] = adaptors;
689
- const { name, version: version2 } = getNameAndVersion5(a);
690
- adaptorName = name.replace(/^@openfn\/language-/, "");
691
- adaptorVersion = version2 || "latest";
712
+ let adaptorVersion;
713
+ let adaptorName;
714
+ if (adaptor) {
715
+ const { name, version: version2 } = getNameAndVersion5(adaptor);
716
+ if (name.match("=")) {
717
+ const [namePart, pathPart] = name.split("=");
718
+ adaptorVersion = loadVersionFromPath(pathPart);
719
+ adaptorName = namePart;
720
+ } else {
721
+ adaptorName = name;
722
+ adaptorVersion = version2 || "latest";
723
+ }
692
724
  }
693
725
  let output;
694
- if (options.logJson) {
726
+ if (logJson) {
695
727
  output = {
696
728
  versions: {
697
729
  "node.js": process.version.substring(1),
@@ -701,19 +733,16 @@ var printVersions = async (logger, options = {}) => {
701
733
  }
702
734
  };
703
735
  if (adaptorName) {
704
- output.versions.adaptor = {
705
- name: adaptorName,
706
- version: adaptorVersion
707
- };
736
+ output.versions[adaptorName] = adaptorVersion;
708
737
  }
709
738
  } else {
710
739
  const adaptorVersionString = adaptorName ? `
711
- ${prefix("adaptor " + adaptorName)}${adaptorVersion}` : "";
740
+ ${prefix(adaptorName)}${adaptorVersion}` : "";
712
741
  output = `Versions:
713
- ${prefix("node.js")}${process.version.substring(1)}
714
- ${prefix("cli")}${version}
715
- ${prefix("runtime")}${runtimeVersion}
716
- ${prefix("compiler")}${compilerVersion}${adaptorVersionString}`;
742
+ ${prefix(NODE)}${process.version.substring(1)}
743
+ ${prefix(CLI2)}${version}
744
+ ${prefix(RUNTIME2)}${runtimeVersion}
745
+ ${prefix(COMPILER2)}${compilerVersion}${adaptorVersionString}`;
717
746
  }
718
747
  logger.info(output);
719
748
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfn/cli",
3
- "version": "0.0.28",
3
+ "version": "0.0.29",
4
4
  "description": "CLI devtools for the openfn toolchain.",
5
5
  "engines": {
6
6
  "node": ">=18",
@@ -36,15 +36,15 @@
36
36
  "typescript": "^4.7.4"
37
37
  },
38
38
  "dependencies": {
39
- "@openfn/compiler": "0.0.24",
40
- "@openfn/describe-package": "0.0.14",
41
- "@openfn/logger": "0.0.9",
42
- "@openfn/runtime": "0.0.18",
43
39
  "fast-safe-stringify": "^2.1.1",
44
40
  "figures": "^5.0.0",
45
41
  "rimraf": "^3.0.2",
46
42
  "treeify": "^1.1.0",
47
- "yargs": "^17.5.1"
43
+ "yargs": "^17.5.1",
44
+ "@openfn/compiler": "0.0.25",
45
+ "@openfn/describe-package": "0.0.14",
46
+ "@openfn/runtime": "0.0.19",
47
+ "@openfn/logger": "0.0.10"
48
48
  },
49
49
  "files": [
50
50
  "dist",