@fnndsc/salsa 3.9.0 → 3.10.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.
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /**
3
+ * @file `/proc/workflows` — instantiated pipelines, beside the jobs they own.
4
+ *
5
+ * A CUBE workflow is a pipeline that was run: it names the pipeline and owns
6
+ * the plugin instances the run created. That is runtime state, which is why it
7
+ * lives under `/proc` alongside `/proc/jobs` rather than under `/bin` with the
8
+ * pipeline definitions.
9
+ *
10
+ * A workflow is a relation, so it projects as a directory of links — the
11
+ * `pipeline` entry points into `/bin`, and each entry under `jobs/` points into
12
+ * `/proc/jobs`. Nothing here duplicates a job's own representation; following a
13
+ * link arrives at the one `/proc/jobs` already provides.
14
+ *
15
+ * Links are lazy: a listing states that a link exists without paying to resolve
16
+ * it, and `linkTarget_resolve` is called only when something actually follows
17
+ * one.
18
+ *
19
+ * @module
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.WorkflowsVfsProvider = void 0;
23
+ const cumin_1 = require("@fnndsc/cumin");
24
+ const index_js_1 = require("../../workflows/index.js");
25
+ /** The prefix this provider answers for. */
26
+ const PREFIX = '/proc/workflows';
27
+ /** Entries every workflow directory carries. */
28
+ const WORKFLOW_ENTRIES = ['pipeline', 'jobs', 'title'];
29
+ /**
30
+ * Reads a field from a workflow row, tolerating the shapes CUBE reports.
31
+ *
32
+ * @param row - One workflow row.
33
+ * @param field - The field to read.
34
+ * @returns The value as a string, or an empty string when absent.
35
+ */
36
+ function field_text(row, field) {
37
+ const value = row[field];
38
+ return value === undefined || value === null ? '' : String(value);
39
+ }
40
+ /**
41
+ * Splits a path below this provider's prefix into its segments.
42
+ *
43
+ * @param path - An absolute path under `/proc/workflows`.
44
+ * @returns The segments after the prefix, empty at the root.
45
+ */
46
+ function segments_below(path) {
47
+ return path.slice(PREFIX.length).split('/').filter(Boolean);
48
+ }
49
+ /**
50
+ * Projects CUBE workflows as `/proc/workflows`.
51
+ */
52
+ class WorkflowsVfsProvider {
53
+ /** @inheritdoc */
54
+ prefix = PREFIX;
55
+ /** @inheritdoc */
56
+ async list(path) {
57
+ const parts = segments_below(path);
58
+ if (parts.length === 0) {
59
+ return this.workflows_list();
60
+ }
61
+ if (parts.length === 1) {
62
+ return (0, cumin_1.Ok)(WORKFLOW_ENTRIES.map((name) => ({
63
+ name,
64
+ type: name === 'jobs' ? 'dir' : (name === 'pipeline' ? 'link' : 'file'),
65
+ size: 0,
66
+ owner: '',
67
+ date: '',
68
+ })));
69
+ }
70
+ if (parts.length === 2 && parts[1] === 'jobs') {
71
+ return this.jobs_list(Number(parts[0]));
72
+ }
73
+ cumin_1.errorStack.stack_push('error', `${path} is not a workflow path.`);
74
+ return (0, cumin_1.Err)();
75
+ }
76
+ /** @inheritdoc */
77
+ async cp(_src, _dest, _options) {
78
+ // A workflow is a record of a run. Copying one would assert that a
79
+ // computation happened twice.
80
+ cumin_1.errorStack.stack_push('error', 'A workflow records a run; it cannot be copied.');
81
+ return false;
82
+ }
83
+ /** @inheritdoc */
84
+ async read(path) {
85
+ const parts = segments_below(path);
86
+ if (parts.length !== 2 || parts[1] !== 'title') {
87
+ cumin_1.errorStack.stack_push('error', `${path} is not a readable workflow file.`);
88
+ return (0, cumin_1.Err)();
89
+ }
90
+ const rows = await this.rows_get();
91
+ const row = rows.find((entry) => field_text(entry, 'id') === parts[0]);
92
+ if (!row) {
93
+ cumin_1.errorStack.stack_push('error', `No workflow ${parts[0]}.`);
94
+ return (0, cumin_1.Err)();
95
+ }
96
+ return (0, cumin_1.Ok)(`${field_text(row, 'title')}\n`);
97
+ }
98
+ /**
99
+ * Resolves a workflow's `pipeline` link to its definition under `/bin`.
100
+ *
101
+ * @param path - The link's absolute path.
102
+ * @returns The target path, or an error when the workflow is unknown.
103
+ */
104
+ async linkTarget_resolve(path) {
105
+ const parts = segments_below(path);
106
+ if (parts.length !== 2 || parts[1] !== 'pipeline') {
107
+ cumin_1.errorStack.stack_push('error', `${path} is not a workflow link.`);
108
+ return (0, cumin_1.Err)();
109
+ }
110
+ const rows = await this.rows_get();
111
+ const row = rows.find((entry) => field_text(entry, 'id') === parts[0]);
112
+ if (!row) {
113
+ cumin_1.errorStack.stack_push('error', `No workflow ${parts[0]}.`);
114
+ return (0, cumin_1.Err)();
115
+ }
116
+ return (0, cumin_1.Ok)(`/bin/${field_text(row, 'pipeline_name')}`);
117
+ }
118
+ /**
119
+ * Fetches every workflow visible to this session.
120
+ *
121
+ * @returns The workflow rows, empty when the fetch failed.
122
+ */
123
+ async rows_get() {
124
+ const data = await (0, index_js_1.workflows_listAll)();
125
+ return data?.tableData ?? [];
126
+ }
127
+ /**
128
+ * Lists the workflows themselves, one directory each.
129
+ *
130
+ * @returns The listing.
131
+ */
132
+ async workflows_list() {
133
+ const rows = await this.rows_get();
134
+ return (0, cumin_1.Ok)(rows.map((row) => ({
135
+ name: field_text(row, 'id'),
136
+ type: 'dir',
137
+ size: 0,
138
+ owner: field_text(row, 'owner_username'),
139
+ date: field_text(row, 'creation_date'),
140
+ title: field_text(row, 'title'),
141
+ id: Number(field_text(row, 'id')),
142
+ })));
143
+ }
144
+ /**
145
+ * Lists one workflow's plugin instances as links into `/proc/jobs`.
146
+ *
147
+ * @param workflowId - The workflow whose instances to list.
148
+ * @returns The listing.
149
+ */
150
+ async jobs_list(workflowId) {
151
+ const rows = await this.rows_get();
152
+ const row = rows.find((entry) => Number(field_text(entry, 'id')) === workflowId);
153
+ if (!row) {
154
+ cumin_1.errorStack.stack_push('error', `No workflow ${workflowId}.`);
155
+ return (0, cumin_1.Err)();
156
+ }
157
+ const ids = Array.isArray(row['plugin_instances'])
158
+ ? row['plugin_instances'].map(Number).filter((id) => !Number.isNaN(id))
159
+ : [];
160
+ return (0, cumin_1.Ok)(ids.map((id) => ({
161
+ name: String(id),
162
+ type: 'link',
163
+ size: 0,
164
+ owner: field_text(row, 'owner_username'),
165
+ date: '',
166
+ target: `/proc/jobs/${id}`,
167
+ id,
168
+ })));
169
+ }
170
+ }
171
+ exports.WorkflowsVfsProvider = WorkflowsVfsProvider;
172
+ //# sourceMappingURL=workflows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../../src/vfs/providers/workflows.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fnndsc/salsa",
3
- "version": "3.9.0",
3
+ "version": "3.10.0",
4
4
  "description": "Shared Application Logic and Service Assets for ChRIS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -59,7 +59,7 @@
59
59
  "inflight": "npm:@aashutoshrathi/word-wrap@^1.2.6"
60
60
  },
61
61
  "dependencies": {
62
- "@fnndsc/cumin": "^3.14.0",
62
+ "@fnndsc/cumin": "^3.15.0",
63
63
  "axios": "^1.6.8",
64
64
  "ws": "^8.21.0"
65
65
  }