@openfn/cli 0.0.28 → 0.0.30
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 +1 -1
- package/dist/process/runner.js +105 -76
- package/package.json +6 -6
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
|
|
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
|
|
package/dist/process/runner.js
CHANGED
|
@@ -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 (
|
|
128
|
+
if (stateStdin) {
|
|
128
129
|
try {
|
|
129
|
-
const json = JSON.parse(
|
|
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(
|
|
136
|
+
log.error(stateStdin);
|
|
136
137
|
log.error(e);
|
|
137
138
|
process.exit(1);
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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.
|
|
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,
|
|
177
|
+
const [module, path5] = exp.split("=");
|
|
175
178
|
const { name, version } = getNameAndVersion(module);
|
|
176
179
|
const info = {};
|
|
177
|
-
if (
|
|
178
|
-
info.path =
|
|
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,
|
|
221
|
-
if (
|
|
222
|
-
log.debug(`Resolved ${specifier} to path: ${
|
|
223
|
-
return
|
|
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
|
|
241
|
-
if (
|
|
243
|
+
const path5 = await resolveSpecifierPath(pattern, opts.repoDir, log);
|
|
244
|
+
if (path5) {
|
|
242
245
|
try {
|
|
243
|
-
exports = await preloadAdaptorExports(
|
|
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 ${
|
|
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.
|
|
457
|
+
options.jobSource = `const fn = () => state => { console.log('${sillyMessage}'); return state * 2; } ; fn()`;
|
|
458
|
+
delete options.jobPath;
|
|
454
459
|
if (!options.stateStdin) {
|
|
455
|
-
logger.
|
|
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 = (
|
|
483
|
-
writeFileSync(
|
|
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,
|
|
490
|
+
var generateDocs = async (specifier, path5, docgen, logger) => {
|
|
490
491
|
const result = await docgen(specifier);
|
|
491
|
-
await writeFile3(
|
|
492
|
-
finish(logger,
|
|
493
|
-
return
|
|
492
|
+
await writeFile3(path5, JSON.stringify(result, null, 2));
|
|
493
|
+
finish(logger, path5);
|
|
494
|
+
return path5;
|
|
494
495
|
};
|
|
495
|
-
var waitForDocs = async (docs,
|
|
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(
|
|
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(
|
|
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 ${
|
|
518
|
-
finish(logger,
|
|
519
|
-
return
|
|
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
|
|
537
|
-
ensurePath(
|
|
537
|
+
const path5 = `${repoDir}/docs/${specifier}.json`;
|
|
538
|
+
ensurePath(path5);
|
|
538
539
|
const handleError = () => {
|
|
539
540
|
logger.info("Removing placeholder");
|
|
540
|
-
rmSync(
|
|
541
|
+
rmSync(path5);
|
|
541
542
|
};
|
|
542
543
|
try {
|
|
543
|
-
const existing = readFileSync(
|
|
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(
|
|
548
|
+
rmSync(path5);
|
|
548
549
|
throw new Error("TIMEOUT");
|
|
549
550
|
}
|
|
550
|
-
return waitForDocs(json,
|
|
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 ${
|
|
554
|
+
logger.info(`Docs JSON not found at ${path5}`);
|
|
554
555
|
}
|
|
555
556
|
logger.debug("Generating placeholder");
|
|
556
|
-
generatePlaceholder(
|
|
557
|
-
return generateDocs(specifier,
|
|
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
|
|
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 (
|
|
613
|
-
const source = await readFile(
|
|
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 {
|
|
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
|
|
695
|
+
const { adaptors, logJson } = options;
|
|
696
|
+
let adaptor = "";
|
|
697
|
+
if (adaptors && adaptors.length) {
|
|
698
|
+
adaptor = adaptors[0];
|
|
699
|
+
}
|
|
700
|
+
let adaptorVersion;
|
|
701
|
+
let adaptorName = "";
|
|
702
|
+
if (adaptor) {
|
|
703
|
+
if (adaptor.match("=")) {
|
|
704
|
+
const [namePart, pathPart] = adaptor.split("=");
|
|
705
|
+
adaptorVersion = loadVersionFromPath(pathPart);
|
|
706
|
+
adaptorName = getNameAndVersion5(namePart).name;
|
|
707
|
+
} else {
|
|
708
|
+
const { name, version: version2 } = getNameAndVersion5(adaptor);
|
|
709
|
+
adaptorName = name;
|
|
710
|
+
adaptorVersion = version2 || "latest";
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
const longest = Math.max(...[
|
|
714
|
+
NODE,
|
|
715
|
+
CLI2,
|
|
716
|
+
RUNTIME2,
|
|
717
|
+
COMPILER2,
|
|
718
|
+
adaptorName
|
|
719
|
+
].map((s) => s.length));
|
|
720
|
+
const prefix = (str) => ` ${t} ${str.padEnd(longest + 4, " ")}`;
|
|
681
721
|
const pkg = await import("../../package.json", { assert: { type: "json" } });
|
|
682
722
|
const { version, dependencies } = pkg.default;
|
|
683
723
|
const compilerVersion = dependencies["@openfn/compiler"];
|
|
684
724
|
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";
|
|
692
|
-
}
|
|
693
725
|
let output;
|
|
694
|
-
if (
|
|
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
|
|
705
|
-
name: adaptorName,
|
|
706
|
-
version: adaptorVersion
|
|
707
|
-
};
|
|
736
|
+
output.versions[adaptorName] = adaptorVersion;
|
|
708
737
|
}
|
|
709
738
|
} else {
|
|
710
739
|
const adaptorVersionString = adaptorName ? `
|
|
711
|
-
${prefix(
|
|
740
|
+
${prefix(adaptorName)}${adaptorVersion}` : "";
|
|
712
741
|
output = `Versions:
|
|
713
|
-
${prefix(
|
|
714
|
-
${prefix(
|
|
715
|
-
${prefix(
|
|
716
|
-
${prefix(
|
|
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.
|
|
3
|
+
"version": "0.0.30",
|
|
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",
|