@openfn/cli 0.0.11 → 0.0.14

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
@@ -3,15 +3,16 @@
3
3
  This package contains a new devtools CLI.
4
4
 
5
5
  The CLI allows you to
6
- * Run a job (expression), writing output to disk or stdout
7
- * ~~Compile a job~~ (coming soon)
8
- * ~~Validate a job~~ (coming soon)
9
- * Use local language adaptors to run the job
6
+
7
+ - Run a job (expression), writing output to disk or stdout
8
+ - Compile a job
9
+ - Install modules for jobs
10
+ - Use local language adaptors to run the job
10
11
 
11
12
  The CLI reads a path as its main argument. That path should either point to a .js file or a folder.
12
13
 
13
- * If the path ends in .js, load as a job file and execute. State and output will be read/written relative to it.
14
- * If the path is a folder, the CLI will look for a job.js, state.json and write an output.json.
14
+ - If the path ends in .js, load as a job file and execute. State and output will be read/written relative to it.
15
+ - If the path is a folder, the CLI will look for a job.js, state.json and write an output.json.
15
16
 
16
17
  From this input it will infer a working directory, from which state will be read and output will be written.
17
18
 
@@ -29,15 +30,40 @@ $ openfn --help
29
30
  $ openfn path/to/expression.js`
30
31
  ```
31
32
 
32
- ## legacy Jobs failing?
33
+ ## Language Adaptors
34
+
35
+ The old engine used to compile knowlede of langauge adaptors into the job file. We no longer do this.
36
+
37
+ Generally the new runtime prefers to explictly import all dependencies - although the compiler will auto-insert imports from a given adaptor for you.
33
38
 
34
- If legacy jobs ar failing because adaptor functions aren't found, you need to tell the CLI which adaptor to use. It will then auto-insert import statements for you.
39
+ You need to pass the name of an adaptor for the runtime to use. It will auto-insert an import statement for you.
35
40
 
41
+ ```
42
+ $ openfn job.js -a commmon
43
+ ```
44
+
45
+ You can use a short-hand name, like above, but longform names also work:
36
46
  ```
37
47
  $ openfn job.js -a @openfn/language-commmon
38
48
  ```
39
49
 
40
- There's more detail in this further down in the readme.
50
+ You can pass an explicit version number too:
51
+
52
+ ```
53
+ $ openfn job.js -a commmon@1.7.3
54
+ ```
55
+
56
+ The adaptor also needs to be installed in the CLI's module repo. You can do this manually:
57
+
58
+ ```
59
+ $ openfn install commmon
60
+ ```
61
+ If no version is provided, the latest will be installed. Again, long and short-form names can be used.
62
+
63
+ Alternatively, pass the -i flag when running a job (it's safe to do this redundantly):
64
+ ```
65
+ $ openfn job.js -i -a @openfn/language-commmon
66
+ ```
41
67
 
42
68
  ## Usage from this repo
43
69
 
@@ -60,36 +86,20 @@ $ npm install -g .
60
86
 
61
87
  Note that this will install the built source from `dist`
62
88
 
63
- ## Current state
64
-
65
- For legacy jobs (ie, jobs without explicit imports), the new runtime is only compatible with language adaptors with type definitions.
66
-
67
- Right now, that means @openfn/language-common@2.0.0-rc3.
89
+ ## Repo Directory
68
90
 
69
- ## Getting Started
91
+ The CLI will save and load adaptors from an arbitrary folder on your system.
70
92
 
71
- Here's how I recommend getting set up:
72
-
73
- * Create a folder for next-gen language adaptors somewhere on your machine
74
-
75
- ```
76
- $ mkdir -p ~/adaptors/@openfn
77
- ```
78
-
79
- * Clone `language-common` into that folder
80
-
81
- ```
82
- git clone https://github.com/OpenFn/language-common.git ~/adaptors/@openfn --branch 2.0.0-pre
83
- ```
84
-
85
- * Set your `OPENFN_MODULES_HOME` environment variable to point to the next-gen adaptors folder. This will tell the CLI to load adaptors from this folder by default.
93
+ You should set the OPENFN_REPO_DIR env var to something sensible.
86
94
 
87
95
  ```
88
96
  # In ~/.bashc or whatever
89
- export OPENFN_MODULES_HOME=~/adaptors/@openfn
97
+ export OPENFN_REPO_DIR=~/adaptors/@openfn
90
98
  ```
91
99
 
92
- This will improve in future, as we implement automatic module loading and add type definitions to the published adaptor packages.
100
+ At the time of writing, teh env var name is about to change. Soon you will be able to pass the repo dir into the command line, but the env var is a much easier way to work.
101
+
102
+ Monorepo support is coming soon.
93
103
 
94
104
  ## Automatic Imports
95
105
 
@@ -105,21 +115,3 @@ $ openfn job.js --adaptors @openfn/language-http=path/to/adaptor
105
115
  If a path is passed (relative to the working directory), that path will be used to load a local version of the adaptor (both at runtime and for import generation)
106
116
 
107
117
  If no path is passed, the currently deployed npm package will be used.
108
-
109
- ## Notes on Module Resolution
110
-
111
- Any import statements inside a job have to resolve to a node module.
112
-
113
- A module can be resolved:
114
-
115
- * Relative to the env var OPENFN_MODULE_HOME
116
- * Relative to CLI's node_modules
117
- * Relative to global node_modules
118
-
119
- Basically, to work with adaptors, you should:
120
-
121
- * Save your adaptors globally
122
-
123
- Or
124
-
125
- * Save adaptors to a folder somewhere (~/openfn) and set OPENFN_MODULE_HOME=~/openfn
package/dist/index.d.ts CHANGED
@@ -1,2 +1 @@
1
1
  #!/usr/bin/env node
2
- export {};
package/dist/index.js CHANGED
@@ -1,102 +1,179 @@
1
1
  #!/usr/bin/env node
2
- import path from 'node:path';
3
- import * as url from 'url';
4
- import { fork } from 'node:child_process';
5
- import yargs from 'yargs';
6
- import { hideBin } from 'yargs/helpers';
7
2
 
8
- /**
9
- * Utility to run CLI commands inside a child process
10
- * This lets us hide the neccessary arguments needed to run our devtools
11
- */
12
- // The default export will create a new child process which calls itself
13
- function runInChildProcess (basePath, opts) {
14
- const execArgv = [
15
- // Suppress experimental argument warnings
16
- '--no-warnings',
17
- // Allows us to load an ESM module from a text string
18
- '--experimental-vm-modules',
19
- // Allows us to do import('path/to/language-common') in the linker
20
- '--experimental-specifier-resolution=node',
21
- ];
22
- const dirname = path.dirname(url.fileURLToPath(import.meta.url));
23
- const child = fork(`${dirname}/process/runner.js`, [], { execArgv });
24
- child.on('message', ({ done }) => {
25
- if (done) {
26
- child.kill();
27
- process.exit(0);
28
- }
29
- });
30
- child.send({ init: true, basePath, opts });
3
+ // src/process/spawn.ts
4
+ import path from "node:path";
5
+ import * as url from "url";
6
+ import { fork } from "node:child_process";
7
+ function spawn_default(basePath, opts2) {
8
+ const execArgv = [
9
+ "--no-warnings",
10
+ "--experimental-vm-modules",
11
+ "--experimental-specifier-resolution=node"
12
+ ];
13
+ const dirname = path.dirname(url.fileURLToPath(import.meta.url));
14
+ const child = fork(`${dirname}/process/runner.js`, [], { execArgv });
15
+ child.on("message", ({ done }) => {
16
+ if (done) {
17
+ child.kill();
18
+ process.exit(0);
19
+ }
20
+ });
21
+ child.send({ init: true, basePath, opts: opts2 });
31
22
  }
32
23
 
33
- const cmd = yargs(hideBin(process.argv))
34
- .command('[path]', "Run the job at the path")
35
- .command('--test', "Run a trivial test job with no disk I/O")
36
- .example('openfn path/to/dir', 'Looks for job.js, state.json in path/to/dir')
37
- .example('openfn foo/job.js', 'Reads foo/job.js, looks for state and output in foo')
38
- .example('openfn job.js -adaptor @openfn/language-common', 'Run job.js with automatic imports from the commmon language adaptor')
39
- .example('openfn job.js -adaptor @openfn/language-common=repo/openfn/language-common', 'Run job.js with a local implementation of the common language adaptor')
40
- .example('openfn foo/job.js -c', 'Compile a job to foo/output/js')
41
- .example('openfn foo/job.js -cO', 'Compile a job to stdout')
42
- .example('openfn foo/job.js --log debug', 'Run a job with debug-level logging')
43
- .example('openfn foo/job.js --log compiler=debug', 'Use debug logging in the compiler only')
44
- .positional('path', {
45
- describe: 'The path to load the job from (a .js file or a dir containing a job.js file)',
46
- demandOption: true
47
- })
48
- .option('test', {
49
- description: 'Run a test job to exercise the installation. Pass a number via -S to multiply by 2.',
50
- boolean: true,
51
- })
52
- .option('output-path', {
53
- alias: 'o',
54
- description: 'Path to the output file',
55
- })
56
- .option('output-stdout', {
57
- alias: 'O',
58
- boolean: true,
59
- description: 'Print output to stdout (intead of a file)',
60
- })
61
- .option('state-path', {
62
- alias: 's',
63
- description: 'Path to the state file'
64
- })
65
- .option('state-stdin', {
66
- alias: 'S',
67
- description: 'Read state from stdin (instead of a file)'
68
- })
69
- .option('no-validation', {
70
- boolean: true,
71
- description: 'Skip validation'
72
- })
73
- .option('compile-only', {
74
- alias: 'c',
75
- boolean: true,
76
- description: 'Compile the job but don\'t execute it. State is written to output.js or returned to console if -O is set.'
77
- })
78
- .option('no-compile', {
79
- boolean: true,
80
- description: 'Skip compilation'
81
- })
82
- .option('adaptors', {
83
- alias: ['a', 'adaptor'],
84
- description: 'Pass one or more adaptors in the form name=path/to/adaptor',
85
- array: true
86
- })
87
- // TODO this becomes log compiler=debug
88
- .option('trace-linker', {
89
- alias: ['t', 'trace'],
90
- description: 'Trace module resolution output in the linker',
91
- boolean: true,
92
- })
93
- .option('log', {
94
- alias: ['l'],
95
- description: 'Set the default log level to none, trace, info or default',
96
- array: true
97
- })
98
- .alias('v', 'version');
24
+ // src/cli.ts
25
+ import yargs from "yargs";
26
+ import { hideBin } from "yargs/helpers";
99
27
 
100
- const opts = cmd.parse();
101
- runInChildProcess(opts._[0], opts);
102
- //# sourceMappingURL=index.js.map
28
+ // src/repo/command.ts
29
+ var repo = {
30
+ command: "repo [subcommand]",
31
+ desc: "Run commands on the module repo (install|clean)",
32
+ builder: (yargs2) => yargs2.command(clean).command(install).command(pwd).command(list).example("repo install -a http", "Install @openfn/language-http").example("repo clean", "Remove everything from the repo working dir").example("repo pwd", "Print the current repo working dir")
33
+ };
34
+ var install = {
35
+ command: "install [packages...]",
36
+ desc: "install one or more packages to the runtime repo",
37
+ handler: (argv) => {
38
+ argv.command = "repo-install";
39
+ },
40
+ builder: (yargs2) => {
41
+ return yargs2.option("adaptor", {
42
+ alias: ["a"],
43
+ description: "Install an adaptor by passing a shortened version of the name",
44
+ boolean: true
45
+ }).example("install axios", "Install the axios npm package to the repo").example(
46
+ "install -a http",
47
+ "Install @openfn/language-http adaptor to the repo"
48
+ ).example(
49
+ "install @openfn/language-http",
50
+ "Install the language-http adaptor to the repo"
51
+ );
52
+ }
53
+ };
54
+ var clean = {
55
+ command: "clean",
56
+ desc: "Removes all modules from the runtime module repo",
57
+ handler: (argv) => {
58
+ argv.command = "repo-clean";
59
+ },
60
+ builder: (yargs2) => yargs2.option("force", {
61
+ alias: ["f"],
62
+ description: "Skip the prompt and force deletion",
63
+ boolean: true
64
+ })
65
+ };
66
+ var pwd = {
67
+ command: "pwd",
68
+ desc: "Print repo's current working directory",
69
+ handler: (argv) => {
70
+ argv.command = "repo-pwd";
71
+ }
72
+ };
73
+ var list = {
74
+ command: "list",
75
+ desc: "Show a report on what is installed in the repo",
76
+ handler: (argv) => {
77
+ argv.command = "repo-list";
78
+ }
79
+ };
80
+
81
+ // src/execute/command.ts
82
+ var executeCommand = {
83
+ command: "execute [path]",
84
+ desc: "Run an openfn job",
85
+ aliases: ["$0"],
86
+ handler: (argv) => {
87
+ argv.command = "execute";
88
+ },
89
+ builder: (yargs2) => {
90
+ return applyExecuteOptions(yargs2).option("immutable", {
91
+ boolean: true,
92
+ description: "Treat state as immutable"
93
+ }).option("autoinstall", {
94
+ alias: "i",
95
+ boolean: true,
96
+ description: "Auto-install the language adaptor"
97
+ }).option("state-path", {
98
+ alias: "s",
99
+ description: "Path to the state file"
100
+ }).option("state-stdin", {
101
+ alias: "S",
102
+ description: "Read state from stdin (instead of a file)"
103
+ }).option("no-compile", {
104
+ boolean: true,
105
+ description: "Skip compilation"
106
+ }).example(
107
+ "openfn foo/job.js",
108
+ "Reads foo/job.js, looks for state and output in foo"
109
+ ).example(
110
+ "openfn job.js -a common",
111
+ "Run job.js using @openfn/language-common"
112
+ ).example(
113
+ "openfn install -a common",
114
+ "Install the latest version of language-common to the repo"
115
+ );
116
+ }
117
+ };
118
+ var applyExecuteOptions = (yargs2) => yargs2.positional("path", {
119
+ describe: "The path to load the job from (a .js file or a dir containing a job.js file)",
120
+ demandOption: true
121
+ }).option("output-path", {
122
+ alias: "o",
123
+ description: "Path to the output file"
124
+ }).option("output-stdout", {
125
+ alias: "O",
126
+ boolean: true,
127
+ description: "Print output to stdout (intead of a file)"
128
+ }).option("adaptors", {
129
+ alias: ["a", "adaptor"],
130
+ description: "A language adaptor to use for the job. Short-form names are allowed. Can include an explicit path to a local adaptor build.",
131
+ array: true
132
+ }).option("no-expand", {
133
+ description: "Don attempt to auto-expand adaptor shorthand names",
134
+ boolean: true
135
+ });
136
+ var command_default = executeCommand;
137
+
138
+ // src/compile/command.ts
139
+ var compileCommand = {
140
+ command: "compile [path]",
141
+ desc: "compile a openfn job and print or save the resulting js",
142
+ handler: (argv) => {
143
+ argv.command = "compile";
144
+ },
145
+ builder: (yargs2) => {
146
+ return applyExecuteOptions(yargs2).example(
147
+ "compile foo/job.js -O",
148
+ "Compiles foo/job.js and prints the result to stdout"
149
+ ).example(
150
+ "compile foo/job.js -o foo/job-compiled.js",
151
+ "Compiles foo/job.js and saves the result to foo/job-compiled.js"
152
+ );
153
+ }
154
+ };
155
+ var command_default2 = compileCommand;
156
+
157
+ // src/test/command.ts
158
+ var command_default3 = {
159
+ command: "test",
160
+ desc: "Compiles and runs a test job, printing the result to stdout",
161
+ handler: (argv) => {
162
+ argv.command = "test";
163
+ },
164
+ builder: (yargs2) => yargs2.option("state-stdin", {
165
+ alias: "S",
166
+ description: "Read state from stdin (instead of a file)"
167
+ }).example("test", "run the test script").example("test -S 42", "run the test script with state 42")
168
+ };
169
+
170
+ // src/cli.ts
171
+ var cmd = yargs(hideBin(process.argv)).command(command_default).command(command_default2).command(install).command(repo).command(command_default3).option("log", {
172
+ alias: ["l"],
173
+ description: "Set the default log level to none, trace, info or default",
174
+ array: true
175
+ }).alias("v", "version").help();
176
+
177
+ // src/index.ts
178
+ var opts = cmd.parse();
179
+ spawn_default(opts.path, opts);
@@ -1 +1 @@
1
- export {};
1
+