@openfn/cli 1.11.5 → 1.12.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/dist/index.js +62 -10
- package/dist/process/runner.js +194 -62
- package/package.json +6 -5
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ import yargs from "yargs";
|
|
|
33
33
|
import { hideBin } from "yargs/helpers";
|
|
34
34
|
|
|
35
35
|
// src/options.ts
|
|
36
|
-
import
|
|
36
|
+
import nodePath from "node:path";
|
|
37
37
|
|
|
38
38
|
// src/constants.ts
|
|
39
39
|
var DEFAULT_REPO_DIR = "/tmp/openfn/repo";
|
|
@@ -171,6 +171,13 @@ var autoinstall = {
|
|
|
171
171
|
default: true
|
|
172
172
|
}
|
|
173
173
|
};
|
|
174
|
+
var apikey = {
|
|
175
|
+
name: "apikey",
|
|
176
|
+
yargs: {
|
|
177
|
+
alias: ["key", "pat", "token"],
|
|
178
|
+
description: "[beta only] API Key, Personal Access Token (Pat), or other access token"
|
|
179
|
+
}
|
|
180
|
+
};
|
|
174
181
|
var apolloUrl = {
|
|
175
182
|
name: "apollo-url",
|
|
176
183
|
yargs: {
|
|
@@ -194,6 +201,14 @@ var apolloUrl = {
|
|
|
194
201
|
});
|
|
195
202
|
}
|
|
196
203
|
};
|
|
204
|
+
var beta = {
|
|
205
|
+
name: "beta",
|
|
206
|
+
yargs: {
|
|
207
|
+
boolean: true,
|
|
208
|
+
description: "Use the beta alternative of this command: see https://github.com/OpenFn/kit/wiki/Pull-Deploy-Beta",
|
|
209
|
+
default: false
|
|
210
|
+
}
|
|
211
|
+
};
|
|
197
212
|
var cacheSteps = {
|
|
198
213
|
name: "cache-steps",
|
|
199
214
|
yargs: {
|
|
@@ -254,6 +269,19 @@ var expandAdaptors = {
|
|
|
254
269
|
setDefaultValue(opts2, "expandAdaptors", true);
|
|
255
270
|
}
|
|
256
271
|
};
|
|
272
|
+
var endpoint = {
|
|
273
|
+
name: "endpoint",
|
|
274
|
+
yargs: {
|
|
275
|
+
alias: ["lightning"],
|
|
276
|
+
description: "[beta only] URL to Lightning endpoint"
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
var env = {
|
|
280
|
+
name: "env",
|
|
281
|
+
yargs: {
|
|
282
|
+
description: "[beta only] Environment name (eg staging, prod, branch)"
|
|
283
|
+
}
|
|
284
|
+
};
|
|
257
285
|
var force = {
|
|
258
286
|
name: "force",
|
|
259
287
|
yargs: {
|
|
@@ -285,7 +313,7 @@ var ignoreImports = {
|
|
|
285
313
|
var getBaseDir = (opts2) => {
|
|
286
314
|
const basePath = opts2.path ?? ".";
|
|
287
315
|
if (/\.(jso?n?)$/.test(basePath)) {
|
|
288
|
-
return
|
|
316
|
+
return nodePath.dirname(basePath);
|
|
289
317
|
}
|
|
290
318
|
return basePath;
|
|
291
319
|
};
|
|
@@ -302,7 +330,7 @@ var inputPath = {
|
|
|
302
330
|
opts2.expressionPath = basePath;
|
|
303
331
|
} else {
|
|
304
332
|
const base = getBaseDir(opts2);
|
|
305
|
-
setDefaultValue(opts2, "expressionPath",
|
|
333
|
+
setDefaultValue(opts2, "expressionPath", nodePath.join(base, "job.js"));
|
|
306
334
|
}
|
|
307
335
|
}
|
|
308
336
|
};
|
|
@@ -351,7 +379,7 @@ var outputPath = {
|
|
|
351
379
|
delete opts2.outputPath;
|
|
352
380
|
} else {
|
|
353
381
|
const base = getBaseDir(opts2);
|
|
354
|
-
setDefaultValue(opts2, "outputPath",
|
|
382
|
+
setDefaultValue(opts2, "outputPath", nodePath.join(base, "output.json"));
|
|
355
383
|
}
|
|
356
384
|
}
|
|
357
385
|
delete opts2.o;
|
|
@@ -365,6 +393,12 @@ var projectPath = {
|
|
|
365
393
|
description: "The location of your project.yaml file"
|
|
366
394
|
}
|
|
367
395
|
};
|
|
396
|
+
var path2 = {
|
|
397
|
+
name: "path",
|
|
398
|
+
yargs: {
|
|
399
|
+
description: "Path"
|
|
400
|
+
}
|
|
401
|
+
};
|
|
368
402
|
var repoDir = {
|
|
369
403
|
name: "repo-dir",
|
|
370
404
|
yargs: () => ({
|
|
@@ -475,6 +509,13 @@ var sanitize = {
|
|
|
475
509
|
throw new Error(err);
|
|
476
510
|
}
|
|
477
511
|
};
|
|
512
|
+
var workflow = {
|
|
513
|
+
name: "workflow",
|
|
514
|
+
yargs: {
|
|
515
|
+
string: true,
|
|
516
|
+
description: "Name of the workflow to execute"
|
|
517
|
+
}
|
|
518
|
+
};
|
|
478
519
|
|
|
479
520
|
// src/util/command-builders.ts
|
|
480
521
|
import c from "chalk";
|
|
@@ -752,7 +793,8 @@ var options2 = [
|
|
|
752
793
|
}),
|
|
753
794
|
outputPath,
|
|
754
795
|
repoDir,
|
|
755
|
-
useAdaptorsMonorepo
|
|
796
|
+
useAdaptorsMonorepo,
|
|
797
|
+
workflow
|
|
756
798
|
];
|
|
757
799
|
var compileCommand = {
|
|
758
800
|
command: "compile [path]",
|
|
@@ -773,6 +815,7 @@ var command_default3 = compileCommand;
|
|
|
773
815
|
|
|
774
816
|
// src/deploy/command.ts
|
|
775
817
|
var options3 = [
|
|
818
|
+
beta,
|
|
776
819
|
configPath,
|
|
777
820
|
confirm,
|
|
778
821
|
describe,
|
|
@@ -841,7 +884,7 @@ var options5 = [
|
|
|
841
884
|
useAdaptorsMonorepo
|
|
842
885
|
];
|
|
843
886
|
var executeCommand = {
|
|
844
|
-
command: "execute [
|
|
887
|
+
command: "execute <path> [workflow]",
|
|
845
888
|
describe: `Run an openfn expression or workflow. Get more help by running openfn <command> help.
|
|
846
889
|
|
|
847
890
|
Execute will run a expression/workflow at the path and write the output state to disk (to ./state.json unless otherwise specified)
|
|
@@ -892,16 +935,25 @@ var command_default8 = {
|
|
|
892
935
|
|
|
893
936
|
// src/pull/command.ts
|
|
894
937
|
var options7 = [
|
|
895
|
-
|
|
896
|
-
|
|
938
|
+
apikey,
|
|
939
|
+
beta,
|
|
940
|
+
beta,
|
|
897
941
|
configPath,
|
|
942
|
+
endpoint,
|
|
943
|
+
env,
|
|
898
944
|
log,
|
|
945
|
+
override(path2, {
|
|
946
|
+
description: "path to output the project to"
|
|
947
|
+
}),
|
|
899
948
|
logJson,
|
|
900
|
-
|
|
949
|
+
projectPath,
|
|
950
|
+
snapshots,
|
|
951
|
+
statePath,
|
|
952
|
+
path2
|
|
901
953
|
];
|
|
902
954
|
var pullCommand = {
|
|
903
955
|
command: "pull [projectId]",
|
|
904
|
-
describe:
|
|
956
|
+
describe: `Pull a project's state and spec from a Lightning Instance to the local directory. Pass --beta to use the experimental new pull command. See https://github.com/OpenFn/kit/wiki/Pull-Deploy-Beta for docs`,
|
|
905
957
|
builder: (yargs2) => build(options7, yargs2).positional("projectId", {
|
|
906
958
|
describe: "The id of the project that should be pulled shouled be a UUID",
|
|
907
959
|
demandOption: true
|
package/dist/process/runner.js
CHANGED
|
@@ -124,14 +124,14 @@ var callApollo = async (apolloBaseUrl, serviceName, payload, logger) => {
|
|
|
124
124
|
});
|
|
125
125
|
});
|
|
126
126
|
};
|
|
127
|
-
var loadPayload = async (logger,
|
|
128
|
-
if (!
|
|
127
|
+
var loadPayload = async (logger, path12) => {
|
|
128
|
+
if (!path12) {
|
|
129
129
|
logger.warn("No JSON payload provided");
|
|
130
130
|
logger.warn("Most apollo services require JSON to be uploaded");
|
|
131
131
|
return {};
|
|
132
132
|
}
|
|
133
|
-
if (
|
|
134
|
-
const str = await readFile(
|
|
133
|
+
if (path12.endsWith(".json")) {
|
|
134
|
+
const str = await readFile(path12, "utf8");
|
|
135
135
|
const json = JSON.parse(str);
|
|
136
136
|
logger.debug("Loaded JSON payload");
|
|
137
137
|
return json;
|
|
@@ -253,13 +253,13 @@ var execute_default = async (plan, input, opts, logger) => {
|
|
|
253
253
|
};
|
|
254
254
|
function parseAdaptors(plan) {
|
|
255
255
|
const extractInfo = (specifier) => {
|
|
256
|
-
const [module,
|
|
256
|
+
const [module, path12] = specifier.split("=");
|
|
257
257
|
const { name, version } = getNameAndVersion(module);
|
|
258
258
|
const info = {
|
|
259
259
|
name
|
|
260
260
|
};
|
|
261
|
-
if (
|
|
262
|
-
info.path =
|
|
261
|
+
if (path12) {
|
|
262
|
+
info.path = path12;
|
|
263
263
|
}
|
|
264
264
|
if (version) {
|
|
265
265
|
info.version = version;
|
|
@@ -278,7 +278,8 @@ function parseAdaptors(plan) {
|
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// src/execute/serialize-output.ts
|
|
281
|
-
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
281
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
282
|
+
import { dirname } from "node:path";
|
|
282
283
|
var serializeOutput2 = async (options, result, logger) => {
|
|
283
284
|
let output = result;
|
|
284
285
|
if (output && (output.configuration || output.data)) {
|
|
@@ -294,6 +295,7 @@ var serializeOutput2 = async (options, result, logger) => {
|
|
|
294
295
|
logger.success(`Result: `);
|
|
295
296
|
logger.always(output);
|
|
296
297
|
} else if (options.outputPath) {
|
|
298
|
+
await mkdir2(dirname(options.outputPath), { recursive: true });
|
|
297
299
|
logger.debug(`Writing output to ${options.outputPath}`);
|
|
298
300
|
await writeFile2(options.outputPath, output);
|
|
299
301
|
logger.success(`State written to ${options.outputPath}`);
|
|
@@ -484,10 +486,10 @@ var stripVersionSpecifier = (specifier) => {
|
|
|
484
486
|
return specifier;
|
|
485
487
|
};
|
|
486
488
|
var resolveSpecifierPath = async (pattern, repoDir, log) => {
|
|
487
|
-
const [specifier,
|
|
488
|
-
if (
|
|
489
|
-
log.debug(`Resolved ${specifier} to path: ${
|
|
490
|
-
return
|
|
489
|
+
const [specifier, path12] = pattern.split("=");
|
|
490
|
+
if (path12) {
|
|
491
|
+
log.debug(`Resolved ${specifier} to path: ${path12}`);
|
|
492
|
+
return path12;
|
|
491
493
|
}
|
|
492
494
|
const repoPath = await getModulePath(specifier, repoDir, log);
|
|
493
495
|
if (repoPath) {
|
|
@@ -505,12 +507,12 @@ var loadTransformOptions = async (opts, log) => {
|
|
|
505
507
|
let exports;
|
|
506
508
|
const [specifier] = adaptorInput.split("=");
|
|
507
509
|
log.debug(`Trying to preload types for ${specifier}`);
|
|
508
|
-
const
|
|
509
|
-
if (
|
|
510
|
+
const path12 = await resolveSpecifierPath(adaptorInput, opts.repoDir, log);
|
|
511
|
+
if (path12) {
|
|
510
512
|
try {
|
|
511
|
-
exports = await preloadAdaptorExports(
|
|
513
|
+
exports = await preloadAdaptorExports(path12, log);
|
|
512
514
|
} catch (e) {
|
|
513
|
-
log.error(`Failed to load adaptor typedefs from path ${
|
|
515
|
+
log.error(`Failed to load adaptor typedefs from path ${path12}`);
|
|
514
516
|
log.error(e);
|
|
515
517
|
}
|
|
516
518
|
}
|
|
@@ -625,7 +627,7 @@ var validateAdaptors = async (options, logger) => {
|
|
|
625
627
|
if (options.skipAdaptorValidation) {
|
|
626
628
|
return;
|
|
627
629
|
}
|
|
628
|
-
const isPlan = options.planPath || options.workflowPath;
|
|
630
|
+
const isPlan = options.planPath || options.workflowPath || options.workflow;
|
|
629
631
|
const hasDeclaredAdaptors = options.adaptors && options.adaptors.length > 0;
|
|
630
632
|
if (isPlan && hasDeclaredAdaptors) {
|
|
631
633
|
logger.error("ERROR: adaptor and workflow provided");
|
|
@@ -648,8 +650,9 @@ var validate_adaptors_default = validateAdaptors;
|
|
|
648
650
|
|
|
649
651
|
// src/util/load-plan.ts
|
|
650
652
|
import fs3 from "node:fs/promises";
|
|
651
|
-
import path4 from "node:path";
|
|
653
|
+
import path4, { dirname as dirname2 } from "node:path";
|
|
652
654
|
import { isPath } from "@openfn/compiler";
|
|
655
|
+
import Project, { yamlToJson } from "@openfn/project";
|
|
653
656
|
|
|
654
657
|
// src/util/expand-adaptors.ts
|
|
655
658
|
var expand = (name) => {
|
|
@@ -730,6 +733,20 @@ var map_adaptors_to_monorepo_default = mapAdaptorsToMonorepo;
|
|
|
730
733
|
// src/util/load-plan.ts
|
|
731
734
|
var loadPlan = async (options, logger) => {
|
|
732
735
|
const { workflowPath, planPath, expressionPath } = options;
|
|
736
|
+
if (options.path && /ya?ml$/.test(options.path)) {
|
|
737
|
+
const content = await fs3.readFile(path4.resolve(options.path), "utf-8");
|
|
738
|
+
const workflow = yamlToJson(content);
|
|
739
|
+
options.baseDir = dirname2(options.path);
|
|
740
|
+
return loadXPlan({ workflow }, options, logger);
|
|
741
|
+
}
|
|
742
|
+
if (options.path && options.workflow) {
|
|
743
|
+
options.baseDir = options.path;
|
|
744
|
+
return fromProject(options.path, options.workflow, options, logger);
|
|
745
|
+
}
|
|
746
|
+
if (!expressionPath && !workflowPath && !/\.(js|json|yaml)+$/.test(options.path || "") && !options.workflow) {
|
|
747
|
+
const workflow = options.path;
|
|
748
|
+
return fromProject(path4.resolve("."), workflow, options, logger);
|
|
749
|
+
}
|
|
733
750
|
if (expressionPath) {
|
|
734
751
|
return loadExpression(options, logger);
|
|
735
752
|
}
|
|
@@ -746,6 +763,16 @@ var loadPlan = async (options, logger) => {
|
|
|
746
763
|
}
|
|
747
764
|
};
|
|
748
765
|
var load_plan_default = loadPlan;
|
|
766
|
+
var fromProject = async (rootDir, workflowName, options, logger) => {
|
|
767
|
+
logger.debug("Loading Repo from ", path4.resolve(rootDir));
|
|
768
|
+
const project = await Project.from("fs", { root: rootDir });
|
|
769
|
+
logger.debug("Loading workflow ", workflowName);
|
|
770
|
+
const workflow = project.getWorkflow(workflowName);
|
|
771
|
+
if (!workflow) {
|
|
772
|
+
throw new Error(`Workflow "${workflowName}" not found`);
|
|
773
|
+
}
|
|
774
|
+
return loadXPlan({ workflow }, options, logger);
|
|
775
|
+
};
|
|
749
776
|
var loadJson = async (workflowPath, logger) => {
|
|
750
777
|
let text;
|
|
751
778
|
try {
|
|
@@ -913,8 +940,8 @@ var loadXPlan = async (plan, options, logger, defaultName = "") => {
|
|
|
913
940
|
};
|
|
914
941
|
|
|
915
942
|
// src/util/assert-path.ts
|
|
916
|
-
var assert_path_default = (
|
|
917
|
-
if (!
|
|
943
|
+
var assert_path_default = (path12) => {
|
|
944
|
+
if (!path12) {
|
|
918
945
|
console.error("ERROR: no path provided!");
|
|
919
946
|
console.error("\nUsage:");
|
|
920
947
|
console.error(" open path/to/job");
|
|
@@ -975,7 +1002,8 @@ var assertStepStructure = (step, index) => {
|
|
|
975
1002
|
"expression",
|
|
976
1003
|
"state",
|
|
977
1004
|
"configuration",
|
|
978
|
-
"linker"
|
|
1005
|
+
"linker",
|
|
1006
|
+
"openfn"
|
|
979
1007
|
];
|
|
980
1008
|
for (const key in step) {
|
|
981
1009
|
if (!allowedKeys.includes(key)) {
|
|
@@ -1512,8 +1540,36 @@ import {
|
|
|
1512
1540
|
getConfig,
|
|
1513
1541
|
validateConfig
|
|
1514
1542
|
} from "@openfn/deploy";
|
|
1543
|
+
|
|
1544
|
+
// src/deploy/beta.ts
|
|
1545
|
+
import Project2 from "@openfn/project";
|
|
1546
|
+
import { deployProject } from "@openfn/deploy";
|
|
1547
|
+
async function handler(options, logger) {
|
|
1548
|
+
const { OPENFN_API_KEY } = process.env;
|
|
1549
|
+
const { endpoint } = options;
|
|
1550
|
+
const config = {
|
|
1551
|
+
apiKey: options.apiKey
|
|
1552
|
+
};
|
|
1553
|
+
if (!options.apiKey && OPENFN_API_KEY) {
|
|
1554
|
+
logger.info("Using OPENFN_API_KEY environment variable");
|
|
1555
|
+
config.apiKey = OPENFN_API_KEY;
|
|
1556
|
+
}
|
|
1557
|
+
const project = await Project2.from("fs", { root: options.path || "." });
|
|
1558
|
+
const state = project.serialize("state", { format: "json" });
|
|
1559
|
+
logger.debug("Converted local project to app state:");
|
|
1560
|
+
logger.debug(JSON.stringify(state, null, 2));
|
|
1561
|
+
config.endpoint = endpoint || project.openfn?.endpoint;
|
|
1562
|
+
logger.info("Sending project to app...");
|
|
1563
|
+
await deployProject(config, state);
|
|
1564
|
+
logger.success("Updated project at", config.endpoint);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
// src/deploy/handler.ts
|
|
1515
1568
|
var actualDeploy = deploy;
|
|
1516
1569
|
async function deployHandler(options, logger, deployFn = actualDeploy) {
|
|
1570
|
+
if (options.beta) {
|
|
1571
|
+
return handler(options, logger);
|
|
1572
|
+
}
|
|
1517
1573
|
try {
|
|
1518
1574
|
const config = mergeOverrides(await getConfig(options.configPath), options);
|
|
1519
1575
|
logger.debug("Deploying with config", JSON.stringify(config, null, 2));
|
|
@@ -1570,20 +1626,20 @@ var RETRY_COUNT = 20;
|
|
|
1570
1626
|
var TIMEOUT_MS = 1e3 * 60;
|
|
1571
1627
|
var actualDocGen = (specifier) => describePackage(specifier, {});
|
|
1572
1628
|
var ensurePath = (filePath) => mkdirSync(path7.dirname(filePath), { recursive: true });
|
|
1573
|
-
var generatePlaceholder = (
|
|
1574
|
-
writeFileSync(
|
|
1629
|
+
var generatePlaceholder = (path12) => {
|
|
1630
|
+
writeFileSync(path12, `{ "loading": true, "timestamp": ${Date.now()}}`);
|
|
1575
1631
|
};
|
|
1576
1632
|
var finish = (logger, resultPath) => {
|
|
1577
1633
|
logger.success("Done! Docs can be found at:\n");
|
|
1578
1634
|
logger.print(` ${path7.resolve(resultPath)}`);
|
|
1579
1635
|
};
|
|
1580
|
-
var generateDocs = async (specifier,
|
|
1636
|
+
var generateDocs = async (specifier, path12, docgen, logger) => {
|
|
1581
1637
|
const result = await docgen(specifier);
|
|
1582
|
-
await writeFile5(
|
|
1583
|
-
finish(logger,
|
|
1584
|
-
return
|
|
1638
|
+
await writeFile5(path12, JSON.stringify(result, null, 2));
|
|
1639
|
+
finish(logger, path12);
|
|
1640
|
+
return path12;
|
|
1585
1641
|
};
|
|
1586
|
-
var waitForDocs = async (docs,
|
|
1642
|
+
var waitForDocs = async (docs, path12, logger, retryDuration = RETRY_DURATION) => {
|
|
1587
1643
|
try {
|
|
1588
1644
|
if (docs.hasOwnProperty("loading")) {
|
|
1589
1645
|
logger.info("Docs are being loaded by another process. Waiting.");
|
|
@@ -1595,19 +1651,19 @@ var waitForDocs = async (docs, path11, logger, retryDuration = RETRY_DURATION) =
|
|
|
1595
1651
|
clearInterval(i);
|
|
1596
1652
|
reject(new Error("Timed out waiting for docs to load"));
|
|
1597
1653
|
}
|
|
1598
|
-
const updated = JSON.parse(readFileSync(
|
|
1654
|
+
const updated = JSON.parse(readFileSync(path12, "utf8"));
|
|
1599
1655
|
if (!updated.hasOwnProperty("loading")) {
|
|
1600
1656
|
logger.info("Docs found!");
|
|
1601
1657
|
clearInterval(i);
|
|
1602
|
-
resolve(
|
|
1658
|
+
resolve(path12);
|
|
1603
1659
|
}
|
|
1604
1660
|
count++;
|
|
1605
1661
|
}, retryDuration);
|
|
1606
1662
|
});
|
|
1607
1663
|
} else {
|
|
1608
|
-
logger.info(`Docs already written to cache at ${
|
|
1609
|
-
finish(logger,
|
|
1610
|
-
return
|
|
1664
|
+
logger.info(`Docs already written to cache at ${path12}`);
|
|
1665
|
+
finish(logger, path12);
|
|
1666
|
+
return path12;
|
|
1611
1667
|
}
|
|
1612
1668
|
} catch (e) {
|
|
1613
1669
|
logger.error("Existing doc JSON corrupt. Aborting");
|
|
@@ -1624,28 +1680,28 @@ var docgenHandler = (options, logger, docgen = actualDocGen, retryDuration = RET
|
|
|
1624
1680
|
process.exit(9);
|
|
1625
1681
|
}
|
|
1626
1682
|
logger.success(`Generating docs for ${specifier}`);
|
|
1627
|
-
const
|
|
1628
|
-
ensurePath(
|
|
1683
|
+
const path12 = `${repoDir}/docs/${specifier}.json`;
|
|
1684
|
+
ensurePath(path12);
|
|
1629
1685
|
const handleError2 = () => {
|
|
1630
1686
|
logger.info("Removing placeholder");
|
|
1631
|
-
rmSync(
|
|
1687
|
+
rmSync(path12);
|
|
1632
1688
|
};
|
|
1633
1689
|
try {
|
|
1634
|
-
const existing = readFileSync(
|
|
1690
|
+
const existing = readFileSync(path12, "utf8");
|
|
1635
1691
|
const json = JSON.parse(existing);
|
|
1636
1692
|
if (json && json.timeout && Date.now() - json.timeout >= TIMEOUT_MS) {
|
|
1637
1693
|
logger.info(`Expired placeholder found. Removing.`);
|
|
1638
|
-
rmSync(
|
|
1694
|
+
rmSync(path12);
|
|
1639
1695
|
throw new Error("TIMEOUT");
|
|
1640
1696
|
}
|
|
1641
|
-
return waitForDocs(json,
|
|
1697
|
+
return waitForDocs(json, path12, logger, retryDuration);
|
|
1642
1698
|
} catch (e) {
|
|
1643
1699
|
if (e.message !== "TIMEOUT") {
|
|
1644
|
-
logger.info(`Docs JSON not found at ${
|
|
1700
|
+
logger.info(`Docs JSON not found at ${path12}`);
|
|
1645
1701
|
}
|
|
1646
1702
|
logger.debug("Generating placeholder");
|
|
1647
|
-
generatePlaceholder(
|
|
1648
|
-
return generateDocs(specifier,
|
|
1703
|
+
generatePlaceholder(path12);
|
|
1704
|
+
return generateDocs(specifier, path12, docgen, logger).catch((e2) => {
|
|
1649
1705
|
logger.error("Error generating documentation");
|
|
1650
1706
|
logger.error(e2);
|
|
1651
1707
|
handleError2();
|
|
@@ -1696,7 +1752,7 @@ var docsHandler = async (options, logger) => {
|
|
|
1696
1752
|
logger.success(`Showing docs for ${adaptorName} v${version}`);
|
|
1697
1753
|
}
|
|
1698
1754
|
logger.info("Generating/loading documentation...");
|
|
1699
|
-
const
|
|
1755
|
+
const path12 = await handler_default7(
|
|
1700
1756
|
{
|
|
1701
1757
|
specifier: `${name}@${version}`,
|
|
1702
1758
|
repoDir
|
|
@@ -1705,8 +1761,8 @@ var docsHandler = async (options, logger) => {
|
|
|
1705
1761
|
createNullLogger()
|
|
1706
1762
|
);
|
|
1707
1763
|
let didError = false;
|
|
1708
|
-
if (
|
|
1709
|
-
const source = await readFile4(
|
|
1764
|
+
if (path12) {
|
|
1765
|
+
const source = await readFile4(path12, "utf8");
|
|
1710
1766
|
const data = JSON.parse(source);
|
|
1711
1767
|
let desc;
|
|
1712
1768
|
if (operation) {
|
|
@@ -1745,7 +1801,7 @@ var handler_default8 = docsHandler;
|
|
|
1745
1801
|
import { createHash } from "node:crypto";
|
|
1746
1802
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
1747
1803
|
import path8 from "node:path";
|
|
1748
|
-
import { writeFile as writeFile6, mkdir as
|
|
1804
|
+
import { writeFile as writeFile6, mkdir as mkdir3 } from "node:fs/promises";
|
|
1749
1805
|
var getPath = (repoDir, key) => `${repoDir}/meta/${key}.json`;
|
|
1750
1806
|
var sortKeys = (obj) => {
|
|
1751
1807
|
const newObj = {};
|
|
@@ -1775,7 +1831,7 @@ var get2 = (repoPath, key) => {
|
|
|
1775
1831
|
};
|
|
1776
1832
|
var set2 = async (repoPath, key, data) => {
|
|
1777
1833
|
const fullPath = getPath(repoPath, key);
|
|
1778
|
-
await
|
|
1834
|
+
await mkdir3(path8.dirname(fullPath), { recursive: true });
|
|
1779
1835
|
await writeFile6(fullPath, JSON.stringify(data));
|
|
1780
1836
|
};
|
|
1781
1837
|
var cache_default = { get: get2, set: set2, generateKey, getPath, sortKeys };
|
|
@@ -1863,16 +1919,92 @@ var metadataHandler = async (options, logger) => {
|
|
|
1863
1919
|
var handler_default9 = metadataHandler;
|
|
1864
1920
|
|
|
1865
1921
|
// src/pull/handler.ts
|
|
1866
|
-
import
|
|
1867
|
-
import
|
|
1922
|
+
import path10 from "path";
|
|
1923
|
+
import fs5 from "node:fs/promises";
|
|
1868
1924
|
import {
|
|
1869
1925
|
getConfig as getConfig2,
|
|
1870
|
-
getProject,
|
|
1926
|
+
getProject as getProject2,
|
|
1871
1927
|
getSpec,
|
|
1872
1928
|
getStateFromProjectPayload,
|
|
1873
1929
|
syncRemoteSpec
|
|
1874
1930
|
} from "@openfn/deploy";
|
|
1931
|
+
|
|
1932
|
+
// src/pull/beta.ts
|
|
1933
|
+
import { confirm } from "@inquirer/prompts";
|
|
1934
|
+
import path9 from "path";
|
|
1935
|
+
import fs4 from "node:fs/promises";
|
|
1936
|
+
import { getProject } from "@openfn/deploy";
|
|
1937
|
+
import Project3 from "@openfn/project";
|
|
1938
|
+
import { rimraf } from "rimraf";
|
|
1939
|
+
async function handler2(options, logger) {
|
|
1940
|
+
const { OPENFN_API_KEY, OPENFN_ENDPOINT } = process.env;
|
|
1941
|
+
const config = {
|
|
1942
|
+
apiKey: options.apiKey,
|
|
1943
|
+
endpoint: options.endpoint
|
|
1944
|
+
};
|
|
1945
|
+
if (!options.apiKey && OPENFN_API_KEY) {
|
|
1946
|
+
logger.info("Using OPENFN_API_KEY environment variable");
|
|
1947
|
+
config.apiKey = OPENFN_API_KEY;
|
|
1948
|
+
}
|
|
1949
|
+
if (!options.endpoint && OPENFN_ENDPOINT) {
|
|
1950
|
+
logger.info("Using OPENFN_ENDPOINT environment variable");
|
|
1951
|
+
config.endpoint = OPENFN_ENDPOINT;
|
|
1952
|
+
}
|
|
1953
|
+
const { data } = await getProject(config, options.projectId);
|
|
1954
|
+
const name = options.env || "project";
|
|
1955
|
+
const project = Project3.from("state", data, {
|
|
1956
|
+
endpoint: config.endpoint,
|
|
1957
|
+
env: name,
|
|
1958
|
+
fetched_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1959
|
+
});
|
|
1960
|
+
const outputRoot = path9.resolve(options.path || ".");
|
|
1961
|
+
const projectFileName = project.getIdentifier();
|
|
1962
|
+
await fs4.mkdir(`${outputRoot}/.projects`, { recursive: true });
|
|
1963
|
+
let stateOutputPath = `${outputRoot}/.projects/${projectFileName}`;
|
|
1964
|
+
const workflowsRoot = path9.resolve(
|
|
1965
|
+
outputRoot,
|
|
1966
|
+
project.repo?.workflowRoot ?? "workflows"
|
|
1967
|
+
);
|
|
1968
|
+
if (!await confirm({
|
|
1969
|
+
message: `This will remove all files in ${path9.resolve(
|
|
1970
|
+
workflowsRoot
|
|
1971
|
+
)} and rebuild the workflow. Are you sure you wish to proceed?
|
|
1972
|
+
`,
|
|
1973
|
+
default: true
|
|
1974
|
+
})) {
|
|
1975
|
+
logger.always("Cancelled");
|
|
1976
|
+
return false;
|
|
1977
|
+
}
|
|
1978
|
+
await rimraf(workflowsRoot);
|
|
1979
|
+
const state = project?.serialize("state");
|
|
1980
|
+
if (project.repo?.formats.project === "yaml") {
|
|
1981
|
+
await fs4.writeFile(`${stateOutputPath}.yaml`, state);
|
|
1982
|
+
} else {
|
|
1983
|
+
await fs4.writeFile(
|
|
1984
|
+
`${stateOutputPath}.json`,
|
|
1985
|
+
JSON.stringify(state, null, 2)
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
logger.success(`Saved project file to ${stateOutputPath}`);
|
|
1989
|
+
const files = project?.serialize("fs");
|
|
1990
|
+
for (const f in files) {
|
|
1991
|
+
if (files[f]) {
|
|
1992
|
+
await fs4.mkdir(path9.join(outputRoot, path9.dirname(f)), {
|
|
1993
|
+
recursive: true
|
|
1994
|
+
});
|
|
1995
|
+
await fs4.writeFile(path9.join(outputRoot, f), files[f]);
|
|
1996
|
+
} else {
|
|
1997
|
+
console.log("WARNING! No content for file", f);
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
logger.success(`Expanded project to ${outputRoot}`);
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
// src/pull/handler.ts
|
|
1875
2004
|
async function pullHandler(options, logger) {
|
|
2005
|
+
if (options.beta) {
|
|
2006
|
+
return handler2(options, logger);
|
|
2007
|
+
}
|
|
1876
2008
|
try {
|
|
1877
2009
|
const config = mergeOverrides2(await getConfig2(options.configPath), options);
|
|
1878
2010
|
if (process.env["OPENFN_API_KEY"]) {
|
|
@@ -1886,7 +2018,7 @@ async function pullHandler(options, logger) {
|
|
|
1886
2018
|
logger.always(
|
|
1887
2019
|
"Downloading existing project state (as JSON) from the server."
|
|
1888
2020
|
);
|
|
1889
|
-
const { data: project } = await
|
|
2021
|
+
const { data: project } = await getProject2(
|
|
1890
2022
|
config,
|
|
1891
2023
|
options.projectId,
|
|
1892
2024
|
options.snapshots
|
|
@@ -1925,7 +2057,7 @@ async function pullHandler(options, logger) {
|
|
|
1925
2057
|
process.exitCode = 1;
|
|
1926
2058
|
process.exit(1);
|
|
1927
2059
|
}
|
|
1928
|
-
const resolvedPath =
|
|
2060
|
+
const resolvedPath = path10.resolve(config.specPath);
|
|
1929
2061
|
logger.debug("reading spec from", resolvedPath);
|
|
1930
2062
|
const updatedSpec = await syncRemoteSpec(
|
|
1931
2063
|
await res.text(),
|
|
@@ -1933,11 +2065,11 @@ async function pullHandler(options, logger) {
|
|
|
1933
2065
|
config,
|
|
1934
2066
|
logger
|
|
1935
2067
|
);
|
|
1936
|
-
await
|
|
1937
|
-
|
|
2068
|
+
await fs5.writeFile(
|
|
2069
|
+
path10.resolve(config.statePath),
|
|
1938
2070
|
JSON.stringify(state, null, 2)
|
|
1939
2071
|
);
|
|
1940
|
-
await
|
|
2072
|
+
await fs5.writeFile(resolvedPath, updatedSpec);
|
|
1941
2073
|
const spec = await getSpec(resolvedPath);
|
|
1942
2074
|
if (spec.errors.length > 0) {
|
|
1943
2075
|
logger.error("ERROR: invalid spec");
|
|
@@ -1968,7 +2100,7 @@ var handler_default10 = pullHandler;
|
|
|
1968
2100
|
|
|
1969
2101
|
// src/util/print-versions.ts
|
|
1970
2102
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
1971
|
-
import
|
|
2103
|
+
import path11 from "node:path";
|
|
1972
2104
|
import url from "node:url";
|
|
1973
2105
|
import { getNameAndVersion as getNameAndVersion5 } from "@openfn/runtime";
|
|
1974
2106
|
import { mainSymbols } from "figures";
|
|
@@ -1980,7 +2112,7 @@ var { triangleRightSmall: t } = mainSymbols;
|
|
|
1980
2112
|
var loadVersionFromPath = (adaptorPath) => {
|
|
1981
2113
|
try {
|
|
1982
2114
|
const pkg = JSON.parse(
|
|
1983
|
-
readFileSync3(
|
|
2115
|
+
readFileSync3(path11.resolve(adaptorPath, "package.json"), "utf8")
|
|
1984
2116
|
);
|
|
1985
2117
|
return pkg.version;
|
|
1986
2118
|
} catch (e) {
|
|
@@ -2015,8 +2147,8 @@ var printVersions = async (logger, options = {}, includeComponents = false) => {
|
|
|
2015
2147
|
...[NODE, CLI2, RUNTIME2, COMPILER2, longestAdaptorName].map((s) => s.length)
|
|
2016
2148
|
);
|
|
2017
2149
|
const prefix = (str) => ` ${t} ${str.padEnd(longest + 4, " ")}`;
|
|
2018
|
-
const
|
|
2019
|
-
const pkg = JSON.parse(readFileSync3(`${
|
|
2150
|
+
const dirname3 = path11.dirname(url.fileURLToPath(import.meta.url));
|
|
2151
|
+
const pkg = JSON.parse(readFileSync3(`${dirname3}/../../package.json`, "utf8"));
|
|
2020
2152
|
const { version, dependencies } = pkg;
|
|
2021
2153
|
const compilerVersion = dependencies["@openfn/compiler"];
|
|
2022
2154
|
const runtimeVersion = dependencies["@openfn/runtime"];
|
|
@@ -2099,13 +2231,13 @@ var parse = async (options, log) => {
|
|
|
2099
2231
|
logger
|
|
2100
2232
|
);
|
|
2101
2233
|
}
|
|
2102
|
-
const
|
|
2103
|
-
if (!
|
|
2234
|
+
const handler3 = handlers[options.command];
|
|
2235
|
+
if (!handler3) {
|
|
2104
2236
|
logger.error(`Unrecognised command: ${options.command}`);
|
|
2105
2237
|
process.exit(1);
|
|
2106
2238
|
}
|
|
2107
2239
|
try {
|
|
2108
|
-
return await
|
|
2240
|
+
return await handler3(options, logger);
|
|
2109
2241
|
} catch (e) {
|
|
2110
2242
|
if (!process.exitCode) {
|
|
2111
2243
|
process.exitCode = e.exitCode || 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "CLI devtools for the openfn toolchain.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18",
|
|
@@ -42,15 +42,16 @@
|
|
|
42
42
|
"@inquirer/prompts": "^1.1.4",
|
|
43
43
|
"chalk": "^5.1.2",
|
|
44
44
|
"figures": "^5.0.0",
|
|
45
|
-
"rimraf": "^
|
|
45
|
+
"rimraf": "^6.0.1",
|
|
46
46
|
"treeify": "^1.1.0",
|
|
47
47
|
"undici": "^7.1.0",
|
|
48
48
|
"ws": "^8.18.0",
|
|
49
49
|
"yargs": "^17.7.2",
|
|
50
|
-
"@openfn/
|
|
51
|
-
"@openfn/compiler": "1.0.3",
|
|
52
|
-
"@openfn/deploy": "0.11.1",
|
|
50
|
+
"@openfn/compiler": "1.0.4",
|
|
53
51
|
"@openfn/describe-package": "0.1.4",
|
|
52
|
+
"@openfn/deploy": "0.11.1",
|
|
53
|
+
"@openfn/lexicon": "^1.2.2",
|
|
54
|
+
"@openfn/project": "^0.1.0",
|
|
54
55
|
"@openfn/logger": "1.0.5",
|
|
55
56
|
"@openfn/runtime": "1.6.4"
|
|
56
57
|
},
|