@fnndsc/salsa 3.5.1 → 3.6.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.
- package/README.md +3 -3
- package/dist/connect/index.d.ts +11 -0
- package/dist/connect/index.js +11 -0
- package/dist/connect/index.js.map +1 -1
- package/dist/dag/feedJoins.js +4 -1
- package/dist/dag/feedJoins.js.map +1 -1
- package/dist/feeds/index.d.ts +15 -2
- package/dist/feeds/index.js.map +1 -1
- package/dist/files/index.d.ts +7 -0
- package/dist/files/index.js +12 -11
- package/dist/files/index.js.map +1 -1
- package/dist/files/regular_content.js +11 -3
- package/dist/files/regular_content.js.map +1 -1
- package/dist/groups/index.d.ts +59 -0
- package/dist/groups/index.js +89 -0
- package/dist/groups/index.js.map +1 -1
- package/dist/groups/membershipRevision.d.ts +19 -0
- package/dist/groups/membershipRevision.js +29 -0
- package/dist/groups/membershipRevision.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/jobs/jobOps.js +45 -2
- package/dist/jobs/jobOps.js.map +1 -1
- package/dist/pipelines/index.d.ts +28 -5
- package/dist/pipelines/index.js +110 -48
- package/dist/pipelines/index.js.map +1 -1
- package/dist/pipelines/invocation.d.ts +80 -0
- package/dist/pipelines/invocation.js +290 -0
- package/dist/pipelines/invocation.js.map +1 -0
- package/dist/pipelines/manifest.d.ts +102 -0
- package/dist/pipelines/manifest.js +204 -0
- package/dist/pipelines/manifest.js.map +1 -0
- package/dist/plugins/index.d.ts +29 -0
- package/dist/plugins/index.js +51 -10
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/internal/plugin_executeNewFeed.d.ts +0 -14
- package/dist/plugins/internal/plugin_executeNewFeed.js +3 -3
- package/dist/plugins/internal/plugin_executeNewFeed.js.map +1 -1
- package/dist/plugins/plugin_register.js +5 -5
- package/dist/plugins/plugin_register.js.map +1 -1
- package/dist/plugins/store_import.js +1 -1
- package/dist/plugins/store_import.js.map +1 -1
- package/dist/retrieve/watch.d.ts +114 -0
- package/dist/retrieve/watch.js +360 -0
- package/dist/retrieve/watch.js.map +1 -0
- package/dist/store/index.d.ts +17 -4
- package/dist/store/index.js +9 -4
- package/dist/store/index.js.map +1 -1
- package/dist/users/index.d.ts +36 -0
- package/dist/users/index.js +50 -0
- package/dist/users/index.js.map +1 -0
- package/dist/vfs/dispatcher.d.ts +11 -0
- package/dist/vfs/dispatcher.js +37 -6
- package/dist/vfs/dispatcher.js.map +1 -1
- package/dist/vfs/index.d.ts +1 -0
- package/dist/vfs/index.js +3 -0
- package/dist/vfs/index.js.map +1 -1
- package/dist/vfs/provider.d.ts +13 -0
- package/dist/vfs/providers/etc.d.ts +2 -0
- package/dist/vfs/providers/etc.js +41 -2
- package/dist/vfs/providers/etc.js.map +1 -1
- package/dist/vfs/providers/native.js +41 -7
- package/dist/vfs/providers/native.js.map +1 -1
- package/dist/vfs/providers/pacs.d.ts +13 -1
- package/dist/vfs/providers/pacs.js +86 -107
- package/dist/vfs/providers/pacs.js.map +1 -1
- package/dist/vfs/providers/pacsHelpers.js +9 -5
- package/dist/vfs/providers/pacsHelpers.js.map +1 -1
- package/dist/vfs/providers/proc.d.ts +34 -1
- package/dist/vfs/providers/proc.js +301 -62
- package/dist/vfs/providers/proc.js.map +1 -1
- package/package.json +11 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/vfs/dispatcher.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/vfs/dispatcher.ts"],"names":[],"mappings":"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"}
|
package/dist/vfs/index.d.ts
CHANGED
package/dist/vfs/index.js
CHANGED
|
@@ -18,9 +18,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.queryId_extractFromFolder = void 0;
|
|
21
22
|
__exportStar(require("./provider.js"), exports);
|
|
22
23
|
__exportStar(require("./dispatcher.js"), exports);
|
|
23
24
|
__exportStar(require("./providers/native.js"), exports);
|
|
24
25
|
__exportStar(require("./providers/pacs.js"), exports);
|
|
26
|
+
var pacsHelpers_js_1 = require("./providers/pacsHelpers.js");
|
|
27
|
+
Object.defineProperty(exports, "queryId_extractFromFolder", { enumerable: true, get: function () { return pacsHelpers_js_1.queryId_extractFromFolder; } });
|
|
25
28
|
__exportStar(require("./providers/etc.js"), exports);
|
|
26
29
|
//# sourceMappingURL=index.js.map
|
package/dist/vfs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vfs/index.ts"],"names":[],"mappings":";AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vfs/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,gDAA8B;AAC9B,kDAAgC;AAChC,wDAAsC;AACtC,sDAAoC;AACpC,6DAAuE;AAA9D,2HAAA,yBAAyB,OAAA;AAClC,qDAAmC"}
|
package/dist/vfs/provider.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface VFSItem {
|
|
|
27
27
|
version?: string;
|
|
28
28
|
/** Title or description (for feeds, queries). */
|
|
29
29
|
title?: string;
|
|
30
|
+
/** Backing resource ID, when the virtual entry represents one. */
|
|
31
|
+
id?: number;
|
|
30
32
|
/** Execution status (for job type items). */
|
|
31
33
|
status?: string;
|
|
32
34
|
}
|
|
@@ -77,4 +79,15 @@ export interface VFSProvider {
|
|
|
77
79
|
* @returns A Promise resolving to a Result containing the file contents as a Buffer.
|
|
78
80
|
*/
|
|
79
81
|
readBinary?(path: string): Promise<Result<Buffer>>;
|
|
82
|
+
/**
|
|
83
|
+
* Resolves the target of a provider-defined lazy link when an operation
|
|
84
|
+
* actually follows it.
|
|
85
|
+
*
|
|
86
|
+
* Listings must not use this hook: providers may expose an unresolved link
|
|
87
|
+
* as structural metadata without paying for its target until navigation.
|
|
88
|
+
*
|
|
89
|
+
* @param path - Absolute virtual path naming the link.
|
|
90
|
+
* @returns The target path, or an error when the provider cannot resolve it.
|
|
91
|
+
*/
|
|
92
|
+
linkTarget_resolve?(path: string): Promise<Result<string>>;
|
|
80
93
|
}
|
|
@@ -16,6 +16,7 @@ import { VFSProvider, VFSItem, CpOptions } from '../provider.js';
|
|
|
16
16
|
*/
|
|
17
17
|
export declare class EtcVfsProvider implements VFSProvider {
|
|
18
18
|
prefix: string;
|
|
19
|
+
private groupProjectionCache;
|
|
19
20
|
/**
|
|
20
21
|
* Lists contents of /etc — the four virtual config files.
|
|
21
22
|
*
|
|
@@ -38,6 +39,7 @@ export declare class EtcVfsProvider implements VFSProvider {
|
|
|
38
39
|
*/
|
|
39
40
|
read(path: string): Promise<Result<string>>;
|
|
40
41
|
private computeYaml_render;
|
|
42
|
+
/** Renders CUBE groups and their usernames in POSIX `/etc/group` form. */
|
|
41
43
|
private group_render;
|
|
42
44
|
private passwd_render;
|
|
43
45
|
private cube_render;
|
|
@@ -14,13 +14,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
14
14
|
exports.EtcVfsProvider = void 0;
|
|
15
15
|
const cumin_1 = require("@fnndsc/cumin");
|
|
16
16
|
const cumin_2 = require("@fnndsc/cumin");
|
|
17
|
+
const membershipRevision_js_1 = require("../../groups/membershipRevision.js");
|
|
17
18
|
/** Virtual files exposed under /etc. */
|
|
18
19
|
const ETC_FILES = ['compute.yaml', 'group', 'passwd', 'cube'];
|
|
20
|
+
/** Maximum group membership lists hydrated concurrently for `/etc/group`. */
|
|
21
|
+
const GROUP_MEMBERSHIP_CONCURRENCY = 4;
|
|
22
|
+
/** How long external CUBE membership changes may remain cached. */
|
|
23
|
+
const GROUP_PROJECTION_TTL_MS = 5 * 60 * 1000;
|
|
19
24
|
/**
|
|
20
25
|
* VFS provider for /etc — maps ChRIS API resources to Unix-style config files.
|
|
21
26
|
*/
|
|
22
27
|
class EtcVfsProvider {
|
|
23
28
|
prefix = '/etc';
|
|
29
|
+
groupProjectionCache;
|
|
24
30
|
/**
|
|
25
31
|
* Lists contents of /etc — the four virtual config files.
|
|
26
32
|
*
|
|
@@ -86,12 +92,45 @@ class EtcVfsProvider {
|
|
|
86
92
|
}
|
|
87
93
|
return (0, cumin_1.Ok)(lines.join('\n') + '\n');
|
|
88
94
|
}
|
|
95
|
+
/** Renders CUBE groups and their usernames in POSIX `/etc/group` form. */
|
|
89
96
|
async group_render() {
|
|
97
|
+
const cubeURL = await cumin_2.chrisContext.ChRISURL_get();
|
|
98
|
+
const cubeUser = await cumin_2.chrisContext.ChRISuser_get();
|
|
99
|
+
const connectionKey = `${cubeURL ?? ''}\u0000${cubeUser ?? ''}`;
|
|
100
|
+
const membershipRevision = (0, membershipRevision_js_1.groupMembershipRevision_get)();
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
if (this.groupProjectionCache?.connectionKey === connectionKey
|
|
103
|
+
&& this.groupProjectionCache.membershipRevision === membershipRevision
|
|
104
|
+
&& this.groupProjectionCache.expiresAt > now) {
|
|
105
|
+
return (0, cumin_1.Ok)(this.groupProjectionCache.content);
|
|
106
|
+
}
|
|
90
107
|
const result = await (0, cumin_2.groups_getAll)();
|
|
91
108
|
if (!result.ok)
|
|
92
109
|
return (0, cumin_1.Err)();
|
|
93
|
-
const lines =
|
|
94
|
-
|
|
110
|
+
const lines = [];
|
|
111
|
+
for (let index = 0; index < result.value.length; index += GROUP_MEMBERSHIP_CONCURRENCY) {
|
|
112
|
+
const groupBatch = result.value.slice(index, index + GROUP_MEMBERSHIP_CONCURRENCY);
|
|
113
|
+
const batchResults = await Promise.all(groupBatch.map(async (group) => ({
|
|
114
|
+
group,
|
|
115
|
+
members: await (0, cumin_2.groupMembers_getAll)(group.id),
|
|
116
|
+
})));
|
|
117
|
+
for (const { group, members } of batchResults) {
|
|
118
|
+
if (!members.ok)
|
|
119
|
+
return (0, cumin_1.Err)();
|
|
120
|
+
const usernames = members.value
|
|
121
|
+
.map((member) => member.username)
|
|
122
|
+
.join(',');
|
|
123
|
+
lines.push(`${group.name}:x:${group.id}:${usernames}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const content = lines.join('\n') + '\n';
|
|
127
|
+
this.groupProjectionCache = {
|
|
128
|
+
connectionKey,
|
|
129
|
+
content,
|
|
130
|
+
expiresAt: Date.now() + GROUP_PROJECTION_TTL_MS,
|
|
131
|
+
membershipRevision,
|
|
132
|
+
};
|
|
133
|
+
return (0, cumin_1.Ok)(content);
|
|
95
134
|
}
|
|
96
135
|
async passwd_render() {
|
|
97
136
|
const result = await (0, cumin_2.currentUser_get)();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"etc.js","sourceRoot":"","sources":["../../../src/vfs/providers/etc.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,yCAA4D;AAC5D,
|
|
1
|
+
{"version":3,"file":"etc.js","sourceRoot":"","sources":["../../../src/vfs/providers/etc.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,yCAA4D;AAC5D,yCAUuB;AAEvB,8EAAiF;AAEjF,wCAAwC;AACxC,MAAM,SAAS,GAAa,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAExE,6EAA6E;AAC7E,MAAM,4BAA4B,GAAW,CAAC,CAAC;AAE/C,mEAAmE;AACnE,MAAM,uBAAuB,GAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAUtD;;GAEG;AACH,MAAa,cAAc;IACzB,MAAM,GAAG,MAAM,CAAC;IACR,oBAAoB,CAAwC;IAEpE;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CACR,KAAa,EACb,QAA2E;QAE3E,MAAM,GAAG,GAAW,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAc,SAAS,CAAC,GAAG,CAAC,CAAC,IAAY,EAAW,EAAE,CAAC,CAAC;YACjE,IAAI;YACJ,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,GAAG;SACV,CAAC,CAAC,CAAC;QACJ,OAAO,IAAA,UAAE,EAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,IAAY,EAAE,KAAa,EAAE,QAAmB;QACvD,kBAAU,CAAC,UAAU,CAAC,OAAO,EAAE,2CAA2C,CAAC,CAAC;QAC5E,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,MAAM,QAAQ,GAAW,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAErD,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,cAAc;gBACjB,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACnC,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7B,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC;YAC9B,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5B;gBACE,kBAAU,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,gBAAgB,CAAC,CAAC;gBACxD,OAAO,IAAA,WAAG,GAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,MAAM,MAAM,GAA8B,MAAM,IAAA,+BAAuB,GAAE,CAAC;QAC1E,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,IAAA,WAAG,GAAE,CAAC;QAE7B,MAAM,KAAK,GAAa,CAAC,2BAA2B,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC7B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC5B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC,CAAC;gBACpD,IAAI,CAAC,CAAC,WAAW;oBAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QACD,OAAO,IAAA,UAAE,EAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,0EAA0E;IAClE,KAAK,CAAC,YAAY;QACxB,MAAM,OAAO,GAAkB,MAAM,oBAAY,CAAC,YAAY,EAAE,CAAC;QACjE,MAAM,QAAQ,GAAkB,MAAM,oBAAY,CAAC,aAAa,EAAE,CAAC;QACnE,MAAM,aAAa,GAAW,GAAG,OAAO,IAAI,EAAE,SAAS,QAAQ,IAAI,EAAE,EAAE,CAAC;QACxE,MAAM,kBAAkB,GAAW,IAAA,mDAA2B,GAAE,CAAC;QACjE,MAAM,GAAG,GAAW,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,IACE,IAAI,CAAC,oBAAoB,EAAE,aAAa,KAAK,aAAa;eACvD,IAAI,CAAC,oBAAoB,CAAC,kBAAkB,KAAK,kBAAkB;eACnE,IAAI,CAAC,oBAAoB,CAAC,SAAS,GAAG,GAAG,EAC5C,CAAC;YACD,OAAO,IAAA,UAAE,EAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,MAAM,GAAyB,MAAM,IAAA,qBAAa,GAAE,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,IAAA,WAAG,GAAE,CAAC;QAE7B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,KAAK,GAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,4BAA4B,EAAE,CAAC;YAC/F,MAAM,UAAU,GAAiB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,4BAA4B,CAAC,CAAC;YACjG,MAAM,YAAY,GAChB,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,KAAiB,EAAE,EAAE,CAAC,CAAC;gBAC7D,KAAK;gBACL,OAAO,EAAE,MAAM,IAAA,2BAAmB,EAAC,KAAK,CAAC,EAAE,CAAC;aAC7C,CAAC,CAAC,CAAC,CAAC;YACP,KAAK,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;gBAC9C,IAAI,CAAC,OAAO,CAAC,EAAE;oBAAE,OAAO,IAAA,WAAG,GAAE,CAAC;gBAC9B,MAAM,SAAS,GAAW,OAAO,CAAC,KAAK;qBACpC,GAAG,CAAC,CAAC,MAAwB,EAAU,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;qBAC1D,IAAI,CAAC,GAAG,CAAC,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,EAAE,IAAI,SAAS,EAAE,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAW,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAChD,IAAI,CAAC,oBAAoB,GAAG;YAC1B,aAAa;YACb,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAuB;YAC/C,kBAAkB;SACnB,CAAC;QACF,OAAO,IAAA,UAAE,EAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,MAAM,MAAM,GAAsB,MAAM,IAAA,uBAAe,GAAE,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,IAAA,WAAG,GAAE,CAAC;QAE7B,MAAM,CAAC,GAAc,MAAM,CAAC,KAAK,CAAC;QAClC,MAAM,GAAG,GAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAW,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,GAAW,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG,IAAI,GAAG,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC;QAC5E,OAAO,IAAA,UAAE,EAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,MAAM,GAAG,GAAkB,MAAM,oBAAY,CAAC,YAAY,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAkB,MAAM,oBAAY,CAAC,aAAa,EAAE,CAAC;QAC/D,MAAM,KAAK,GAAa;YACtB,yBAAyB;YACzB,QAAQ,GAAG,IAAI,iBAAiB,EAAE;YAClC,SAAS,IAAI,IAAI,iBAAiB,EAAE;SACrC,CAAC;QACF,OAAO,IAAA,UAAE,EAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AA7ID,wCA6IC"}
|
|
@@ -38,6 +38,24 @@ class NativeVfsProvider {
|
|
|
38
38
|
(0, index_js_1.files_listAll)(fetchOpts, "links", resolvedPath),
|
|
39
39
|
]);
|
|
40
40
|
const [dirsResult, filesResult, linksResult] = results;
|
|
41
|
+
// files_listAll returns null both for a failed folder resolution and for
|
|
42
|
+
// an existing folder whose collection is simply empty. When every
|
|
43
|
+
// sub-listing comes back empty-or-failed the two cases are
|
|
44
|
+
// indistinguishable here, so probe the parent listing: a missing folder
|
|
45
|
+
// must surface as an error, not render as an empty directory.
|
|
46
|
+
const noneSucceeded = results.every((settled) => settled.status === "rejected" || !settled.value?.tableData);
|
|
47
|
+
if (noneSucceeded && resolvedPath !== "/") {
|
|
48
|
+
const dirExists = await path_checkIsDir(resolvedPath);
|
|
49
|
+
if (!dirExists.ok) {
|
|
50
|
+
// The probe itself failed: report the verification failure rather
|
|
51
|
+
// than claiming the folder is absent.
|
|
52
|
+
return (0, cumin_1.Err)();
|
|
53
|
+
}
|
|
54
|
+
if (!dirExists.value) {
|
|
55
|
+
cumin_1.errorStack.stack_push("error", `Cannot list ${resolvedPath}: No such file or directory`);
|
|
56
|
+
return (0, cumin_1.Err)();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
41
59
|
const items = [];
|
|
42
60
|
const mapToItem = (raw, type) => {
|
|
43
61
|
let name = raw.fname || raw.path || "";
|
|
@@ -89,13 +107,19 @@ class NativeVfsProvider {
|
|
|
89
107
|
async cp(src, dest, options) {
|
|
90
108
|
try {
|
|
91
109
|
const srcIsDir = await path_checkIsDir(src);
|
|
92
|
-
if (srcIsDir
|
|
110
|
+
if (!srcIsDir.ok) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (srcIsDir.value && !options.recursive) {
|
|
93
114
|
cumin_1.errorStack.stack_push("error", `Source is a directory. Re-run with --recursive to copy: ${src}`);
|
|
94
115
|
return false;
|
|
95
116
|
}
|
|
96
117
|
const destIsDir = await path_checkIsDir(dest);
|
|
118
|
+
if (!destIsDir.ok) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
97
121
|
const destLooksDir = dest.endsWith("/");
|
|
98
|
-
const finalDest = (destIsDir || destLooksDir)
|
|
122
|
+
const finalDest = (destIsDir.value || destLooksDir)
|
|
99
123
|
? path_1.default.posix.join(dest, path_1.default.posix.basename(src))
|
|
100
124
|
: dest;
|
|
101
125
|
if (options.recursive) {
|
|
@@ -116,8 +140,13 @@ exports.NativeVfsProvider = NativeVfsProvider;
|
|
|
116
140
|
/**
|
|
117
141
|
* Determines whether a given ChRIS path refers to a directory.
|
|
118
142
|
*
|
|
143
|
+
* Distinguishes "verified absent" from "could not verify": a listing failure
|
|
144
|
+
* while probing must not masquerade as a missing directory, since callers use
|
|
145
|
+
* this probe to decide between not-found errors and real operations.
|
|
146
|
+
*
|
|
119
147
|
* @param targetPath - The absolute ChRIS path to check.
|
|
120
|
-
* @returns
|
|
148
|
+
* @returns Ok(true/false) when the parent listing answered, Err when the
|
|
149
|
+
* probe itself failed (an error has been pushed to the stack).
|
|
121
150
|
*/
|
|
122
151
|
async function path_checkIsDir(targetPath) {
|
|
123
152
|
const parent = path_1.default.posix.dirname(targetPath);
|
|
@@ -125,9 +154,11 @@ async function path_checkIsDir(targetPath) {
|
|
|
125
154
|
try {
|
|
126
155
|
const results = await (0, index_js_1.files_listAll)({ limit: 1000, offset: 0 }, "dirs", parent);
|
|
127
156
|
if (!results || !results.tableData) {
|
|
128
|
-
|
|
157
|
+
// files_listAll returns null for both an empty parent and a failed
|
|
158
|
+
// context: an empty parent simply has no dirs, so absent is the answer.
|
|
159
|
+
return (0, cumin_1.Ok)(false);
|
|
129
160
|
}
|
|
130
|
-
|
|
161
|
+
const found = results.tableData.some((entry) => {
|
|
131
162
|
const candidate = typeof entry.path === "string" && entry.path.length > 0
|
|
132
163
|
? entry.path
|
|
133
164
|
: typeof entry.fname === "string"
|
|
@@ -135,9 +166,12 @@ async function path_checkIsDir(targetPath) {
|
|
|
135
166
|
: "";
|
|
136
167
|
return candidate === targetPath || path_1.default.posix.basename(candidate) === name;
|
|
137
168
|
});
|
|
169
|
+
return (0, cumin_1.Ok)(found);
|
|
138
170
|
}
|
|
139
|
-
catch {
|
|
140
|
-
|
|
171
|
+
catch (error) {
|
|
172
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
173
|
+
cumin_1.errorStack.stack_push("error", `Cannot verify directory ${targetPath}: ${msg}`);
|
|
174
|
+
return (0, cumin_1.Err)();
|
|
141
175
|
}
|
|
142
176
|
}
|
|
143
177
|
//# sourceMappingURL=native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../src/vfs/providers/native.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;AAEH,yCAA4D;AAE5D,wCAA2C;AAC3C,mDAI8B;AAC9B,gDAAwB;AAaxB;;GAEG;AACH,MAAa,iBAAiB;IAC5B,iCAAiC;IACjC,MAAM,GAAG,EAAE,CAAC;IAEZ;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CACR,OAAe,EACf,OAA0E;QAE1E,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YAC7C,MAAM,YAAY,GAAW,OAAO,IAAI,GAAG,CAAC;YAE5C,4CAA4C;YAC5C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;gBACvC,IAAA,wBAAa,EAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC;gBAC9C,IAAA,wBAAa,EAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC;gBAC/C,IAAA,wBAAa,EAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC;aAChD,CAAC,CAAC;YAEH,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../src/vfs/providers/native.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,8 +17,20 @@ type SortOptions = {
|
|
|
17
17
|
export declare class PacsVfsProvider implements VFSProvider {
|
|
18
18
|
/** Prefix matches /net/pacs and subdirectories. */
|
|
19
19
|
prefix: string;
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Cache for decoded PACS query results to avoid redundant API hits.
|
|
22
|
+
*
|
|
23
|
+
* Contract (see docs/code-audit-2026-08.adoc, cache inventory): only a
|
|
24
|
+
* settled result — one carrying a structured `json` payload — is cached,
|
|
25
|
+
* since a query's payload is written once and never mutates afterwards; a
|
|
26
|
+
* payload-less decode (query still running, or empty) is re-fetched on the
|
|
27
|
+
* next access. The cache is size-bounded so a long-lived daemon does not
|
|
28
|
+
* grow it monotonically; eviction is oldest-inserted-first, which for
|
|
29
|
+
* monotonically increasing query ids approximates least-recently-created.
|
|
30
|
+
*/
|
|
21
31
|
private _queryCache;
|
|
32
|
+
/** Upper bound on cached decoded query results. */
|
|
33
|
+
private static readonly QUERY_CACHE_MAX;
|
|
22
34
|
/**
|
|
23
35
|
* Fetches the decoded query result, leveraging a cache to prevent redundant API calls.
|
|
24
36
|
*
|
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.PacsVfsProvider = void 0;
|
|
14
14
|
const cumin_1 = require("@fnndsc/cumin");
|
|
15
|
+
const watch_js_1 = require("../../retrieve/watch.js");
|
|
15
16
|
const sort_js_1 = require("../sort.js");
|
|
16
17
|
const pacsHelpers_js_1 = require("./pacsHelpers.js");
|
|
17
18
|
const index_js_1 = require("../../pacs/index.js");
|
|
@@ -19,28 +20,6 @@ const index_js_2 = require("../../files/index.js");
|
|
|
19
20
|
const path_1 = __importDefault(require("path"));
|
|
20
21
|
const chalk_1 = __importDefault(require("chalk"));
|
|
21
22
|
const pacs_content_js_1 = require("./pacs_content.js");
|
|
22
|
-
/**
|
|
23
|
-
* Resolves the folder path on ChRIS storage for a retrieved series.
|
|
24
|
-
*
|
|
25
|
-
* @param seriesInstanceUID - The Series Instance UID to resolve.
|
|
26
|
-
* @returns Promise resolving to the folder path string or null on failure.
|
|
27
|
-
*/
|
|
28
|
-
async function series_getFolderPath(seriesInstanceUID) {
|
|
29
|
-
const client = await cumin_1.chrisConnection.client_get();
|
|
30
|
-
if (!client) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
const seriesList = await client.getPACSSeriesList({
|
|
34
|
-
SeriesInstanceUID: seriesInstanceUID,
|
|
35
|
-
limit: 1,
|
|
36
|
-
});
|
|
37
|
-
const seriesItems = seriesList.getItems();
|
|
38
|
-
if (!seriesItems || seriesItems.length === 0) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
const series = seriesItems[0];
|
|
42
|
-
return series?.data?.folder_path || null;
|
|
43
|
-
}
|
|
44
23
|
function pacsRoot_list() {
|
|
45
24
|
return (0, cumin_1.Ok)([{ name: "queries", type: "vfs", size: 0, owner: "root", date: new Date().toISOString() }]);
|
|
46
25
|
}
|
|
@@ -126,16 +105,17 @@ function seriesToRetrieve_build(decoded, studyUID, seriesUID, src) {
|
|
|
126
105
|
}
|
|
127
106
|
const seriesArray = (0, pacsHelpers_js_1.series_extractFromStudy)(studyObj);
|
|
128
107
|
const seriesToRetrieve = [];
|
|
108
|
+
const expected_of = (obj) => Number((0, pacsHelpers_js_1.tag_extractValue)(obj?.NumberOfSeriesRelatedInstances ?? 0)) || 0;
|
|
129
109
|
if (seriesUID) {
|
|
130
110
|
const seriesObj = (0, pacsHelpers_js_1.series_findByUID)(seriesArray, seriesUID);
|
|
131
111
|
const desc = seriesObj ? (0, pacsHelpers_js_1.tag_extractValue)(seriesObj.SeriesDescription || "Series") : "Series";
|
|
132
|
-
seriesToRetrieve.push({ uid: seriesUID, description: desc });
|
|
112
|
+
seriesToRetrieve.push({ uid: seriesUID, description: desc, expectedFiles: expected_of(seriesObj) });
|
|
133
113
|
}
|
|
134
114
|
else {
|
|
135
115
|
for (const s of seriesArray) {
|
|
136
116
|
const sUID = (0, pacsHelpers_js_1.tag_extractValue)(s.SeriesInstanceUID || s.uid);
|
|
137
117
|
if (sUID) {
|
|
138
|
-
seriesToRetrieve.push({ uid: sUID, description: (0, pacsHelpers_js_1.tag_extractValue)(s.SeriesDescription || "Series") });
|
|
118
|
+
seriesToRetrieve.push({ uid: sUID, description: (0, pacsHelpers_js_1.tag_extractValue)(s.SeriesDescription || "Series"), expectedFiles: expected_of(s) });
|
|
139
119
|
}
|
|
140
120
|
}
|
|
141
121
|
}
|
|
@@ -156,98 +136,69 @@ async function pacsServer_resolve() {
|
|
|
156
136
|
cumin_1.errorStack.stack_push("error", "cp: No PACS server available or configured in context.");
|
|
157
137
|
return (0, cumin_1.Err)();
|
|
158
138
|
}
|
|
159
|
-
async function
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
anyPulling = true;
|
|
184
|
-
if (ser.status !== "pulled")
|
|
185
|
-
allPulled = false;
|
|
186
|
-
if (ser.status === "error")
|
|
187
|
-
anyError = true;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
139
|
+
async function series_retrieveAndCopy(seriesItem, studyUID, pacsserver, dest, idx, total) {
|
|
140
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.cyan(`\n[PACS Retrieve ${idx + 1}/${total}] Processing series: ${seriesItem.description} (${seriesItem.uid})...`)}\n`);
|
|
141
|
+
const client = await cumin_1.chrisConnection.client_get();
|
|
142
|
+
if (!client) {
|
|
143
|
+
(0, cumin_1.runtimeOutput_err)(`${chalk_1.default.red(" ✗ Not connected to ChRIS.")}\n`);
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
// One retrieve engine for cp and pull alike: bounded, retried firing plus
|
|
147
|
+
// the LONK watch, replacing this provider's former 5-second polling loop.
|
|
148
|
+
const task = (0, watch_js_1.retrieveTask_make)({
|
|
149
|
+
label: seriesItem.description,
|
|
150
|
+
seriesUID: seriesItem.uid,
|
|
151
|
+
studyUID,
|
|
152
|
+
pacsName: pacsserver,
|
|
153
|
+
// The decode's instance count enables the idempotency skip: a series
|
|
154
|
+
// already fully registered in CUBE is copied without refiring.
|
|
155
|
+
expectedFiles: seriesItem.expectedFiles,
|
|
156
|
+
});
|
|
157
|
+
const alreadyThere = await (0, watch_js_1.retrieveTasks_skipComplete)([task]);
|
|
158
|
+
if (alreadyThere === 0) {
|
|
159
|
+
const events = {
|
|
160
|
+
task: (t, status) => {
|
|
161
|
+
if (status === 'running' && t.actualFiles > 0) {
|
|
162
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.gray(` ${t.actualFiles} file(s) received...`)}\n`);
|
|
190
163
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
164
|
+
else if (status === 'error') {
|
|
165
|
+
(0, cumin_1.runtimeOutput_err)(`${chalk_1.default.red(" ✗ PACS retrieve reported an error.")}\n`);
|
|
166
|
+
}
|
|
167
|
+
else if (status === 'stalled' || status === 'timeout') {
|
|
168
|
+
(0, cumin_1.runtimeOutput_err)(`${chalk_1.default.red(` ✗ PACS retrieve ${status}.`)}\n`);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.gray(" -> Firing PACS retrieve and watching progress...")}\n`);
|
|
173
|
+
const firingErrors = await (0, watch_js_1.retrieve_fireAndWatch)([task], pacsserver, client, events);
|
|
174
|
+
if (firingErrors > 0) {
|
|
175
|
+
(0, cumin_1.runtimeOutput_err)(`${chalk_1.default.red(` ✗ Retrieve could not be fired for series ${seriesItem.uid}.`)}\n`);
|
|
176
|
+
return false;
|
|
202
177
|
}
|
|
203
|
-
if (
|
|
204
|
-
console.error(chalk_1.default.red(" ✗ PACS retrieve reported error status."));
|
|
178
|
+
if (task.status !== 'pulled') {
|
|
205
179
|
return false;
|
|
206
180
|
}
|
|
207
181
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const queryPayload = {
|
|
214
|
-
title: `Synthetic cp Query ${seriesItem.uid}`,
|
|
215
|
-
query: JSON.stringify({ SeriesInstanceUID: seriesItem.uid, StudyInstanceUID: studyUID }),
|
|
216
|
-
execute: false,
|
|
217
|
-
};
|
|
218
|
-
console.log(chalk_1.default.gray(" -> Registering synthetic query on CUBE..."));
|
|
219
|
-
const queryResult = await (0, index_js_1.pacsQueries_create)(pacsserver, queryPayload);
|
|
220
|
-
if (!queryResult.ok) {
|
|
221
|
-
console.error(chalk_1.default.red(` ✗ Failed to create synthetic query for series ${seriesItem.uid}`));
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
const syntheticQueryId = queryResult.value.id;
|
|
225
|
-
console.log(chalk_1.default.gray(` -> Triggering PACS retrieve (Query ID: ${syntheticQueryId})...`));
|
|
226
|
-
const retrieveResult = await (0, index_js_1.pacsRetrieve_create)(syntheticQueryId);
|
|
227
|
-
if (!retrieveResult.ok) {
|
|
228
|
-
console.error(chalk_1.default.red(` ✗ Failed to create PACS retrieve for query ${syntheticQueryId}`));
|
|
229
|
-
return false;
|
|
182
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.gray(" -> Finding folder path on ChRIS storage...")}\n`);
|
|
183
|
+
let folderPath = task.cubePathDir;
|
|
184
|
+
if (folderPath === null) {
|
|
185
|
+
const stateResult = await (0, cumin_1.seriesStorage_resolve)(seriesItem.uid, { attempts: 4, delayMs: 2_000 });
|
|
186
|
+
folderPath = stateResult.ok ? stateResult.value.folderPath : null;
|
|
230
187
|
}
|
|
231
|
-
console.log(chalk_1.default.gray(" -> Pulling series data sequentially, polling progress..."));
|
|
232
|
-
const finished = await retrieve_pollUntilComplete(syntheticQueryId, seriesItem.uid, 60);
|
|
233
|
-
if (!finished)
|
|
234
|
-
return false;
|
|
235
|
-
console.log(chalk_1.default.gray(" -> Finding folder path on ChRIS storage..."));
|
|
236
|
-
const folderPath = await series_getFolderPath(seriesItem.uid);
|
|
237
188
|
if (!folderPath) {
|
|
238
|
-
|
|
189
|
+
(0, cumin_1.runtimeOutput_err)(`${chalk_1.default.red(` ✗ No registered folder path found for series UID ${seriesItem.uid}`)}\n`);
|
|
239
190
|
return false;
|
|
240
191
|
}
|
|
241
192
|
const absoluteFolderPath = folderPath.startsWith("/") ? folderPath : "/" + folderPath;
|
|
242
193
|
const cleanDesc = seriesItem.description.replace(/[\s/]/g, "_");
|
|
243
194
|
const targetSeriesFolder = path_1.default.posix.join(dest, `Series_${seriesItem.uid}_${cleanDesc}`);
|
|
244
|
-
|
|
195
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.gray(` -> Copying series files to '${targetSeriesFolder}'...`)}\n`);
|
|
245
196
|
const copySuccess = await (0, index_js_2.files_copyRecursively)(absoluteFolderPath, targetSeriesFolder);
|
|
246
197
|
if (!copySuccess) {
|
|
247
|
-
|
|
198
|
+
(0, cumin_1.runtimeOutput_err)(`${chalk_1.default.red(` ✗ Recursive copy failed from '${absoluteFolderPath}' to '${targetSeriesFolder}'`)}\n`);
|
|
248
199
|
return false;
|
|
249
200
|
}
|
|
250
|
-
|
|
201
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.green(` ✓ Series '${seriesItem.description}' copied successfully.`)}\n`);
|
|
251
202
|
return true;
|
|
252
203
|
}
|
|
253
204
|
/**
|
|
@@ -256,8 +207,20 @@ async function series_retrieveAndCopy(seriesItem, studyUID, pacsserver, dest, id
|
|
|
256
207
|
class PacsVfsProvider {
|
|
257
208
|
/** Prefix matches /net/pacs and subdirectories. */
|
|
258
209
|
prefix = "/net/pacs";
|
|
259
|
-
/**
|
|
210
|
+
/**
|
|
211
|
+
* Cache for decoded PACS query results to avoid redundant API hits.
|
|
212
|
+
*
|
|
213
|
+
* Contract (see docs/code-audit-2026-08.adoc, cache inventory): only a
|
|
214
|
+
* settled result — one carrying a structured `json` payload — is cached,
|
|
215
|
+
* since a query's payload is written once and never mutates afterwards; a
|
|
216
|
+
* payload-less decode (query still running, or empty) is re-fetched on the
|
|
217
|
+
* next access. The cache is size-bounded so a long-lived daemon does not
|
|
218
|
+
* grow it monotonically; eviction is oldest-inserted-first, which for
|
|
219
|
+
* monotonically increasing query ids approximates least-recently-created.
|
|
220
|
+
*/
|
|
260
221
|
_queryCache = new Map();
|
|
222
|
+
/** Upper bound on cached decoded query results. */
|
|
223
|
+
static QUERY_CACHE_MAX = 100;
|
|
261
224
|
/**
|
|
262
225
|
* Fetches the decoded query result, leveraging a cache to prevent redundant API calls.
|
|
263
226
|
*
|
|
@@ -273,7 +236,17 @@ class PacsVfsProvider {
|
|
|
273
236
|
if (!decodedResult.ok || !decodedResult.value) {
|
|
274
237
|
return null;
|
|
275
238
|
}
|
|
276
|
-
|
|
239
|
+
// Cache settled results only: a decode without a structured payload may
|
|
240
|
+
// be a still-running query whose payload arrives later, and caching it
|
|
241
|
+
// would pin the empty view for the life of the process.
|
|
242
|
+
if (decodedResult.value.json !== undefined && decodedResult.value.json !== null) {
|
|
243
|
+
if (this._queryCache.size >= PacsVfsProvider.QUERY_CACHE_MAX) {
|
|
244
|
+
const oldest = this._queryCache.keys().next().value;
|
|
245
|
+
if (oldest !== undefined)
|
|
246
|
+
this._queryCache.delete(oldest);
|
|
247
|
+
}
|
|
248
|
+
this._queryCache.set(queryId, decodedResult.value);
|
|
249
|
+
}
|
|
277
250
|
return decodedResult.value;
|
|
278
251
|
}
|
|
279
252
|
/**
|
|
@@ -309,16 +282,22 @@ class PacsVfsProvider {
|
|
|
309
282
|
return studies_list(studies, options);
|
|
310
283
|
const studyUID = parts[4].replace(/^Study_/, "").split("_")[0];
|
|
311
284
|
const studyObj = (0, pacsHelpers_js_1.study_findByUID)(studies, studyUID);
|
|
312
|
-
|
|
313
|
-
|
|
285
|
+
// A missing UID is "no such directory", never an empty one: rendering
|
|
286
|
+
// not-found as an empty listing hides typos and stale paths entirely.
|
|
287
|
+
if (!studyObj) {
|
|
288
|
+
cumin_1.errorStack.stack_push("error", `'${effectivePath}': No such study in query ${queryId}. Use 'ls' on the query directory to see available studies.`);
|
|
289
|
+
return (0, cumin_1.Err)();
|
|
290
|
+
}
|
|
314
291
|
const seriesArr = (0, pacsHelpers_js_1.series_extractFromStudy)(studyObj);
|
|
315
292
|
if (parts.length === 5)
|
|
316
293
|
return series_list(seriesArr, options);
|
|
317
294
|
if (parts.length === 6) {
|
|
318
295
|
const seriesUID = parts[5].replace(/^Series_/, "").split("_")[0];
|
|
319
296
|
const seriesObj = (0, pacsHelpers_js_1.series_findByUID)(seriesArr, seriesUID);
|
|
320
|
-
if (!seriesObj)
|
|
321
|
-
|
|
297
|
+
if (!seriesObj) {
|
|
298
|
+
cumin_1.errorStack.stack_push("error", `'${effectivePath}': No such series in study ${studyUID}.`);
|
|
299
|
+
return (0, cumin_1.Err)();
|
|
300
|
+
}
|
|
322
301
|
return seriesFiles_list(seriesObj);
|
|
323
302
|
}
|
|
324
303
|
return (0, cumin_1.Ok)([]);
|
|
@@ -355,7 +334,7 @@ class PacsVfsProvider {
|
|
|
355
334
|
if (!serverResult.ok)
|
|
356
335
|
return false;
|
|
357
336
|
const pacsserver = serverResult.value;
|
|
358
|
-
|
|
337
|
+
(0, cumin_1.runtimeOutput_data)(`${chalk_1.default.cyan(`[PACS Retrieve] Initiating sequential gather of ${seriesToRetrieve.length} series...`)}\n`);
|
|
359
338
|
let overallSuccess = true;
|
|
360
339
|
for (let i = 0; i < seriesToRetrieve.length; i++) {
|
|
361
340
|
const ok = await series_retrieveAndCopy(seriesToRetrieve[i], studyUID, pacsserver, dest, i, seriesToRetrieve.length);
|