@openfn/project 0.8.1 → 0.9.1
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.d.ts +13 -1
- package/dist/index.js +131 -72
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,17 @@ import * as l from '@openfn/lexicon';
|
|
|
2
2
|
import l__default, { WorkspaceConfig, UUID } from '@openfn/lexicon';
|
|
3
3
|
import { Provisioner } from '@openfn/lexicon/lightning';
|
|
4
4
|
|
|
5
|
+
type SerializedProject = Omit<Partial<l.Project>, 'workflows'> & {
|
|
6
|
+
version: number;
|
|
7
|
+
workflows: SerializedWorkflow[];
|
|
8
|
+
};
|
|
9
|
+
type SerializedWorkflow = {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
steps: l.Step[];
|
|
13
|
+
openfn?: l.ProjectMeta;
|
|
14
|
+
};
|
|
15
|
+
|
|
5
16
|
type WithMeta<T> = T & {
|
|
6
17
|
openfn?: l.NodeMeta;
|
|
7
18
|
};
|
|
@@ -89,6 +100,7 @@ declare class Project {
|
|
|
89
100
|
config: l__default.WorkspaceConfig;
|
|
90
101
|
collections: any;
|
|
91
102
|
credentials: string[];
|
|
103
|
+
static from(type: 'project', data: any, options: never): Promise<Project>;
|
|
92
104
|
static from(type: 'state', data: Provisioner.Project, meta?: Partial<l__default.ProjectMeta>, config?: fromAppStateConfig): Promise<Project>;
|
|
93
105
|
static from(type: 'fs', options: FromFsConfig): Promise<Project>;
|
|
94
106
|
static from(type: 'path', data: string, options?: {
|
|
@@ -97,7 +109,7 @@ declare class Project {
|
|
|
97
109
|
static merge(source: Project, target: Project, options?: Partial<MergeProjectOptions>): Project;
|
|
98
110
|
constructor(data: Partial<l__default.Project>, config?: Partial<l__default.WorkspaceConfig>);
|
|
99
111
|
setConfig(config: Partial<WorkspaceConfig>): void;
|
|
100
|
-
serialize(type?: '
|
|
112
|
+
serialize(type?: 'project' | 'fs' | 'state', options?: any): string | Record<string, string> | Provisioner.Project_v1 | SerializedProject;
|
|
101
113
|
getWorkflow(idOrName: string): Workflow | undefined;
|
|
102
114
|
getIdentifier(): string;
|
|
103
115
|
getUUID(workflow: string | Workflow, stepId: string, otherStep?: string): any;
|
package/dist/index.js
CHANGED
|
@@ -210,7 +210,7 @@ var Workflow = class {
|
|
|
210
210
|
return this.index.uuid[id];
|
|
211
211
|
}
|
|
212
212
|
toJSON() {
|
|
213
|
-
return this.workflow;
|
|
213
|
+
return clone(this.workflow);
|
|
214
214
|
}
|
|
215
215
|
getUUIDMap() {
|
|
216
216
|
return this.index.uuid;
|
|
@@ -235,28 +235,10 @@ var Workflow_default = Workflow;
|
|
|
235
235
|
var serialize_exports = {};
|
|
236
236
|
__export(serialize_exports, {
|
|
237
237
|
fs: () => to_fs_default,
|
|
238
|
-
|
|
238
|
+
project: () => to_project_default,
|
|
239
239
|
state: () => to_app_state_default
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
-
// src/serialize/to-json.ts
|
|
243
|
-
function to_json_default(project) {
|
|
244
|
-
return {
|
|
245
|
-
// There must be a better way to do this?
|
|
246
|
-
// Do we just serialize all public fields?
|
|
247
|
-
id: project.id,
|
|
248
|
-
name: project.name,
|
|
249
|
-
description: project.description,
|
|
250
|
-
config: project.config,
|
|
251
|
-
meta: project.meta,
|
|
252
|
-
workflows: project.workflows.map((w) => w.toJSON()),
|
|
253
|
-
collections: project.collections,
|
|
254
|
-
credentials: project.credentials,
|
|
255
|
-
openfn: project.openfn,
|
|
256
|
-
options: project.options
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
|
|
260
242
|
// src/serialize/to-app-state.ts
|
|
261
243
|
import { pick, omitBy, isNil, sortBy } from "lodash-es";
|
|
262
244
|
import { randomUUID } from "node:crypto";
|
|
@@ -286,8 +268,19 @@ function jsonToYaml(json) {
|
|
|
286
268
|
}
|
|
287
269
|
|
|
288
270
|
// src/serialize/to-app-state.ts
|
|
271
|
+
var defaultJobProps = {
|
|
272
|
+
keychain_credential_id: null,
|
|
273
|
+
project_credential_id: null
|
|
274
|
+
};
|
|
289
275
|
function to_app_state_default(project, options = {}) {
|
|
290
|
-
const {
|
|
276
|
+
const {
|
|
277
|
+
uuid,
|
|
278
|
+
endpoint,
|
|
279
|
+
env,
|
|
280
|
+
id,
|
|
281
|
+
fetched_at,
|
|
282
|
+
...rest
|
|
283
|
+
} = project.openfn ?? {};
|
|
291
284
|
const state = omitBy(
|
|
292
285
|
pick(project, ["name", "description", "collections"]),
|
|
293
286
|
isNil
|
|
@@ -341,12 +334,10 @@ var mapWorkflow = (workflow) => {
|
|
|
341
334
|
node = omitBy(pick(s, ["name", "adaptor"]), isNil);
|
|
342
335
|
const { uuid: uuid2, ...otherOpenFnProps } = s.openfn ?? {};
|
|
343
336
|
node.id = uuid2;
|
|
344
|
-
Object.assign(node, otherOpenFnProps);
|
|
345
337
|
if (s.expression) {
|
|
346
338
|
node.body = s.expression;
|
|
347
339
|
}
|
|
348
|
-
node
|
|
349
|
-
node.keychain_credential_id = null;
|
|
340
|
+
Object.assign(node, defaultJobProps, otherOpenFnProps);
|
|
350
341
|
wfState.jobs.push(node);
|
|
351
342
|
}
|
|
352
343
|
Object.keys(s.next ?? {}).forEach((next) => {
|
|
@@ -380,6 +371,7 @@ var mapWorkflow = (workflow) => {
|
|
|
380
371
|
|
|
381
372
|
// src/serialize/to-fs.ts
|
|
382
373
|
import nodepath from "path";
|
|
374
|
+
import { omit } from "lodash-es";
|
|
383
375
|
|
|
384
376
|
// src/util/config.ts
|
|
385
377
|
import { readFileSync } from "node:fs";
|
|
@@ -506,10 +498,16 @@ var extractWorkflow = (project, workflowId) => {
|
|
|
506
498
|
// Not crazy about this - maybe we should do something better? Or do we like the consistency?
|
|
507
499
|
options: workflow.options,
|
|
508
500
|
steps: workflow.steps.map((step) => {
|
|
509
|
-
const { openfn, expression, ...mapped } = step;
|
|
501
|
+
const { openfn, expression, next, ...mapped } = step;
|
|
510
502
|
if (expression) {
|
|
511
503
|
mapped.expression = `./${step.id}.js`;
|
|
512
504
|
}
|
|
505
|
+
if (next && typeof next === "object") {
|
|
506
|
+
mapped.next = {};
|
|
507
|
+
for (const id in next) {
|
|
508
|
+
mapped.next[id] = omit(next[id], ["openfn"]);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
513
511
|
return mapped;
|
|
514
512
|
})
|
|
515
513
|
};
|
|
@@ -544,18 +542,52 @@ var handleOutput = (data, filePath, format) => {
|
|
|
544
542
|
return { path: path5, content };
|
|
545
543
|
};
|
|
546
544
|
|
|
547
|
-
// src/
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
545
|
+
// src/serialize/to-project.ts
|
|
546
|
+
import { omitBy as omitBy2, isNil as isNil3 } from "lodash-es";
|
|
547
|
+
var SERIALIZE_VERSION = 2;
|
|
548
|
+
var to_project_default = (project, options = {}) => {
|
|
549
|
+
const proj = omitBy2(
|
|
550
|
+
{
|
|
551
|
+
id: project.id,
|
|
552
|
+
name: project.name,
|
|
553
|
+
version: SERIALIZE_VERSION,
|
|
554
|
+
// important!
|
|
555
|
+
description: project.description,
|
|
556
|
+
collections: project.collections,
|
|
557
|
+
credentials: project.credentials,
|
|
558
|
+
openfn: project.openfn,
|
|
559
|
+
meta: project.meta,
|
|
560
|
+
options: omitBy2(project.options, isNil3),
|
|
561
|
+
//workflows: project.workflows.map(mapWorkflow) as SerializedWorkflow[],
|
|
562
|
+
workflows: project.workflows.map(
|
|
563
|
+
(w) => w.toJSON()
|
|
564
|
+
)
|
|
565
|
+
},
|
|
566
|
+
isNil3
|
|
567
|
+
);
|
|
568
|
+
const format = options.format ?? proj.config?.formats.project;
|
|
569
|
+
if (format === "json") {
|
|
570
|
+
return proj;
|
|
571
|
+
}
|
|
572
|
+
return jsonToYaml(proj);
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
// src/util/ensure-json.ts
|
|
576
|
+
var ensure_json_default = (obj) => {
|
|
577
|
+
if (typeof obj === "string") {
|
|
578
|
+
const firstChar = obj.trim()[0];
|
|
579
|
+
if (firstChar === "{" || firstChar === "[") {
|
|
580
|
+
return JSON.parse(obj);
|
|
553
581
|
} else {
|
|
554
|
-
|
|
582
|
+
return yamlToJson(obj);
|
|
555
583
|
}
|
|
556
|
-
} else {
|
|
557
|
-
stateJson = state;
|
|
558
584
|
}
|
|
585
|
+
return obj;
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
// src/parse/from-app-state.ts
|
|
589
|
+
var from_app_state_default = (state, meta = {}, config = {}) => {
|
|
590
|
+
let stateJson = ensure_json_default(state);
|
|
559
591
|
delete config.format;
|
|
560
592
|
const {
|
|
561
593
|
id,
|
|
@@ -658,24 +690,32 @@ var mapWorkflow2 = (workflow) => {
|
|
|
658
690
|
};
|
|
659
691
|
|
|
660
692
|
// src/parse/from-path.ts
|
|
661
|
-
import { extname } from "node:path";
|
|
662
693
|
import { readFile } from "node:fs/promises";
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
let
|
|
668
|
-
if (
|
|
669
|
-
|
|
670
|
-
state = JSON.parse(source);
|
|
671
|
-
} else if (ext.match(/(ya?ml)$/)) {
|
|
672
|
-
config.format = "yaml";
|
|
673
|
-
state = yamlToJson(source);
|
|
694
|
+
|
|
695
|
+
// src/parse/from-project.ts
|
|
696
|
+
var from_project_default = (data, config) => {
|
|
697
|
+
let rawJson = ensure_json_default(data);
|
|
698
|
+
let json;
|
|
699
|
+
if (rawJson.version) {
|
|
700
|
+
json = from_v2(rawJson);
|
|
674
701
|
} else {
|
|
675
|
-
|
|
702
|
+
json = from_v1(rawJson);
|
|
676
703
|
}
|
|
677
|
-
|
|
678
|
-
|
|
704
|
+
return new Project_default(json, config);
|
|
705
|
+
};
|
|
706
|
+
var from_v1 = (data) => {
|
|
707
|
+
return from_app_state_default(data);
|
|
708
|
+
};
|
|
709
|
+
var from_v2 = (data) => {
|
|
710
|
+
return {
|
|
711
|
+
...data
|
|
712
|
+
};
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
// src/parse/from-path.ts
|
|
716
|
+
var from_path_default = async (path5, config = {}) => {
|
|
717
|
+
const source = await readFile(path5, "utf8");
|
|
718
|
+
return from_project_default(source, config);
|
|
679
719
|
};
|
|
680
720
|
|
|
681
721
|
// src/parse/from-fs.ts
|
|
@@ -697,6 +737,7 @@ var get_identifier_default = (config = {}) => {
|
|
|
697
737
|
};
|
|
698
738
|
|
|
699
739
|
// src/parse/from-fs.ts
|
|
740
|
+
import { omit as omit2 } from "lodash-es";
|
|
700
741
|
var parseProject = async (options) => {
|
|
701
742
|
const { root } = options;
|
|
702
743
|
const { type, content } = findWorkspaceFile(root);
|
|
@@ -715,13 +756,13 @@ var parseProject = async (options) => {
|
|
|
715
756
|
`${identifier}.${format}`
|
|
716
757
|
);
|
|
717
758
|
const stateFile = await fs.readFile(statePath, "utf8");
|
|
718
|
-
state =
|
|
759
|
+
state = from_project_default(stateFile, config);
|
|
719
760
|
} catch (e) {
|
|
720
761
|
console.warn(`Failed to find state file for ${identifier}`);
|
|
721
762
|
}
|
|
722
763
|
const proj = {
|
|
723
764
|
name: state?.name,
|
|
724
|
-
openfn: context.project,
|
|
765
|
+
openfn: omit2(context.project, ["id"]),
|
|
725
766
|
config,
|
|
726
767
|
workflows: []
|
|
727
768
|
};
|
|
@@ -1208,6 +1249,7 @@ var Project = class {
|
|
|
1208
1249
|
options;
|
|
1209
1250
|
// local metadata used by the CLI
|
|
1210
1251
|
// This stuff is not synced back to lightning
|
|
1252
|
+
// TODO maybe rename cli or local
|
|
1211
1253
|
meta;
|
|
1212
1254
|
// this contains meta about the connected openfn project
|
|
1213
1255
|
openfn;
|
|
@@ -1216,17 +1258,23 @@ var Project = class {
|
|
|
1216
1258
|
collections;
|
|
1217
1259
|
credentials;
|
|
1218
1260
|
static async from(type, data, ...rest) {
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1261
|
+
switch (type) {
|
|
1262
|
+
case "project":
|
|
1263
|
+
var [config] = rest;
|
|
1264
|
+
return from_project_default(data, config);
|
|
1265
|
+
case "state":
|
|
1266
|
+
return from_app_state_default(data, rest[0], rest[1]);
|
|
1267
|
+
case "fs":
|
|
1268
|
+
return parseProject(data);
|
|
1269
|
+
case "path":
|
|
1270
|
+
var [config] = rest;
|
|
1271
|
+
return from_path_default(data, config);
|
|
1272
|
+
default:
|
|
1273
|
+
throw new Error(`Didn't recognize type ${type}`);
|
|
1225
1274
|
}
|
|
1226
|
-
throw new Error(`Didn't recognize type ${type}`);
|
|
1227
1275
|
}
|
|
1228
1276
|
// Diff two projects
|
|
1229
|
-
//
|
|
1277
|
+
// static diff(a: Project, b: Project) {}
|
|
1230
1278
|
// Merge a source project (staging) into the target project (main)
|
|
1231
1279
|
// Returns a new Project
|
|
1232
1280
|
// TODO: throw if histories have diverged
|
|
@@ -1252,7 +1300,7 @@ var Project = class {
|
|
|
1252
1300
|
setConfig(config) {
|
|
1253
1301
|
this.config = buildConfig(config);
|
|
1254
1302
|
}
|
|
1255
|
-
serialize(type = "
|
|
1303
|
+
serialize(type = "project", options) {
|
|
1256
1304
|
if (type in serialize_exports) {
|
|
1257
1305
|
return serialize_exports[type](this, options);
|
|
1258
1306
|
}
|
|
@@ -1315,7 +1363,7 @@ function pathExists(fpath, type) {
|
|
|
1315
1363
|
|
|
1316
1364
|
// src/Workspace.ts
|
|
1317
1365
|
var Workspace = class {
|
|
1318
|
-
// @ts-ignore config not
|
|
1366
|
+
// @ts-ignore config not definitely assigned - it sure is
|
|
1319
1367
|
config;
|
|
1320
1368
|
activeProject;
|
|
1321
1369
|
projects = [];
|
|
@@ -1343,14 +1391,9 @@ var Workspace = class {
|
|
|
1343
1391
|
const stateFilePath = path3.join(projectsPath, file);
|
|
1344
1392
|
try {
|
|
1345
1393
|
const data = fs3.readFileSync(stateFilePath, "utf-8");
|
|
1346
|
-
const project =
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
{
|
|
1350
|
-
...this.config,
|
|
1351
|
-
format: this.config?.formats.project
|
|
1352
|
-
}
|
|
1353
|
-
);
|
|
1394
|
+
const project = from_project_default(data, {
|
|
1395
|
+
...this.config
|
|
1396
|
+
});
|
|
1354
1397
|
this.projectPaths.set(project.id, stateFilePath);
|
|
1355
1398
|
return project;
|
|
1356
1399
|
} catch (e) {
|
|
@@ -1398,8 +1441,19 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
1398
1441
|
import path4 from "node:path";
|
|
1399
1442
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
1400
1443
|
import { grammar } from "ohm-js";
|
|
1401
|
-
import { isNil as
|
|
1444
|
+
import { isNil as isNil4, set } from "lodash-es";
|
|
1402
1445
|
var parser;
|
|
1446
|
+
var expectedNodeProps = [
|
|
1447
|
+
// TODO need to clarify adaptor/adaptors confusion
|
|
1448
|
+
"adaptor",
|
|
1449
|
+
"adaptors",
|
|
1450
|
+
"expression",
|
|
1451
|
+
"condition",
|
|
1452
|
+
"label",
|
|
1453
|
+
"type",
|
|
1454
|
+
"disabled",
|
|
1455
|
+
"name"
|
|
1456
|
+
];
|
|
1403
1457
|
var initOperations = (options = {}) => {
|
|
1404
1458
|
let nodes = {};
|
|
1405
1459
|
const uuidMap = options.uuidMap ?? {};
|
|
@@ -1473,7 +1527,12 @@ var initOperations = (options = {}) => {
|
|
|
1473
1527
|
const name = nameNode.sourceString;
|
|
1474
1528
|
const node = buildNode(name);
|
|
1475
1529
|
props.buildWorkflow().forEach(([key, value]) => {
|
|
1476
|
-
|
|
1530
|
+
if (expectedNodeProps.includes(key)) {
|
|
1531
|
+
nodes[name][key] = value;
|
|
1532
|
+
} else {
|
|
1533
|
+
nodes[name].openfn ??= {};
|
|
1534
|
+
nodes[name].openfn[key] = value;
|
|
1535
|
+
}
|
|
1477
1536
|
});
|
|
1478
1537
|
return node;
|
|
1479
1538
|
},
|
|
@@ -1553,7 +1612,7 @@ function generateWorkflow(def, options = {}) {
|
|
|
1553
1612
|
if (options.uuidMap && raw.id in options.uuidMap) {
|
|
1554
1613
|
uuid = options.uuidMap[raw.id];
|
|
1555
1614
|
}
|
|
1556
|
-
if (!
|
|
1615
|
+
if (!isNil4(uuid) && options.openfnUuid) {
|
|
1557
1616
|
raw.openfn ??= {};
|
|
1558
1617
|
raw.openfn.uuid = uuid;
|
|
1559
1618
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/project",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Read, serialize, replicate and sync OpenFn projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"lodash-es": "^4.17.21",
|
|
35
35
|
"ohm-js": "^17.2.1",
|
|
36
36
|
"yaml": "^2.2.2",
|
|
37
|
-
"@openfn/lexicon": "^1.2.
|
|
38
|
-
"@openfn/logger": "1.0
|
|
37
|
+
"@openfn/lexicon": "^1.2.7",
|
|
38
|
+
"@openfn/logger": "1.1.0"
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
41
|
"dist",
|