@openfn/project 0.9.0 → 0.9.2
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 +19 -2
- package/dist/index.js +167 -85
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as l from '@openfn/lexicon';
|
|
2
2
|
import l__default, { WorkspaceConfig, UUID } from '@openfn/lexicon';
|
|
3
|
+
import { Logger } from '@openfn/logger';
|
|
3
4
|
import { Provisioner } from '@openfn/lexicon/lightning';
|
|
4
5
|
|
|
5
6
|
type WithMeta<T> = T & {
|
|
@@ -42,6 +43,17 @@ type FromFsConfig = {
|
|
|
42
43
|
root: string;
|
|
43
44
|
};
|
|
44
45
|
|
|
46
|
+
type SerializedProject = Omit<Partial<l.Project>, 'workflows'> & {
|
|
47
|
+
version: number;
|
|
48
|
+
workflows: SerializedWorkflow[];
|
|
49
|
+
};
|
|
50
|
+
type SerializedWorkflow = {
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
steps: WithMeta<l.Step[]>;
|
|
54
|
+
openfn?: l.ProjectMeta;
|
|
55
|
+
};
|
|
56
|
+
|
|
45
57
|
type MergeProjectOptions = {
|
|
46
58
|
workflowMappings: Record<string, string>;
|
|
47
59
|
removeUnmapped: boolean;
|
|
@@ -54,7 +66,8 @@ declare class Workspace {
|
|
|
54
66
|
private projects;
|
|
55
67
|
private projectPaths;
|
|
56
68
|
private isValid;
|
|
57
|
-
|
|
69
|
+
private logger;
|
|
70
|
+
constructor(workspacePath: string, logger?: Logger);
|
|
58
71
|
loadProject(): void;
|
|
59
72
|
list(): Project[];
|
|
60
73
|
/** Get a project by its id or UUID */
|
|
@@ -89,6 +102,7 @@ declare class Project {
|
|
|
89
102
|
config: l__default.WorkspaceConfig;
|
|
90
103
|
collections: any;
|
|
91
104
|
credentials: string[];
|
|
105
|
+
static from(type: 'project', data: any, options: never): Promise<Project>;
|
|
92
106
|
static from(type: 'state', data: Provisioner.Project, meta?: Partial<l__default.ProjectMeta>, config?: fromAppStateConfig): Promise<Project>;
|
|
93
107
|
static from(type: 'fs', options: FromFsConfig): Promise<Project>;
|
|
94
108
|
static from(type: 'path', data: string, options?: {
|
|
@@ -97,7 +111,9 @@ declare class Project {
|
|
|
97
111
|
static merge(source: Project, target: Project, options?: Partial<MergeProjectOptions>): Project;
|
|
98
112
|
constructor(data: Partial<l__default.Project>, config?: Partial<l__default.WorkspaceConfig>);
|
|
99
113
|
setConfig(config: Partial<WorkspaceConfig>): void;
|
|
100
|
-
serialize(type
|
|
114
|
+
serialize(type: 'project', options?: any): SerializedProject | string;
|
|
115
|
+
serialize(type: 'state', options?: any): Provisioner.Project | string;
|
|
116
|
+
serialize(type: 'fs', options?: any): Record<string, string>;
|
|
101
117
|
getWorkflow(idOrName: string): Workflow | undefined;
|
|
102
118
|
getIdentifier(): string;
|
|
103
119
|
getUUID(workflow: string | Workflow, stepId: string, otherStep?: string): any;
|
|
@@ -105,6 +121,7 @@ declare class Project {
|
|
|
105
121
|
* Returns a map of ids:uuids for everything in the project
|
|
106
122
|
*/
|
|
107
123
|
getUUIDMap(): UUIDMap;
|
|
124
|
+
canMergeInto(target: Project): boolean;
|
|
108
125
|
}
|
|
109
126
|
|
|
110
127
|
declare function yamlToJson(y: string): any;
|
package/dist/index.js
CHANGED
|
@@ -105,7 +105,7 @@ var Workflow = class {
|
|
|
105
105
|
};
|
|
106
106
|
this.workflow = clone(workflow);
|
|
107
107
|
this.workflow.history = workflow.history?.length ? workflow.history : [];
|
|
108
|
-
const { id, name, openfn, steps, ...options } = workflow;
|
|
108
|
+
const { id, name, openfn, steps, history, ...options } = workflow;
|
|
109
109
|
if (!(id || name)) {
|
|
110
110
|
throw new Error("A Workflow MUST have a name or id");
|
|
111
111
|
}
|
|
@@ -151,7 +151,7 @@ var Workflow = class {
|
|
|
151
151
|
Object.assign(item, props);
|
|
152
152
|
return this;
|
|
153
153
|
}
|
|
154
|
-
// Get properties on any step or edge by id
|
|
154
|
+
// Get properties on any step or edge by id or uuid
|
|
155
155
|
get(id) {
|
|
156
156
|
const item = this.index.edges[id] || this.index.steps[id];
|
|
157
157
|
if (!item) {
|
|
@@ -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";
|
|
@@ -291,7 +273,14 @@ var defaultJobProps = {
|
|
|
291
273
|
project_credential_id: null
|
|
292
274
|
};
|
|
293
275
|
function to_app_state_default(project, options = {}) {
|
|
294
|
-
const {
|
|
276
|
+
const {
|
|
277
|
+
uuid,
|
|
278
|
+
endpoint,
|
|
279
|
+
env,
|
|
280
|
+
id,
|
|
281
|
+
fetched_at,
|
|
282
|
+
...rest
|
|
283
|
+
} = project.openfn ?? {};
|
|
295
284
|
const state = omitBy(
|
|
296
285
|
pick(project, ["name", "description", "collections"]),
|
|
297
286
|
isNil
|
|
@@ -382,6 +371,7 @@ var mapWorkflow = (workflow) => {
|
|
|
382
371
|
|
|
383
372
|
// src/serialize/to-fs.ts
|
|
384
373
|
import nodepath from "path";
|
|
374
|
+
import { omit } from "lodash-es";
|
|
385
375
|
|
|
386
376
|
// src/util/config.ts
|
|
387
377
|
import { readFileSync } from "node:fs";
|
|
@@ -508,10 +498,16 @@ var extractWorkflow = (project, workflowId) => {
|
|
|
508
498
|
// Not crazy about this - maybe we should do something better? Or do we like the consistency?
|
|
509
499
|
options: workflow.options,
|
|
510
500
|
steps: workflow.steps.map((step) => {
|
|
511
|
-
const { openfn, expression, ...mapped } = step;
|
|
501
|
+
const { openfn, expression, next, ...mapped } = step;
|
|
512
502
|
if (expression) {
|
|
513
503
|
mapped.expression = `./${step.id}.js`;
|
|
514
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
|
+
}
|
|
515
511
|
return mapped;
|
|
516
512
|
})
|
|
517
513
|
};
|
|
@@ -546,18 +542,71 @@ var handleOutput = (data, filePath, format) => {
|
|
|
546
542
|
return { path: path5, content };
|
|
547
543
|
};
|
|
548
544
|
|
|
549
|
-
// src/
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
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: omitBy2(project.openfn, isNil3),
|
|
559
|
+
meta: project.meta,
|
|
560
|
+
options: omitBy2(project.options, isNil3),
|
|
561
|
+
workflows: project.workflows.map((w) => {
|
|
562
|
+
const obj = w.toJSON();
|
|
563
|
+
if (obj.openfn) {
|
|
564
|
+
obj.openfn = omitBy2(obj.openfn, isNil3);
|
|
565
|
+
}
|
|
566
|
+
if (obj.steps) {
|
|
567
|
+
obj.steps = obj.steps.sort((a, b) => {
|
|
568
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
569
|
+
});
|
|
570
|
+
obj.steps.forEach((s) => {
|
|
571
|
+
s.openfn = omitBy2(s.openfn, isNil3);
|
|
572
|
+
if (s.next && typeof s.next !== "string") {
|
|
573
|
+
for (const id in s.next) {
|
|
574
|
+
const edge = s.next[id];
|
|
575
|
+
if (edge.openfn) {
|
|
576
|
+
edge.openfn = omitBy2(edge.openfn, isNil3);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
return obj;
|
|
583
|
+
})
|
|
584
|
+
},
|
|
585
|
+
isNil3
|
|
586
|
+
);
|
|
587
|
+
const format = options.format ?? proj.config?.formats.project;
|
|
588
|
+
if (format === "json") {
|
|
589
|
+
return proj;
|
|
590
|
+
}
|
|
591
|
+
return jsonToYaml(proj);
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
// src/util/ensure-json.ts
|
|
595
|
+
var ensure_json_default = (obj) => {
|
|
596
|
+
if (typeof obj === "string") {
|
|
597
|
+
const firstChar = obj.trim()[0];
|
|
598
|
+
if (firstChar === "{" || firstChar === "[") {
|
|
599
|
+
return JSON.parse(obj);
|
|
555
600
|
} else {
|
|
556
|
-
|
|
601
|
+
return yamlToJson(obj);
|
|
557
602
|
}
|
|
558
|
-
} else {
|
|
559
|
-
stateJson = state;
|
|
560
603
|
}
|
|
604
|
+
return obj;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
// src/parse/from-app-state.ts
|
|
608
|
+
var from_app_state_default = (state, meta = {}, config = {}) => {
|
|
609
|
+
let stateJson = ensure_json_default(state);
|
|
561
610
|
delete config.format;
|
|
562
611
|
const {
|
|
563
612
|
id,
|
|
@@ -606,10 +655,11 @@ var mapTriggerEdgeCondition = (edge) => {
|
|
|
606
655
|
return e;
|
|
607
656
|
};
|
|
608
657
|
var mapWorkflow2 = (workflow) => {
|
|
609
|
-
const { jobs, edges, triggers, name, ...remoteProps } = workflow;
|
|
658
|
+
const { jobs, edges, triggers, name, version_history, ...remoteProps } = workflow;
|
|
610
659
|
const mapped = {
|
|
611
660
|
name: workflow.name,
|
|
612
661
|
steps: [],
|
|
662
|
+
history: workflow.version_history ?? [],
|
|
613
663
|
openfn: renameKeys(remoteProps, { id: "uuid" })
|
|
614
664
|
};
|
|
615
665
|
if (workflow.name) {
|
|
@@ -660,24 +710,32 @@ var mapWorkflow2 = (workflow) => {
|
|
|
660
710
|
};
|
|
661
711
|
|
|
662
712
|
// src/parse/from-path.ts
|
|
663
|
-
import { extname } from "node:path";
|
|
664
713
|
import { readFile } from "node:fs/promises";
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
let
|
|
670
|
-
if (
|
|
671
|
-
|
|
672
|
-
state = JSON.parse(source);
|
|
673
|
-
} else if (ext.match(/(ya?ml)$/)) {
|
|
674
|
-
config.format = "yaml";
|
|
675
|
-
state = yamlToJson(source);
|
|
714
|
+
|
|
715
|
+
// src/parse/from-project.ts
|
|
716
|
+
var from_project_default = (data, config) => {
|
|
717
|
+
let rawJson = ensure_json_default(data);
|
|
718
|
+
let json;
|
|
719
|
+
if (rawJson.version) {
|
|
720
|
+
json = from_v2(rawJson);
|
|
676
721
|
} else {
|
|
677
|
-
|
|
722
|
+
json = from_v1(rawJson);
|
|
678
723
|
}
|
|
679
|
-
|
|
680
|
-
|
|
724
|
+
return new Project_default(json, config);
|
|
725
|
+
};
|
|
726
|
+
var from_v1 = (data) => {
|
|
727
|
+
return from_app_state_default(data);
|
|
728
|
+
};
|
|
729
|
+
var from_v2 = (data) => {
|
|
730
|
+
return {
|
|
731
|
+
...data
|
|
732
|
+
};
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
// src/parse/from-path.ts
|
|
736
|
+
var from_path_default = async (path5, config = {}) => {
|
|
737
|
+
const source = await readFile(path5, "utf8");
|
|
738
|
+
return from_project_default(source, config);
|
|
681
739
|
};
|
|
682
740
|
|
|
683
741
|
// src/parse/from-fs.ts
|
|
@@ -699,6 +757,7 @@ var get_identifier_default = (config = {}) => {
|
|
|
699
757
|
};
|
|
700
758
|
|
|
701
759
|
// src/parse/from-fs.ts
|
|
760
|
+
import { omit as omit2 } from "lodash-es";
|
|
702
761
|
var parseProject = async (options) => {
|
|
703
762
|
const { root } = options;
|
|
704
763
|
const { type, content } = findWorkspaceFile(root);
|
|
@@ -717,13 +776,13 @@ var parseProject = async (options) => {
|
|
|
717
776
|
`${identifier}.${format}`
|
|
718
777
|
);
|
|
719
778
|
const stateFile = await fs.readFile(statePath, "utf8");
|
|
720
|
-
state =
|
|
779
|
+
state = from_project_default(stateFile, config);
|
|
721
780
|
} catch (e) {
|
|
722
781
|
console.warn(`Failed to find state file for ${identifier}`);
|
|
723
782
|
}
|
|
724
783
|
const proj = {
|
|
725
784
|
name: state?.name,
|
|
726
|
-
openfn: context.project,
|
|
785
|
+
openfn: omit2(context.project, ["id"]),
|
|
727
786
|
config,
|
|
728
787
|
workflows: []
|
|
729
788
|
};
|
|
@@ -738,12 +797,12 @@ var parseProject = async (options) => {
|
|
|
738
797
|
try {
|
|
739
798
|
const wf = fileType === "yaml" ? yamlToJson(candidate) : JSON.parse(candidate);
|
|
740
799
|
if (wf.id && Array.isArray(wf.steps)) {
|
|
741
|
-
const wfState =
|
|
742
|
-
wf.openfn = {
|
|
743
|
-
uuid: wfState
|
|
744
|
-
|
|
745
|
-
};
|
|
800
|
+
const wfState = state?.getWorkflow(wf.id);
|
|
801
|
+
wf.openfn = Object.assign({}, wfState?.openfn, {
|
|
802
|
+
uuid: wfState?.openfn?.uuid ?? null
|
|
803
|
+
});
|
|
746
804
|
for (const step of wf.steps) {
|
|
805
|
+
const stateStep = wfState?.get(step.id);
|
|
747
806
|
if (step.expression && step.expression.endsWith(".js")) {
|
|
748
807
|
const dir = path2.dirname(filePath);
|
|
749
808
|
const exprPath = path2.join(dir, step.expression);
|
|
@@ -754,15 +813,14 @@ var parseProject = async (options) => {
|
|
|
754
813
|
console.error(`Error loading expression from ${exprPath}`);
|
|
755
814
|
}
|
|
756
815
|
}
|
|
757
|
-
|
|
758
|
-
step.openfn = { uuid };
|
|
816
|
+
step.openfn = Object.assign({}, stateStep?.openfn);
|
|
759
817
|
for (const target in step.next || {}) {
|
|
760
818
|
if (typeof step.next[target] === "boolean") {
|
|
761
819
|
const bool = step.next[target];
|
|
762
820
|
step.next[target] = { condition: bool };
|
|
763
821
|
}
|
|
764
|
-
const
|
|
765
|
-
step.next[target].openfn = { uuid
|
|
822
|
+
const uuid = state?.getUUID(wf.id, step.id, target) ?? null;
|
|
823
|
+
step.next[target].openfn = { uuid };
|
|
766
824
|
}
|
|
767
825
|
}
|
|
768
826
|
proj.workflows.push(wf);
|
|
@@ -1210,6 +1268,7 @@ var Project = class {
|
|
|
1210
1268
|
options;
|
|
1211
1269
|
// local metadata used by the CLI
|
|
1212
1270
|
// This stuff is not synced back to lightning
|
|
1271
|
+
// TODO maybe rename cli or local
|
|
1213
1272
|
meta;
|
|
1214
1273
|
// this contains meta about the connected openfn project
|
|
1215
1274
|
openfn;
|
|
@@ -1218,17 +1277,23 @@ var Project = class {
|
|
|
1218
1277
|
collections;
|
|
1219
1278
|
credentials;
|
|
1220
1279
|
static async from(type, data, ...rest) {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1280
|
+
switch (type) {
|
|
1281
|
+
case "project":
|
|
1282
|
+
var [config] = rest;
|
|
1283
|
+
return from_project_default(data, config);
|
|
1284
|
+
case "state":
|
|
1285
|
+
return from_app_state_default(data, rest[0], rest[1]);
|
|
1286
|
+
case "fs":
|
|
1287
|
+
return parseProject(data);
|
|
1288
|
+
case "path":
|
|
1289
|
+
var [config] = rest;
|
|
1290
|
+
return from_path_default(data, config);
|
|
1291
|
+
default:
|
|
1292
|
+
throw new Error(`Didn't recognize type ${type}`);
|
|
1227
1293
|
}
|
|
1228
|
-
throw new Error(`Didn't recognize type ${type}`);
|
|
1229
1294
|
}
|
|
1230
1295
|
// Diff two projects
|
|
1231
|
-
//
|
|
1296
|
+
// static diff(a: Project, b: Project) {}
|
|
1232
1297
|
// Merge a source project (staging) into the target project (main)
|
|
1233
1298
|
// Returns a new Project
|
|
1234
1299
|
// TODO: throw if histories have diverged
|
|
@@ -1254,7 +1319,7 @@ var Project = class {
|
|
|
1254
1319
|
setConfig(config) {
|
|
1255
1320
|
this.config = buildConfig(config);
|
|
1256
1321
|
}
|
|
1257
|
-
serialize(type = "
|
|
1322
|
+
serialize(type = "project", options) {
|
|
1258
1323
|
if (type in serialize_exports) {
|
|
1259
1324
|
return serialize_exports[type](this, options);
|
|
1260
1325
|
}
|
|
@@ -1293,10 +1358,25 @@ var Project = class {
|
|
|
1293
1358
|
}
|
|
1294
1359
|
return result;
|
|
1295
1360
|
}
|
|
1361
|
+
canMergeInto(target) {
|
|
1362
|
+
const potentialConflicts = {};
|
|
1363
|
+
for (const sourceWorkflow of this.workflows) {
|
|
1364
|
+
const targetId = sourceWorkflow.id;
|
|
1365
|
+
const targetWorkflow = target.getWorkflow(targetId);
|
|
1366
|
+
if (targetWorkflow && !sourceWorkflow.canMergeInto(targetWorkflow)) {
|
|
1367
|
+
potentialConflicts[sourceWorkflow.id] = targetWorkflow?.id;
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
if (Object.keys(potentialConflicts).length) {
|
|
1371
|
+
return false;
|
|
1372
|
+
}
|
|
1373
|
+
return true;
|
|
1374
|
+
}
|
|
1296
1375
|
};
|
|
1297
1376
|
var Project_default = Project;
|
|
1298
1377
|
|
|
1299
1378
|
// src/Workspace.ts
|
|
1379
|
+
import createLogger from "@openfn/logger";
|
|
1300
1380
|
import path3 from "node:path";
|
|
1301
1381
|
import fs3 from "node:fs";
|
|
1302
1382
|
|
|
@@ -1317,26 +1397,29 @@ function pathExists(fpath, type) {
|
|
|
1317
1397
|
|
|
1318
1398
|
// src/Workspace.ts
|
|
1319
1399
|
var Workspace = class {
|
|
1320
|
-
// @ts-ignore config not
|
|
1400
|
+
// @ts-ignore config not definitely assigned - it sure is
|
|
1321
1401
|
config;
|
|
1322
1402
|
activeProject;
|
|
1323
1403
|
projects = [];
|
|
1324
1404
|
projectPaths = /* @__PURE__ */ new Map();
|
|
1325
1405
|
isValid = false;
|
|
1326
|
-
|
|
1327
|
-
|
|
1406
|
+
logger;
|
|
1407
|
+
constructor(workspacePath, logger) {
|
|
1408
|
+
this.logger = logger ?? createLogger("Workspace", { level: "info" });
|
|
1409
|
+
let context = { workspace: void 0, project: void 0 };
|
|
1328
1410
|
try {
|
|
1329
1411
|
const { type, content } = findWorkspaceFile(workspacePath);
|
|
1330
1412
|
context = loadWorkspaceFile(content, type);
|
|
1331
1413
|
this.isValid = true;
|
|
1332
1414
|
} catch (e) {
|
|
1333
|
-
|
|
1334
|
-
|
|
1415
|
+
this.logger.warn(
|
|
1416
|
+
`Could not find openfn.yaml at ${workspacePath}. Using default values.`
|
|
1417
|
+
);
|
|
1335
1418
|
}
|
|
1336
1419
|
this.config = buildConfig(context.workspace);
|
|
1337
1420
|
this.activeProject = context.project;
|
|
1338
1421
|
const projectsPath = path3.join(workspacePath, this.config.dirs.projects);
|
|
1339
|
-
if (
|
|
1422
|
+
if (pathExists(projectsPath, "directory")) {
|
|
1340
1423
|
const ext = `.${this.config.formats.project}`;
|
|
1341
1424
|
const stateFiles = fs3.readdirSync(projectsPath).filter(
|
|
1342
1425
|
(fileName) => path3.extname(fileName) === ext && path3.parse(fileName).name !== "openfn"
|
|
@@ -1345,14 +1428,9 @@ var Workspace = class {
|
|
|
1345
1428
|
const stateFilePath = path3.join(projectsPath, file);
|
|
1346
1429
|
try {
|
|
1347
1430
|
const data = fs3.readFileSync(stateFilePath, "utf-8");
|
|
1348
|
-
const project =
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
{
|
|
1352
|
-
...this.config,
|
|
1353
|
-
format: this.config?.formats.project
|
|
1354
|
-
}
|
|
1355
|
-
);
|
|
1431
|
+
const project = from_project_default(data, {
|
|
1432
|
+
...this.config
|
|
1433
|
+
});
|
|
1356
1434
|
this.projectPaths.set(project.id, stateFilePath);
|
|
1357
1435
|
return project;
|
|
1358
1436
|
} catch (e) {
|
|
@@ -1360,6 +1438,10 @@ var Workspace = class {
|
|
|
1360
1438
|
console.warn(e);
|
|
1361
1439
|
}
|
|
1362
1440
|
}).filter((s) => s);
|
|
1441
|
+
} else {
|
|
1442
|
+
this.logger.warn(
|
|
1443
|
+
`No projects found: directory at ${projectsPath} does not exist`
|
|
1444
|
+
);
|
|
1363
1445
|
}
|
|
1364
1446
|
}
|
|
1365
1447
|
// TODO
|
|
@@ -1400,7 +1482,7 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
1400
1482
|
import path4 from "node:path";
|
|
1401
1483
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
1402
1484
|
import { grammar } from "ohm-js";
|
|
1403
|
-
import { isNil as
|
|
1485
|
+
import { isNil as isNil4, set } from "lodash-es";
|
|
1404
1486
|
var parser;
|
|
1405
1487
|
var expectedNodeProps = [
|
|
1406
1488
|
// TODO need to clarify adaptor/adaptors confusion
|
|
@@ -1571,7 +1653,7 @@ function generateWorkflow(def, options = {}) {
|
|
|
1571
1653
|
if (options.uuidMap && raw.id in options.uuidMap) {
|
|
1572
1654
|
uuid = options.uuidMap[raw.id];
|
|
1573
1655
|
}
|
|
1574
|
-
if (!
|
|
1656
|
+
if (!isNil4(uuid) && options.openfnUuid) {
|
|
1575
1657
|
raw.openfn ??= {};
|
|
1576
1658
|
raw.openfn.uuid = uuid;
|
|
1577
1659
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/project",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
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.
|
|
38
|
-
"@openfn/logger": "1.0
|
|
37
|
+
"@openfn/lexicon": "^1.3.0",
|
|
38
|
+
"@openfn/logger": "1.1.0"
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
41
|
"dist",
|