@openfn/project 0.2.0 → 0.3.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 CHANGED
@@ -18,9 +18,8 @@ declare class Workflow {
18
18
  name: string;
19
19
  id: string;
20
20
  openfn: OpenfnMeta;
21
- steps: WithMeta<l.Job | l.Trigger>[];
22
21
  constructor(workflow: l.Workflow);
23
- get steps(): (l.Job | l.Trigger)[];
22
+ get steps(): WithMeta<l.Job | l.Trigger>[];
24
23
  set(id: string, props: Parital<l.Job, l.Edge>): this;
25
24
  get(id: any): WithMeta<l.Step | l.Trigger | l.Edge>;
26
25
  meta(id: any): OpenfnMeta;
@@ -34,6 +33,10 @@ declare class Workflow {
34
33
  toJSON(): JSON.Object;
35
34
  }
36
35
 
36
+ type FromFsConfig = {
37
+ root: string;
38
+ };
39
+
37
40
  type MergeProjectOptions = Partial<{
38
41
  workflowMappings: Record<string, string>;
39
42
  removeUnmapped: boolean;
@@ -41,6 +44,22 @@ type MergeProjectOptions = Partial<{
41
44
  }>;
42
45
 
43
46
  type FileFormats = 'yaml' | 'json';
47
+ interface OpenfnConfig {
48
+ name: string;
49
+ workflowRoot: string;
50
+ formats: {
51
+ openfn: FileFormats;
52
+ project: FileFormats;
53
+ workflow: FileFormats;
54
+ };
55
+ project: {
56
+ projectId: string;
57
+ endpoint: string;
58
+ env: string;
59
+ inserted_at: string;
60
+ updated_at: string;
61
+ };
62
+ }
44
63
  type RepoOptions = {
45
64
  /**default workflow root when serializing to fs (relative to openfn.yaml) */
46
65
  workflowRoot?: string;
@@ -62,9 +81,7 @@ declare class Project {
62
81
  repo?: Required<RepoOptions>;
63
82
  collections: any;
64
83
  static from(type: 'state', data: any, options: Partial<l.ProjectConfig>): Project;
65
- static from(type: 'fs', options: {
66
- root: string;
67
- }): Project;
84
+ static from(type: 'fs', options: FromFsConfig): Project;
68
85
  static from(type: 'path', data: any): Project;
69
86
  static diff(a: Project, b: Project): void;
70
87
  static merge(source: Project, target: Project, options: MergeProjectOptions): Project;
@@ -77,7 +94,20 @@ declare class Project {
77
94
  getUUID(workflow: string | Workflow, stepId: string, otherStep?: string): any;
78
95
  }
79
96
 
97
+ declare class Workspace {
98
+ private config?;
99
+ private projects;
100
+ private isValid;
101
+ constructor(workspacePath: string);
102
+ list(): Project[];
103
+ get(id: string): Project | undefined;
104
+ getActiveProject(): Project | undefined;
105
+ getConfig(): OpenfnConfig | undefined;
106
+ get activeProjectId(): string | undefined;
107
+ get valid(): boolean;
108
+ }
109
+
80
110
  declare function yamlToJson(y: string): any;
81
111
  declare function jsonToYaml(json: string | JSONObject): string;
82
112
 
83
- export { Project as default, jsonToYaml, yamlToJson };
113
+ export { Workspace, Project as default, jsonToYaml, yamlToJson };
package/dist/index.js CHANGED
@@ -13,7 +13,6 @@ var Workflow = class {
13
13
  name;
14
14
  id;
15
15
  openfn;
16
- steps;
17
16
  constructor(workflow) {
18
17
  this.index = {
19
18
  steps: {},
@@ -263,16 +262,16 @@ import nodepath from "path";
263
262
  var stringify = (json) => JSON.stringify(json, null, 2);
264
263
  function to_fs_default(project) {
265
264
  const files = {};
266
- const { path: path2, content } = extractRepoConfig(project);
267
- files[path2] = content;
265
+ const { path: path3, content } = extractRepoConfig(project);
266
+ files[path3] = content;
268
267
  for (const wf of project.workflows) {
269
- const { path: path3, content: content2 } = extractWorkflow(project, wf.id);
270
- files[path3] = content2;
268
+ const { path: path4, content: content2 } = extractWorkflow(project, wf.id);
269
+ files[path4] = content2;
271
270
  for (const s of wf.steps) {
272
271
  const result = extractStep(project, wf.id, s.id);
273
272
  if (result) {
274
- const { path: path4, content: content3 } = result;
275
- files[path4] = content3;
273
+ const { path: path5, content: content3 } = result;
274
+ files[path5] = content3;
276
275
  }
277
276
  }
278
277
  }
@@ -285,7 +284,7 @@ var extractWorkflow = (project, workflowId2) => {
285
284
  throw new Error(`workflow not found: ${workflowId2}`);
286
285
  }
287
286
  const root = project.repo?.workflowRoot ?? "workflows/";
288
- const path2 = nodepath.join(root, workflow.id, workflow.id);
287
+ const path3 = nodepath.join(root, workflow.id, workflow.id);
289
288
  const wf = {
290
289
  id: workflow.id,
291
290
  name: workflow.name,
@@ -300,7 +299,7 @@ var extractWorkflow = (project, workflowId2) => {
300
299
  return mapped;
301
300
  })
302
301
  };
303
- return handleOutput(wf, path2, format);
302
+ return handleOutput(wf, path3, format);
304
303
  };
305
304
  var extractStep = (project, workflowId2, stepId) => {
306
305
  const workflow = project.getWorkflow(workflowId2);
@@ -313,9 +312,9 @@ var extractStep = (project, workflowId2, stepId) => {
313
312
  }
314
313
  if (step.expression) {
315
314
  const root = project.config?.workflowRoot ?? "workflows/";
316
- const path2 = nodepath.join(root, `${workflow.id}/${step.id}.js`);
315
+ const path3 = nodepath.join(root, `${workflow.id}/${step.id}.js`);
317
316
  const content = step.expression;
318
- return { path: path2, content };
317
+ return { path: path3, content };
319
318
  }
320
319
  };
321
320
  var extractRepoConfig = (project) => {
@@ -328,7 +327,7 @@ var extractRepoConfig = (project) => {
328
327
  return handleOutput(config, "openfn", format);
329
328
  };
330
329
  var handleOutput = (data, filePath, format) => {
331
- const path2 = `${filePath}.${format}`;
330
+ const path3 = `${filePath}.${format}`;
332
331
  let content;
333
332
  if (format === "json") {
334
333
  content = stringify(data, null, 2);
@@ -337,7 +336,7 @@ var handleOutput = (data, filePath, format) => {
337
336
  } else {
338
337
  throw new Error(`Unrecognised format: ${format}`);
339
338
  }
340
- return { path: path2, content };
339
+ return { path: path3, content };
341
340
  };
342
341
 
343
342
  // src/parse/from-app-state.ts
@@ -984,8 +983,7 @@ var Project = class {
984
983
  static from(type, data, options) {
985
984
  if (type === "state") {
986
985
  return from_app_state_default(data, options);
987
- }
988
- if (type === "fs") {
986
+ } else if (type === "fs") {
989
987
  return parseProject(data, options);
990
988
  }
991
989
  throw new Error(`Didn't recognize type ${type}`);
@@ -1050,9 +1048,73 @@ var Project = class {
1050
1048
  }
1051
1049
  };
1052
1050
 
1051
+ // src/util/path-exists.ts
1052
+ import fs2 from "fs";
1053
+ function pathExists(fpath, type) {
1054
+ try {
1055
+ const stat = fs2.statSync(fpath);
1056
+ if (type === "file" && stat.isFile())
1057
+ return true;
1058
+ else if (type === "directory" && stat.isDirectory())
1059
+ return true;
1060
+ return false;
1061
+ } catch (e) {
1062
+ return false;
1063
+ }
1064
+ }
1065
+
1066
+ // src/Workspace.ts
1067
+ import path2 from "path";
1068
+ import fs3 from "fs";
1069
+ var PROJECTS_DIRECTORY = ".projects";
1070
+ var OPENFN_YAML_FILE = "openfn.yaml";
1071
+ var PROJECT_EXTENSIONS = [".yaml", ".yml"];
1072
+ var Workspace = class {
1073
+ config;
1074
+ projects = [];
1075
+ isValid = false;
1076
+ constructor(workspacePath) {
1077
+ const projectsPath = path2.join(workspacePath, PROJECTS_DIRECTORY);
1078
+ const openfnYamlPath = path2.join(workspacePath, OPENFN_YAML_FILE);
1079
+ if (pathExists(openfnYamlPath, "file")) {
1080
+ this.isValid = true;
1081
+ const data = fs3.readFileSync(openfnYamlPath, "utf-8");
1082
+ this.config = yamlToJson(data);
1083
+ }
1084
+ if (this.isValid && pathExists(projectsPath, "directory")) {
1085
+ const stateFiles = fs3.readdirSync(projectsPath).filter(
1086
+ (fileName) => PROJECT_EXTENSIONS.includes(path2.extname(fileName))
1087
+ );
1088
+ this.projects = stateFiles.map((file) => {
1089
+ const data = fs3.readFileSync(path2.join(projectsPath, file), "utf-8");
1090
+ return from_app_state_default(data, { format: "yaml" });
1091
+ });
1092
+ }
1093
+ }
1094
+ list() {
1095
+ return this.projects;
1096
+ }
1097
+ get(id) {
1098
+ return this.projects.find((p) => p.name === id);
1099
+ }
1100
+ getActiveProject() {
1101
+ return this.projects.find((p) => p.name === this.config?.name);
1102
+ }
1103
+ getConfig() {
1104
+ return this.config;
1105
+ }
1106
+ get activeProjectId() {
1107
+ return this.config?.name;
1108
+ }
1109
+ get valid() {
1110
+ return this.isValid;
1111
+ }
1112
+ };
1113
+
1053
1114
  // src/index.ts
1054
1115
  var src_default = Project;
1055
1116
  export {
1117
+ Workspace,
1056
1118
  src_default as default,
1057
1119
  jsonToYaml,
1058
1120
  yamlToJson
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfn/project",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Read, serialize, replicate and sync OpenFn projects",
5
5
  "type": "module",
6
6
  "exports": {