@fnndsc/cumin 3.8.1 → 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.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/dist/cache/index.d.ts +5 -1
  3. package/dist/cache/index.js +9 -1
  4. package/dist/cache/index.js.map +1 -1
  5. package/dist/cache/listCache.d.ts +11 -0
  6. package/dist/cache/listCache.js +19 -0
  7. package/dist/cache/listCache.js.map +1 -1
  8. package/dist/cache/procCache.d.ts +118 -5
  9. package/dist/cache/procCache.js +213 -6
  10. package/dist/cache/procCache.js.map +1 -1
  11. package/dist/cache/procCheckpoint.d.ts +47 -0
  12. package/dist/cache/procCheckpoint.js +217 -0
  13. package/dist/cache/procCheckpoint.js.map +1 -0
  14. package/dist/cache/procPrompt.d.ts +34 -0
  15. package/dist/cache/procPrompt.js +25 -0
  16. package/dist/cache/procPrompt.js.map +1 -0
  17. package/dist/chrisapi/adapter.d.ts +23 -1
  18. package/dist/chrisapi/adapter.js +39 -0
  19. package/dist/chrisapi/adapter.js.map +1 -1
  20. package/dist/chrisapi/contract.d.ts +336 -0
  21. package/dist/chrisapi/contract.js +219 -0
  22. package/dist/chrisapi/contract.js.map +1 -0
  23. package/dist/connect/chrisConnection.d.ts +20 -0
  24. package/dist/connect/chrisConnection.js +33 -0
  25. package/dist/connect/chrisConnection.js.map +1 -1
  26. package/dist/feeds/chrisFeed.js +2 -1
  27. package/dist/feeds/chrisFeed.js.map +1 -1
  28. package/dist/groups/chrisGroups.d.ts +67 -1
  29. package/dist/groups/chrisGroups.js +171 -1
  30. package/dist/groups/chrisGroups.js.map +1 -1
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.js +13 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/io/chrisIO.d.ts +14 -0
  35. package/dist/io/chrisIO.js +31 -2
  36. package/dist/io/chrisIO.js.map +1 -1
  37. package/dist/jobs/chrisJob.js +4 -0
  38. package/dist/jobs/chrisJob.js.map +1 -1
  39. package/dist/output/runtimeOutput.d.ts +49 -0
  40. package/dist/output/runtimeOutput.js +51 -0
  41. package/dist/output/runtimeOutput.js.map +1 -0
  42. package/dist/pacs/chrisPACS.d.ts +28 -0
  43. package/dist/pacs/chrisPACS.js +40 -21
  44. package/dist/pacs/chrisPACS.js.map +1 -1
  45. package/dist/path/chrisPath.js +3 -3
  46. package/dist/path/chrisPath.js.map +1 -1
  47. package/dist/pipelines/chrisPipeline.d.ts +4 -0
  48. package/dist/pipelines/chrisPipeline.js +1 -1
  49. package/dist/pipelines/chrisPipeline.js.map +1 -1
  50. package/dist/plugins/chrisPlugins.d.ts +8 -1
  51. package/dist/plugins/chrisPlugins.js +8 -1
  52. package/dist/plugins/chrisPlugins.js.map +1 -1
  53. package/dist/resources/chrisObjContext.d.ts +11 -0
  54. package/dist/resources/chrisObjContext.js +38 -2
  55. package/dist/resources/chrisObjContext.js.map +1 -1
  56. package/dist/resources/chrisResources.js +4 -0
  57. package/dist/resources/chrisResources.js.map +1 -1
  58. package/dist/users/chrisUsers.d.ts +56 -10
  59. package/dist/users/chrisUsers.js +149 -20
  60. package/dist/users/chrisUsers.js.map +1 -1
  61. package/dist/utils/retry.d.ts +29 -0
  62. package/dist/utils/retry.js +44 -0
  63. package/dist/utils/retry.js.map +1 -0
  64. package/package.json +19 -8
@@ -0,0 +1,336 @@
1
+ /**
2
+ * @file Typed ChRIS API contract — domain-typed access to the hot wire surfaces.
3
+ *
4
+ * The adapter (`adapter.ts`) is the unsafe seam: the only module that imports
5
+ * `@fnndsc/chrisapi` and the only one allowed to cast against it. This module
6
+ * is the typed floor above that seam. It declares the wire shapes for the two
7
+ * surfaces that have produced live defects (the jobs surface: plugin
8
+ * instances, feeds; the PACS surface: download tokens, PACS files) and exposes
9
+ * domain-typed accessors built purely on the adapter's generics. Downstream
10
+ * packages call these instead of casting the opaque client per call site,
11
+ * which is what this module exists to end.
12
+ *
13
+ * Key components:
14
+ * - ListPage<T>: normalized page shape (data + totalCount) for CUBE lists
15
+ * - FeedData / PluginInstanceData / InstanceParameterData: wire row shapes
16
+ * - feedsPage_get / publicFeedsPage_get / pluginInstancesPage_get: paged reads
17
+ * - pluginInstance_get: detail handle (data, parameters, status, logs, delete)
18
+ * - downloadToken_create: PACS/LONK download token
19
+ *
20
+ * Dependencies: only `adapter.ts`. This file must contain no unchecked double
21
+ * casts and no `@fnndsc/chrisapi` import; the cast ratchet and the seam lint
22
+ * enforce that shape.
23
+ *
24
+ * @module
25
+ */
26
+ import { Client } from './adapter';
27
+ import type { PipelineRecord } from '../pipelines/chrisPipeline';
28
+ /**
29
+ * One normalized page of a paginated CUBE list.
30
+ *
31
+ * @property data - The rows of this page, in server order.
32
+ * @property totalCount - The collection's total row count when the server
33
+ * reported one, otherwise null. A null total means "unknown", not zero.
34
+ */
35
+ export interface ListPage<T> {
36
+ data: T[];
37
+ totalCount: number | null;
38
+ }
39
+ /**
40
+ * Wire shape of one CUBE feed row, as served by the feeds list endpoints.
41
+ *
42
+ * @property id - Feed id.
43
+ * @property name - Feed title.
44
+ * @property owner_username - Owning user, when serialized.
45
+ * @property public - Public visibility flag.
46
+ * @property creation_date - ISO creation timestamp.
47
+ * @property finished_jobs - Count of jobs finished successfully.
48
+ * @property errored_jobs - Count of jobs finished with error.
49
+ * @property started_jobs - Count of running jobs.
50
+ * @property scheduled_jobs - Count of scheduled jobs.
51
+ * @property cancelled_jobs - Count of cancelled jobs.
52
+ * @property created_jobs - Count of created (not yet scheduled) jobs.
53
+ */
54
+ export interface FeedData {
55
+ id: number;
56
+ name: string;
57
+ owner_username?: string;
58
+ public?: boolean;
59
+ creation_date?: string;
60
+ finished_jobs?: number;
61
+ errored_jobs?: number;
62
+ started_jobs?: number;
63
+ scheduled_jobs?: number;
64
+ cancelled_jobs?: number;
65
+ created_jobs?: number;
66
+ [key: string]: unknown;
67
+ }
68
+ /**
69
+ * Wire shape of one CUBE plugin-instance row.
70
+ *
71
+ * @property id - Instance id.
72
+ * @property feed_id - Owning feed id.
73
+ * @property previous_id - Parent instance id, or null for a feed root.
74
+ * @property plugin_name - Name of the plugin this instance runs.
75
+ * @property plugin_type - Plugin type (`fs`, `ds`, `ts`), when serialized.
76
+ * @property status - Current job status string.
77
+ * @property output_path - CFS output directory, once CUBE records one.
78
+ * @property raw - Base64 zlib-compressed pfcon response, when present.
79
+ */
80
+ export interface PluginInstanceData {
81
+ id: number;
82
+ feed_id: number;
83
+ previous_id?: number | null;
84
+ plugin_name: string;
85
+ plugin_type?: string;
86
+ status?: string;
87
+ output_path?: string;
88
+ raw?: string;
89
+ [key: string]: unknown;
90
+ }
91
+ /**
92
+ * One resolved parameter value recorded on a plugin instance.
93
+ *
94
+ * @property param_name - The parameter's flag name.
95
+ * @property value - The recorded invocation value.
96
+ */
97
+ export interface InstanceParameterData {
98
+ param_name?: string;
99
+ value?: unknown;
100
+ }
101
+ /**
102
+ * A CUBE file-download token, used for authenticated downloads and the LONK
103
+ * WebSocket.
104
+ *
105
+ * @property token - The token string.
106
+ * @property url - REST URL of the token resource (its origin hosts the LONK
107
+ * WebSocket endpoint).
108
+ */
109
+ export interface DownloadToken {
110
+ token: string;
111
+ url: string;
112
+ }
113
+ /**
114
+ * Typed handle over one plugin-instance detail resource.
115
+ *
116
+ * Wraps the live chrisapi resource so callers can read its payload and drive
117
+ * its lifecycle without touching the unsafe object.
118
+ *
119
+ * @property data - The instance's wire payload, or null when the resource
120
+ * carries none (the sub-resources and lifecycle methods still work).
121
+ */
122
+ export interface PluginInstanceHandle {
123
+ data: PluginInstanceData | null;
124
+ /**
125
+ * Reads one page of the instance's effective parameter values.
126
+ *
127
+ * @param params - Page window (limit, offset).
128
+ * @returns The page of recorded parameter values.
129
+ */
130
+ parametersPage_get(params: {
131
+ limit: number;
132
+ offset: number;
133
+ }): Promise<ListPage<InstanceParameterData>>;
134
+ /**
135
+ * Writes a new status to the instance (e.g. `cancelled`).
136
+ *
137
+ * @param status - The status string to PUT.
138
+ */
139
+ status_set(status: string): Promise<void>;
140
+ /** Deletes the instance record from CUBE. */
141
+ delete(): Promise<void>;
142
+ /**
143
+ * Fetches the instance's log text via its logs sub-resource.
144
+ *
145
+ * @returns The joined log text, or null when this instance's resource does
146
+ * not expose logs.
147
+ */
148
+ logs_get(): Promise<string | null>;
149
+ }
150
+ /**
151
+ * Reads one page of the session user's feeds (owned and shared).
152
+ *
153
+ * @param client - Connected chrisapi client.
154
+ * @param params - CUBE search/pagination params (limit, offset, id, ...).
155
+ * @returns The typed feed page.
156
+ * @throws {Error} Propagates chrisapi/network errors.
157
+ */
158
+ export declare function feedsPage_get(client: Client, params: Record<string, unknown>): Promise<ListPage<FeedData>>;
159
+ /**
160
+ * Reads one page of public feeds, when the connected CUBE offers them.
161
+ *
162
+ * @param client - Connected chrisapi client.
163
+ * @param params - CUBE search/pagination params.
164
+ * @returns The typed feed page, or null when the client has no public-feeds
165
+ * endpoint (older CUBE versions).
166
+ * @throws {Error} Propagates chrisapi/network errors.
167
+ */
168
+ export declare function publicFeedsPage_get(client: Client, params: Record<string, unknown>): Promise<ListPage<FeedData> | null>;
169
+ /**
170
+ * Reads one page of plugin instances, optionally filtered.
171
+ *
172
+ * @param client - Connected chrisapi client.
173
+ * @param params - CUBE search/pagination params (feed_id, id, plugin_name, ...).
174
+ * @returns The typed instance page.
175
+ * @throws {Error} Propagates chrisapi/network errors.
176
+ */
177
+ export declare function pluginInstancesPage_get(client: Client, params: Record<string, unknown>): Promise<ListPage<PluginInstanceData>>;
178
+ /**
179
+ * Fetches one plugin instance's detail resource as a typed handle.
180
+ *
181
+ * @param client - Connected chrisapi client.
182
+ * @param instanceID - The plugin instance id.
183
+ * @returns The typed handle, or null when CUBE returns no such instance.
184
+ * @throws {Error} Propagates chrisapi/network errors.
185
+ */
186
+ export declare function pluginInstance_get(client: Client, instanceID: number): Promise<PluginInstanceHandle | null>;
187
+ /**
188
+ * Wire shape of one registered pipeline source file row.
189
+ *
190
+ * @property fname - CFS path of the uploaded pipeline source.
191
+ * @property pipeline_name - Name of the pipeline it registered.
192
+ * @property pipeline_id - Id of the pipeline it registered.
193
+ */
194
+ export interface PipelineSourceFileData {
195
+ fname: string;
196
+ pipeline_name?: string;
197
+ pipeline_id?: number;
198
+ [key: string]: unknown;
199
+ }
200
+ /**
201
+ * Wire shape of one plugin piping row in a registered pipeline.
202
+ *
203
+ * @property id - Piping id.
204
+ * @property title - Piping title, when authored.
205
+ * @property plugin_name - Name of the plugin this piping runs.
206
+ * @property plugin_version - Version of that plugin.
207
+ * @property previous_id - Parent piping id, or null for the root.
208
+ */
209
+ export interface PluginPipingData {
210
+ id: number;
211
+ title?: string;
212
+ plugin_name?: string;
213
+ plugin_version?: string;
214
+ previous_id?: number | null;
215
+ [key: string]: unknown;
216
+ }
217
+ /**
218
+ * Wire shape of one stored piping default-parameter row.
219
+ *
220
+ * @property plugin_piping_id - Piping the default belongs to.
221
+ * @property param_name - The parameter's flag name.
222
+ * @property value - The stored default value.
223
+ */
224
+ export interface PipingDefaultParameterData {
225
+ plugin_piping_id?: number;
226
+ param_name?: string;
227
+ value?: unknown;
228
+ [key: string]: unknown;
229
+ }
230
+ /**
231
+ * Wire shape of one plugin parameter definition row.
232
+ *
233
+ * @property name - The parameter's flag name.
234
+ * @property type - Declared value type (e.g. "string").
235
+ * @property optional - Whether the parameter may be omitted.
236
+ * @property default - Declared default value.
237
+ * @property help - Author-provided help text.
238
+ */
239
+ export interface PluginParameterData {
240
+ name: string;
241
+ type?: string;
242
+ optional?: boolean;
243
+ default?: unknown;
244
+ help?: string;
245
+ [key: string]: unknown;
246
+ }
247
+ /**
248
+ * Wire shape of one compute-resource row attached to a plugin.
249
+ *
250
+ * @property name - The compute environment's name.
251
+ */
252
+ export interface ComputeResourceData {
253
+ name?: string;
254
+ [key: string]: unknown;
255
+ }
256
+ /**
257
+ * Typed handle over one plugin detail resource (metadata surfaces only).
258
+ */
259
+ export interface PluginHandle {
260
+ /**
261
+ * Reads one page of the plugin's declared parameters.
262
+ *
263
+ * @param params - Page window (limit, offset).
264
+ * @returns The page of parameter definitions.
265
+ */
266
+ parametersPage_get(params: Record<string, unknown>): Promise<ListPage<PluginParameterData>>;
267
+ /**
268
+ * Reads one page of the plugin's registered compute resources.
269
+ *
270
+ * @param params - Page window (limit, offset).
271
+ * @returns The page of compute-resource rows.
272
+ */
273
+ computeResourcesPage_get(params: Record<string, unknown>): Promise<ListPage<ComputeResourceData>>;
274
+ }
275
+ /**
276
+ * One plugin piping of a registered pipeline, with its plugin reachable.
277
+ *
278
+ * @property data - The piping's wire payload.
279
+ */
280
+ export interface PluginPipingItem {
281
+ data: PluginPipingData;
282
+ /**
283
+ * Fetches the plugin this piping runs, when the item links one.
284
+ *
285
+ * @returns The plugin handle, or null when the item exposes no plugin link.
286
+ */
287
+ plugin_get(): Promise<PluginHandle | null>;
288
+ }
289
+ /**
290
+ * Typed handle over one registered pipeline resource.
291
+ *
292
+ * @property data - The pipeline's wire payload, or null when absent.
293
+ */
294
+ export interface PipelineHandle {
295
+ data: PipelineRecord | null;
296
+ /**
297
+ * Reads the pipeline's plugin pipings as items (plugin link preserved).
298
+ *
299
+ * @param params - Page window (limit, offset).
300
+ * @returns The piping items of that page.
301
+ */
302
+ pluginPipings_get(params: Record<string, unknown>): Promise<PluginPipingItem[]>;
303
+ /**
304
+ * Reads one page of the stored piping default parameters.
305
+ *
306
+ * @param params - Page window (limit, offset).
307
+ * @returns The page of stored defaults.
308
+ */
309
+ defaultParametersPage_get(params: Record<string, unknown>): Promise<ListPage<PipingDefaultParameterData>>;
310
+ }
311
+ /**
312
+ * Fetches one registered pipeline's detail resource as a typed handle.
313
+ *
314
+ * @param client - Connected chrisapi client.
315
+ * @param pipelineID - The pipeline id.
316
+ * @returns The typed handle, or null when CUBE returns no such pipeline.
317
+ * @throws {Error} Propagates chrisapi/network errors.
318
+ */
319
+ export declare function pipeline_get(client: Client, pipelineID: number): Promise<PipelineHandle | null>;
320
+ /**
321
+ * Reads one page of registered pipeline source files.
322
+ *
323
+ * @param client - Connected chrisapi client.
324
+ * @param params - CUBE search/pagination params (pipeline_id, limit, ...).
325
+ * @returns The typed source-file page.
326
+ * @throws {Error} Propagates chrisapi/network errors.
327
+ */
328
+ export declare function pipelineSourceFilesPage_get(client: Client, params: Record<string, unknown>): Promise<ListPage<PipelineSourceFileData>>;
329
+ /**
330
+ * Creates a CUBE download token for authenticated file access and LONK.
331
+ *
332
+ * @param client - Connected chrisapi client.
333
+ * @returns The token string and the token resource's REST URL.
334
+ * @throws {Error} Propagates chrisapi/network errors.
335
+ */
336
+ export declare function downloadToken_create(client: Client): Promise<DownloadToken>;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ /**
3
+ * @file Typed ChRIS API contract — domain-typed access to the hot wire surfaces.
4
+ *
5
+ * The adapter (`adapter.ts`) is the unsafe seam: the only module that imports
6
+ * `@fnndsc/chrisapi` and the only one allowed to cast against it. This module
7
+ * is the typed floor above that seam. It declares the wire shapes for the two
8
+ * surfaces that have produced live defects (the jobs surface: plugin
9
+ * instances, feeds; the PACS surface: download tokens, PACS files) and exposes
10
+ * domain-typed accessors built purely on the adapter's generics. Downstream
11
+ * packages call these instead of casting the opaque client per call site,
12
+ * which is what this module exists to end.
13
+ *
14
+ * Key components:
15
+ * - ListPage<T>: normalized page shape (data + totalCount) for CUBE lists
16
+ * - FeedData / PluginInstanceData / InstanceParameterData: wire row shapes
17
+ * - feedsPage_get / publicFeedsPage_get / pluginInstancesPage_get: paged reads
18
+ * - pluginInstance_get: detail handle (data, parameters, status, logs, delete)
19
+ * - downloadToken_create: PACS/LONK download token
20
+ *
21
+ * Dependencies: only `adapter.ts`. This file must contain no unchecked double
22
+ * casts and no `@fnndsc/chrisapi` import; the cast ratchet and the seam lint
23
+ * enforce that shape.
24
+ *
25
+ * @module
26
+ */
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.feedsPage_get = feedsPage_get;
29
+ exports.publicFeedsPage_get = publicFeedsPage_get;
30
+ exports.pluginInstancesPage_get = pluginInstancesPage_get;
31
+ exports.pluginInstance_get = pluginInstance_get;
32
+ exports.pipeline_get = pipeline_get;
33
+ exports.pipelineSourceFilesPage_get = pipelineSourceFilesPage_get;
34
+ exports.downloadToken_create = downloadToken_create;
35
+ const adapter_1 = require("./adapter");
36
+ /**
37
+ * Normalizes a raw chrisapi list response into a typed ListPage.
38
+ *
39
+ * @param page - The raw list resource (or null/undefined).
40
+ * @returns The typed page; totalCount is null when the server sent none.
41
+ */
42
+ function listPage_wrap(page) {
43
+ const total = page?.totalCount;
44
+ return {
45
+ data: (0, adapter_1.listData_get)(page ?? undefined),
46
+ totalCount: typeof total === 'number' && total >= 0 ? total : null,
47
+ };
48
+ }
49
+ /**
50
+ * Reads one page of the session user's feeds (owned and shared).
51
+ *
52
+ * @param client - Connected chrisapi client.
53
+ * @param params - CUBE search/pagination params (limit, offset, id, ...).
54
+ * @returns The typed feed page.
55
+ * @throws {Error} Propagates chrisapi/network errors.
56
+ */
57
+ async function feedsPage_get(client, params) {
58
+ return listPage_wrap(await (0, adapter_1.resource_call)(client, 'getFeeds', params));
59
+ }
60
+ /**
61
+ * Reads one page of public feeds, when the connected CUBE offers them.
62
+ *
63
+ * @param client - Connected chrisapi client.
64
+ * @param params - CUBE search/pagination params.
65
+ * @returns The typed feed page, or null when the client has no public-feeds
66
+ * endpoint (older CUBE versions).
67
+ * @throws {Error} Propagates chrisapi/network errors.
68
+ */
69
+ async function publicFeedsPage_get(client, params) {
70
+ if (!(0, adapter_1.method_exists)(client, 'getPublicFeeds'))
71
+ return null;
72
+ return listPage_wrap(await (0, adapter_1.resource_call)(client, 'getPublicFeeds', params));
73
+ }
74
+ /**
75
+ * Reads one page of plugin instances, optionally filtered.
76
+ *
77
+ * @param client - Connected chrisapi client.
78
+ * @param params - CUBE search/pagination params (feed_id, id, plugin_name, ...).
79
+ * @returns The typed instance page.
80
+ * @throws {Error} Propagates chrisapi/network errors.
81
+ */
82
+ async function pluginInstancesPage_get(client, params) {
83
+ return listPage_wrap(await (0, adapter_1.resource_call)(client, 'getPluginInstances', params));
84
+ }
85
+ /**
86
+ * Fetches one plugin instance's detail resource as a typed handle.
87
+ *
88
+ * @param client - Connected chrisapi client.
89
+ * @param instanceID - The plugin instance id.
90
+ * @returns The typed handle, or null when CUBE returns no such instance.
91
+ * @throws {Error} Propagates chrisapi/network errors.
92
+ */
93
+ async function pluginInstance_get(client, instanceID) {
94
+ const resource = await (0, adapter_1.resource_call)(client, 'getPluginInstance', instanceID);
95
+ if (!resource)
96
+ return null;
97
+ const data = (0, adapter_1.itemData_get)(resource);
98
+ return {
99
+ data,
100
+ async parametersPage_get(params) {
101
+ // Some chrisapi versions serve rows in `data`, others only via getItems().
102
+ return listPageFlexible_wrap(await (0, adapter_1.resource_call)(resource, 'getParameters', params));
103
+ },
104
+ async status_set(status) {
105
+ await (0, adapter_1.resource_call)(resource, 'put', { status });
106
+ },
107
+ async delete() {
108
+ await (0, adapter_1.resource_call)(resource, 'delete');
109
+ },
110
+ async logs_get() {
111
+ if (!(0, adapter_1.method_exists)(resource, 'getLogs'))
112
+ return null;
113
+ const logs = await (0, adapter_1.resource_call)(resource, 'getLogs');
114
+ const rows = (0, adapter_1.listData_get)(logs);
115
+ return rows.map((row) => (typeof row.log === 'string' ? row.log : '')).join('\n');
116
+ },
117
+ };
118
+ }
119
+ /**
120
+ * Normalizes a chrisapi list response that may serve rows in `data` or only
121
+ * via `getItems()` into a typed ListPage.
122
+ *
123
+ * @param page - The raw list resource.
124
+ * @returns The typed page; totalCount is null when the server sent none.
125
+ */
126
+ function listPageFlexible_wrap(page) {
127
+ if (Array.isArray(page?.data) || typeof page?.getItems !== 'function') {
128
+ return listPage_wrap(page);
129
+ }
130
+ const rows = (0, adapter_1.items_get)(page)
131
+ .map((item) => (0, adapter_1.itemData_get)(item))
132
+ .filter((row) => row !== null);
133
+ const total = page?.totalCount;
134
+ return { data: rows, totalCount: typeof total === 'number' && total >= 0 ? total : null };
135
+ }
136
+ /**
137
+ * Wraps a plugin detail resource as a typed metadata handle.
138
+ *
139
+ * @param resource - The chrisapi plugin resource.
140
+ * @returns The typed handle.
141
+ */
142
+ function pluginHandle_wrap(resource) {
143
+ return {
144
+ async parametersPage_get(params) {
145
+ return listPageFlexible_wrap(await (0, adapter_1.resource_call)(resource, 'getPluginParameters', params));
146
+ },
147
+ async computeResourcesPage_get(params) {
148
+ return listPageFlexible_wrap(await (0, adapter_1.resource_call)(resource, 'getPluginComputeResources', params));
149
+ },
150
+ };
151
+ }
152
+ /**
153
+ * Fetches one registered pipeline's detail resource as a typed handle.
154
+ *
155
+ * @param client - Connected chrisapi client.
156
+ * @param pipelineID - The pipeline id.
157
+ * @returns The typed handle, or null when CUBE returns no such pipeline.
158
+ * @throws {Error} Propagates chrisapi/network errors.
159
+ */
160
+ async function pipeline_get(client, pipelineID) {
161
+ const resource = await (0, adapter_1.resource_call)(client, 'getPipeline', pipelineID);
162
+ if (!resource)
163
+ return null;
164
+ return {
165
+ data: (0, adapter_1.itemData_get)(resource),
166
+ async pluginPipings_get(params) {
167
+ const page = await (0, adapter_1.resource_call)(resource, 'getPluginPipings', params);
168
+ const rawItems = typeof page?.getItems === 'function'
169
+ ? (0, adapter_1.items_get)(page)
170
+ : (0, adapter_1.listData_get)(page).map((row) => ({ data: row }));
171
+ return rawItems
172
+ .map((item) => {
173
+ const data = (0, adapter_1.itemData_get)(item);
174
+ if (!data)
175
+ return null;
176
+ return {
177
+ data,
178
+ async plugin_get() {
179
+ if (!(0, adapter_1.method_exists)(item, 'getPlugin'))
180
+ return null;
181
+ const plugin = await (0, adapter_1.resource_call)(item, 'getPlugin');
182
+ return plugin ? pluginHandle_wrap(plugin) : null;
183
+ },
184
+ };
185
+ })
186
+ .filter((item) => item !== null);
187
+ },
188
+ async defaultParametersPage_get(params) {
189
+ return listPageFlexible_wrap(await (0, adapter_1.resource_call)(resource, 'getDefaultParameters', params));
190
+ },
191
+ };
192
+ }
193
+ /**
194
+ * Reads one page of registered pipeline source files.
195
+ *
196
+ * @param client - Connected chrisapi client.
197
+ * @param params - CUBE search/pagination params (pipeline_id, limit, ...).
198
+ * @returns The typed source-file page.
199
+ * @throws {Error} Propagates chrisapi/network errors.
200
+ */
201
+ async function pipelineSourceFilesPage_get(client, params) {
202
+ return listPageFlexible_wrap(await (0, adapter_1.resource_call)(client, 'getPipelineSourceFiles', params));
203
+ }
204
+ /**
205
+ * Creates a CUBE download token for authenticated file access and LONK.
206
+ *
207
+ * @param client - Connected chrisapi client.
208
+ * @returns The token string and the token resource's REST URL.
209
+ * @throws {Error} Propagates chrisapi/network errors.
210
+ */
211
+ async function downloadToken_create(client) {
212
+ const resource = await (0, adapter_1.resource_call)(client, 'createDownloadToken');
213
+ const data = (0, adapter_1.itemData_get)(resource);
214
+ return {
215
+ token: String(data?.token ?? ''),
216
+ url: String(resource?.url ?? ''),
217
+ };
218
+ }
219
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/chrisapi/contract.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,11 @@ interface ConnectOptions {
24
24
  debug: boolean;
25
25
  url: string;
26
26
  }
27
+ /** Credentials used to obtain a short-lived elevated CUBE token. */
28
+ export interface ElevationCredentials {
29
+ username: string;
30
+ password: string;
31
+ }
27
32
  /**
28
33
  * Manages the connection and authentication with a ChRIS CUBE.
29
34
  */
@@ -35,6 +40,7 @@ export declare class ChRISConnection {
35
40
  private client;
36
41
  private _config?;
37
42
  private storageProvider?;
43
+ private readonly elevatedClientContext;
38
44
  /**
39
45
  * Constructs a new ChRISConnection instance.
40
46
  * @param config - The connection configuration object.
@@ -89,6 +95,20 @@ export declare class ChRISConnection {
89
95
  * @returns A Promise resolving to the Client instance or null.
90
96
  */
91
97
  client_get(): Promise<Client | null>;
98
+ /**
99
+ * Executes one operation with a non-persistent CUBE client for supplied
100
+ * credentials. The client follows only the nested operation's asynchronous
101
+ * context, so concurrent normal and elevated commands retain their own
102
+ * identities.
103
+ *
104
+ * The normal session token, cached client, and token storage remain intact.
105
+ *
106
+ * @param credentials - Credentials for the requested CUBE identity.
107
+ * @param operation - Work to perform while the temporary client is active.
108
+ * @returns The operation's result.
109
+ * @throws {Error} When no CUBE URL is available or authentication fails.
110
+ */
111
+ elevation_withCredentials<T>(credentials: ElevationCredentials, operation: () => Promise<T>): Promise<T>;
92
112
  /**
93
113
  * Checks if the client is currently connected.
94
114
  * @returns True if connected, false otherwise.
@@ -22,6 +22,7 @@ const chrisContext_js_1 = require("../context/chrisContext.js");
22
22
  const chrisIO_js_1 = require("../io/chrisIO.js");
23
23
  const errorStack_js_1 = require("../error/errorStack.js");
24
24
  const chalk_1 = __importDefault(require("chalk"));
25
+ const node_async_hooks_1 = require("node:async_hooks");
25
26
  /**
26
27
  * Helper function to validate and format a context string.
27
28
  * @param context - The context string to check.
@@ -50,6 +51,7 @@ class ChRISConnection {
50
51
  this.user = null;
51
52
  this.chrisURL = null;
52
53
  this.client = null;
54
+ this.elevatedClientContext = new node_async_hooks_1.AsyncLocalStorage();
53
55
  if (config && storageProvider) {
54
56
  this.init(config, storageProvider);
55
57
  }
@@ -228,6 +230,9 @@ class ChRISConnection {
228
230
  * @returns A Promise resolving to the Client instance or null.
229
231
  */
230
232
  async client_get() {
233
+ const elevatedClient = this.elevatedClientContext.getStore();
234
+ if (elevatedClient)
235
+ return elevatedClient;
231
236
  if ((await this.authToken_get()) &&
232
237
  (await this.chrisURL_get()) &&
233
238
  this.chrisURL &&
@@ -238,6 +243,27 @@ class ChRISConnection {
238
243
  }
239
244
  return this.client;
240
245
  }
246
+ /**
247
+ * Executes one operation with a non-persistent CUBE client for supplied
248
+ * credentials. The client follows only the nested operation's asynchronous
249
+ * context, so concurrent normal and elevated commands retain their own
250
+ * identities.
251
+ *
252
+ * The normal session token, cached client, and token storage remain intact.
253
+ *
254
+ * @param credentials - Credentials for the requested CUBE identity.
255
+ * @param operation - Work to perform while the temporary client is active.
256
+ * @returns The operation's result.
257
+ * @throws {Error} When no CUBE URL is available or authentication fails.
258
+ */
259
+ async elevation_withCredentials(credentials, operation) {
260
+ const url = await this.chrisURL_get();
261
+ if (!url)
262
+ throw new Error('Not connected to ChRIS. Run connect first.');
263
+ const token = await (0, adapter_js_1.authToken_get)(`${url}auth-token/`, credentials.username, credentials.password);
264
+ const elevatedClient = (0, adapter_js_1.client_create)(url, token);
265
+ return await this.elevatedClientContext.run(elevatedClient, operation);
266
+ }
241
267
  /**
242
268
  * Checks if the client is currently connected.
243
269
  * @returns True if connected, false otherwise.
@@ -281,6 +307,13 @@ class ChRISConnection {
281
307
  this.authToken = await this.storageProvider.read(this.tokenFile);
282
308
  }
283
309
  catch (error) {
310
+ // A missing token file is the normal logged-out state; any other read
311
+ // failure (permissions, disk) must not silently present as logged-out.
312
+ const code = error?.code;
313
+ if (code !== "ENOENT") {
314
+ const msg = error instanceof Error ? error.message : String(error);
315
+ errorStack_js_1.errorStack.stack_push("warning", `Could not read auth token file ${this.tokenFile}: ${msg}`);
316
+ }
284
317
  this.authToken = null;
285
318
  }
286
319
  }