@fnndsc/chili 3.2.5 → 3.3.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 +18 -11
- package/dist/commands/man/doc.js +1 -1
- package/dist/commands/plugin/readme.js +3 -0
- package/dist/filesystem/fileGroupHandler.d.ts +0 -5
- package/dist/filesystem/fileGroupHandler.js +2 -19
- package/dist/handlers/baseGroupHandler.d.ts +0 -7
- package/dist/handlers/baseGroupHandler.js +2 -21
- package/dist/index.d.ts +6 -1
- package/dist/index.js +13 -179
- package/dist/man/renderer.d.ts +1 -1
- package/dist/man/renderer.js +6 -8
- package/dist/path/pathCommand.js +6 -3
- package/dist/run.d.ts +24 -0
- package/dist/run.js +192 -0
- package/dist/utils/resourceData.d.ts +16 -0
- package/dist/utils/resourceData.js +23 -0
- package/package.json +6 -8
package/README.md
CHANGED
|
@@ -42,27 +42,34 @@ Designed for developers and power-users who want to script and control a ChRIS i
|
|
|
42
42
|
2. **[`salsa`](https://github.com/FNNDSC/salsa) (Logic)**: Shared Application Logic and Service Assets — high-level business intents.
|
|
43
43
|
3. **[`cumin`](https://github.com/FNNDSC/cumin) (Infrastructure)**: State and connection layer — authentication, context persistence, low-level API.
|
|
44
44
|
|
|
45
|
-
##
|
|
45
|
+
## Development
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
`chili` lives in the [`mise` monorepo](https://github.com/FNNDSC/mise) alongside
|
|
48
|
+
`cumin`, `salsa`, and `chell`. Build the whole stack from the repository root —
|
|
49
|
+
npm workspaces links the four packages together, so there is nothing to clone or
|
|
50
|
+
hand-link:
|
|
48
51
|
|
|
49
52
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
git clone https://github.com/FNNDSC/mise
|
|
54
|
+
cd mise
|
|
55
|
+
make taco # scrub → prep → cook → taste → serve (the full course)
|
|
52
56
|
```
|
|
53
57
|
|
|
54
|
-
### Individual steps
|
|
58
|
+
### Individual steps (run from the repo root)
|
|
55
59
|
|
|
56
60
|
| Target | Action |
|
|
57
61
|
|--------|--------|
|
|
58
|
-
| `make
|
|
59
|
-
| `make
|
|
60
|
-
| `make
|
|
61
|
-
| `make
|
|
62
|
-
| `make serve` | Link packages globally |
|
|
62
|
+
| `make prep` | `npm install` — install deps and link all four workspaces |
|
|
63
|
+
| `make cook` | Build (compile TypeScript) all packages in dependency order |
|
|
64
|
+
| `make taste` | Run the full test suite |
|
|
65
|
+
| `make serve` | Link `chell` globally |
|
|
63
66
|
| `make scrub` | Clean build artifacts and `node_modules` |
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
To build or test just this package: `npm run build -w @fnndsc/chili` /
|
|
69
|
+
`npm test -w @fnndsc/chili`.
|
|
70
|
+
|
|
71
|
+
> Use [NVM](https://github.com/nvm-sh/nvm) and Node 22.x to avoid needing `sudo`
|
|
72
|
+
> for the global link in `make serve`.
|
|
66
73
|
|
|
67
74
|
## Core Features
|
|
68
75
|
|
package/dist/commands/man/doc.js
CHANGED
|
@@ -11,6 +11,9 @@ import { marked } from "marked";
|
|
|
11
11
|
import TerminalRenderer from "marked-terminal";
|
|
12
12
|
import chalk from "chalk";
|
|
13
13
|
marked.setOptions({
|
|
14
|
+
// @ts-expect-error marked-terminal@6 ships .d.ts that drift from marked@9's
|
|
15
|
+
// Renderer type at this runtime-compatible version pair. (Tracked: align the
|
|
16
|
+
// marked / marked-terminal versions across chili & chell.)
|
|
14
17
|
renderer: new TerminalRenderer({
|
|
15
18
|
code: chalk.yellow,
|
|
16
19
|
blockquote: chalk.gray.italic,
|
|
@@ -25,11 +25,6 @@ export declare class FileGroupHandler {
|
|
|
25
25
|
* @returns A Promise resolving to a new FileGroupHandler instance.
|
|
26
26
|
*/
|
|
27
27
|
static handler_create(assetName: string, path?: string): Promise<FileGroupHandler>;
|
|
28
|
-
/**
|
|
29
|
-
* Removes duplicate column headers from FilteredResourceData results.
|
|
30
|
-
* Copied from BaseGroupHandler to support local listing logic.
|
|
31
|
-
*/
|
|
32
|
-
private columns_removeDuplicates;
|
|
33
28
|
/**
|
|
34
29
|
* Lists files, links, or directories using the new command logic.
|
|
35
30
|
*/
|
|
@@ -4,6 +4,7 @@ import { path_resolveChrisFs } from "../utils/cli.js";
|
|
|
4
4
|
import { FileController } from "../controllers/fileController.js";
|
|
5
5
|
import { files_create } from "../commands/fs/create.js";
|
|
6
6
|
import { errorStack } from "@fnndsc/cumin";
|
|
7
|
+
import { resourceColumns_removeDuplicates } from "../utils/resourceData.js";
|
|
7
8
|
import { table_display } from "../screen/screen.js";
|
|
8
9
|
import { files_fetchList } from "../commands/files/list.js";
|
|
9
10
|
import { fileFields_fetch } from "../commands/files/fields.js";
|
|
@@ -41,24 +42,6 @@ export class FileGroupHandler {
|
|
|
41
42
|
throw new Error(`Failed to initialize FileGroupHandler for ${assetName}: ${errorMessage}`);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Removes duplicate column headers from FilteredResourceData results.
|
|
46
|
-
* Copied from BaseGroupHandler to support local listing logic.
|
|
47
|
-
*/
|
|
48
|
-
columns_removeDuplicates(results) {
|
|
49
|
-
const uniqueHeaders = Array.from(new Set(results.selectedFields));
|
|
50
|
-
const uniqueTableData = results.tableData.map((row) => uniqueHeaders.reduce((acc, header) => {
|
|
51
|
-
if (typeof header === "string" && header in row) {
|
|
52
|
-
acc[header] = row[header];
|
|
53
|
-
}
|
|
54
|
-
return acc;
|
|
55
|
-
}, {}));
|
|
56
|
-
return {
|
|
57
|
-
...results,
|
|
58
|
-
selectedFields: uniqueHeaders,
|
|
59
|
-
tableData: uniqueTableData,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
45
|
/**
|
|
63
46
|
* Lists files, links, or directories using the new command logic.
|
|
64
47
|
*/
|
|
@@ -73,7 +56,7 @@ export class FileGroupHandler {
|
|
|
73
56
|
console.log(`No ${this.assetName} found matching the criteria.`);
|
|
74
57
|
}
|
|
75
58
|
else {
|
|
76
|
-
const uniqueResults =
|
|
59
|
+
const uniqueResults = resourceColumns_removeDuplicates(results);
|
|
77
60
|
// cumin returns dynamic table rows (Record<string, unknown>[]);
|
|
78
61
|
// narrow to the FileResource view model at this boundary.
|
|
79
62
|
console.log(fileList_render(uniqueResults.tableData, uniqueResults.selectedFields, { table: options.table, csv: options.csv }));
|
|
@@ -16,13 +16,6 @@ export declare class BaseGroupHandler {
|
|
|
16
16
|
displayOptions: TableOptions;
|
|
17
17
|
chrisObject: ChRISPluginGroup | ChRISFeedGroup | ChRISEmbeddedResourceGroup<unknown> | ChRISPACSGroup;
|
|
18
18
|
constructor(assetName: string, chrisObject: ChRISPluginGroup | ChRISFeedGroup | ChRISEmbeddedResourceGroup<unknown> | ChRISPACSGroup);
|
|
19
|
-
/**
|
|
20
|
-
* Removes duplicate column headers from FilteredResourceData results.
|
|
21
|
-
*
|
|
22
|
-
* @param results - The FilteredResourceData to process.
|
|
23
|
-
* @returns FilteredResourceData with unique headers and corresponding data.
|
|
24
|
-
*/
|
|
25
|
-
private columns_removeDuplicates;
|
|
26
19
|
/**
|
|
27
20
|
* Lists ChRIS resources based on provided CLI options.
|
|
28
21
|
*
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
import { ChRISFeedGroup, record_extract, errorStack, } from "@fnndsc/cumin";
|
|
8
8
|
import { options_toParams } from "../utils/cli.js";
|
|
9
|
+
import { resourceColumns_removeDuplicates } from "../utils/resourceData.js";
|
|
9
10
|
import { table_display, border_draw } from "../screen/screen.js";
|
|
10
11
|
import * as readline from "readline";
|
|
11
12
|
/**
|
|
@@ -21,26 +22,6 @@ export class BaseGroupHandler {
|
|
|
21
22
|
title: { title: this.assetName, justification: "center" },
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Removes duplicate column headers from FilteredResourceData results.
|
|
26
|
-
*
|
|
27
|
-
* @param results - The FilteredResourceData to process.
|
|
28
|
-
* @returns FilteredResourceData with unique headers and corresponding data.
|
|
29
|
-
*/
|
|
30
|
-
columns_removeDuplicates(results) {
|
|
31
|
-
const uniqueHeaders = Array.from(new Set(results.selectedFields));
|
|
32
|
-
const uniqueTableData = results.tableData.map((row) => uniqueHeaders.reduce((acc, header) => {
|
|
33
|
-
if (typeof header === "string" && header in row) {
|
|
34
|
-
acc[header] = row[header];
|
|
35
|
-
}
|
|
36
|
-
return acc;
|
|
37
|
-
}, {}));
|
|
38
|
-
return {
|
|
39
|
-
...results,
|
|
40
|
-
selectedFields: uniqueHeaders,
|
|
41
|
-
tableData: uniqueTableData,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
25
|
/**
|
|
45
26
|
* Lists ChRIS resources based on provided CLI options.
|
|
46
27
|
*
|
|
@@ -77,7 +58,7 @@ export class BaseGroupHandler {
|
|
|
77
58
|
console.log(`No ${this.assetName} found matching the criteria.`);
|
|
78
59
|
}
|
|
79
60
|
else {
|
|
80
|
-
const uniqueResults =
|
|
61
|
+
const uniqueResults = resourceColumns_removeDuplicates(results);
|
|
81
62
|
// Construct column options based on parsed widths
|
|
82
63
|
const columns = uniqueResults.selectedFields.map(field => {
|
|
83
64
|
const width = columnWidths[field];
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @file Command-line entry point for the chili (ChILI) CLI.
|
|
4
4
|
*
|
|
5
|
+
* This is a thin wrapper: all command wiring and execution live in {@link run}
|
|
6
|
+
* (./run.js) so the same logic can be driven in-process by a host such as chell
|
|
7
|
+
* without spawning a separate `node` subprocess. This file only adds the
|
|
8
|
+
* bin-only concerns — shell completion and fatal-exit handling.
|
|
9
|
+
*
|
|
5
10
|
* @module
|
|
6
11
|
*/
|
|
7
|
-
export { logical_toPhysical } from
|
|
12
|
+
export { logical_toPhysical } from "./utils/cli.js";
|
package/dist/index.js
CHANGED
|
@@ -2,62 +2,18 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @file Command-line entry point for the chili (ChILI) CLI.
|
|
4
4
|
*
|
|
5
|
-
* @
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* This warning originates from the `proxy-from-env` package (version 1.1.0)
|
|
11
|
-
* used by axios for proxy configuration. The package uses the legacy `url.parse()`
|
|
12
|
-
* API which is deprecated in favor of the WHATWG URL API.
|
|
5
|
+
* This is a thin wrapper: all command wiring and execution live in {@link run}
|
|
6
|
+
* (./run.js) so the same logic can be driven in-process by a host such as chell
|
|
7
|
+
* without spawning a separate `node` subprocess. This file only adds the
|
|
8
|
+
* bin-only concerns — shell completion and fatal-exit handling.
|
|
13
9
|
*
|
|
14
|
-
*
|
|
15
|
-
* - It's a transitive dependency (axios → proxy-from-env) we don't control
|
|
16
|
-
* - proxy-from-env 1.1.0 is the latest version and hasn't been updated
|
|
17
|
-
* - According to the warning: "CVEs are not issued for url.parse() vulnerabilities"
|
|
18
|
-
* - The warning doesn't affect functionality, only console output
|
|
19
|
-
* - This is a well-known issue in the Node.js ecosystem
|
|
20
|
-
*
|
|
21
|
-
* This can be removed once:
|
|
22
|
-
* - proxy-from-env migrates to WHATWG URL API, OR
|
|
23
|
-
* - axios replaces proxy-from-env with an alternative
|
|
24
|
-
*
|
|
25
|
-
* Tracking: https://github.com/Rob--W/proxy-from-env/issues/51
|
|
10
|
+
* @module
|
|
26
11
|
*/
|
|
27
|
-
const originalEmitWarning = process.emitWarning;
|
|
28
|
-
process.emitWarning = function (warning, ...args) {
|
|
29
|
-
// Suppress only the specific DEP0169 warning
|
|
30
|
-
if (typeof warning === 'string' &&
|
|
31
|
-
(warning.includes('DEP0169') || warning.includes('url.parse()'))) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
// Allow all other warnings through
|
|
35
|
-
return originalEmitWarning.call(process, warning, ...args);
|
|
36
|
-
};
|
|
37
|
-
import { Command } from "commander";
|
|
38
|
-
import figlet from "figlet";
|
|
39
12
|
import omelette from "omelette";
|
|
40
|
-
import {
|
|
41
|
-
import { FeedGroupHandler, FeedMemberHandler } from "./feeds/feedHandler.js";
|
|
42
|
-
import { PluginGroupHandler, PluginMemberHandler, } from "./plugins/pluginHandler.js";
|
|
43
|
-
import { PluginMetaGroupHandler } from "./plugins/pluginMetaHandler.js";
|
|
44
|
-
import { PluginContextGroupHandler } from "./plugins/pluginGroupHandler.js";
|
|
45
|
-
import { inodeCommand_setup } from "./filesystem/inodeCommand.js";
|
|
46
|
-
import { contextCommand_setup } from "./context/contextCommand.js";
|
|
47
|
-
import { pathCommand_setup } from "./path/pathCommand.js";
|
|
48
|
-
import { fileBrowserCommand_setup } from "./filesystem/filesystemHandler.js";
|
|
49
|
-
import { manCommand_setup } from "./man/man.js";
|
|
50
|
-
import { chefsCommand_setup } from "./chefs/chefs.js";
|
|
51
|
-
import { PACSServerGroupHandler } from "./pacs/pacsServerHandler.js";
|
|
52
|
-
import { PACSQueryGroupHandler } from "./pacs/pacsQueryHandler.js";
|
|
53
|
-
import { PACSRetrieveGroupHandler } from "./pacs/pacsRetrieveHandler.js";
|
|
54
|
-
import { chrisConnection_init, NodeStorageProvider, errorStack_getAllOfType } from "@fnndsc/cumin";
|
|
55
|
-
import { FileGroupHandler } from "./filesystem/fileGroupHandler.js";
|
|
56
|
-
const program = new Command();
|
|
57
|
-
program.version("1.0.1").description("A CLI for ChRIS");
|
|
13
|
+
import { run } from "./run.js";
|
|
58
14
|
/**
|
|
59
|
-
* Sets up command completion for the
|
|
60
|
-
* This
|
|
15
|
+
* Sets up shell command completion for the standalone chili CLI using omelette.
|
|
16
|
+
* This is a bin-only concern; in-process hosts provide their own completion.
|
|
61
17
|
*/
|
|
62
18
|
function commandCompletion_setup() {
|
|
63
19
|
const completion = omelette(`chili|chili`);
|
|
@@ -95,7 +51,6 @@ function commandCompletion_setup() {
|
|
|
95
51
|
});
|
|
96
52
|
completion.on("man.doc", ({ reply }) => {
|
|
97
53
|
console.log("Autocomplete triggered for man doc command");
|
|
98
|
-
// We'll implement actual topic retrieval here later
|
|
99
54
|
reply([]);
|
|
100
55
|
});
|
|
101
56
|
completion.init();
|
|
@@ -104,136 +59,15 @@ function commandCompletion_setup() {
|
|
|
104
59
|
}
|
|
105
60
|
}
|
|
106
61
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* @param program - The Commander.js program instance.
|
|
110
|
-
*/
|
|
111
|
-
async function handlers_initialize() {
|
|
112
|
-
// const client = await chrisConnection.client_get();
|
|
113
|
-
// We don't enforce connection here to allow --help to work.
|
|
114
|
-
// Commands will fail individually if not connected.
|
|
115
|
-
fileBrowserCommand_setup(program);
|
|
116
|
-
contextCommand_setup(program);
|
|
117
|
-
pathCommand_setup(program);
|
|
118
|
-
manCommand_setup(program);
|
|
119
|
-
chefsCommand_setup(program);
|
|
120
|
-
const pacsServerHandler = new PACSServerGroupHandler();
|
|
121
|
-
pacsServerHandler.pacsServerCommand_setup(program);
|
|
122
|
-
const pacsQueryHandler = new PACSQueryGroupHandler();
|
|
123
|
-
pacsQueryHandler.pacsQueryCommand_setup(program);
|
|
124
|
-
const pacsRetrieveHandler = new PACSRetrieveGroupHandler();
|
|
125
|
-
pacsRetrieveHandler.pacsRetrieveCommand_setup(program);
|
|
126
|
-
await inodeCommand_setup(program);
|
|
127
|
-
const pluginGroupHandler = new PluginGroupHandler();
|
|
128
|
-
pluginGroupHandler.pluginGroupCommand_setup(program);
|
|
129
|
-
const pluginMetaGroupHandler = new PluginMetaGroupHandler();
|
|
130
|
-
pluginMetaGroupHandler.pluginMetaGroupCommand_setup(program);
|
|
131
|
-
const feedGroupHandler = new FeedGroupHandler();
|
|
132
|
-
feedGroupHandler.feedGroupCommand_setup(program);
|
|
133
|
-
const feedMemberHandler = new FeedMemberHandler();
|
|
134
|
-
feedMemberHandler.feedCommand_setup(program);
|
|
135
|
-
const pluginMemberHandler = new PluginMemberHandler();
|
|
136
|
-
pluginMemberHandler.pluginCommand_setup(program);
|
|
137
|
-
try {
|
|
138
|
-
const filesGroupHandler = await FileGroupHandler.handler_create("files");
|
|
139
|
-
filesGroupHandler.fileGroupCommand_setup(program);
|
|
140
|
-
const linksGroupHandler = await FileGroupHandler.handler_create("links");
|
|
141
|
-
linksGroupHandler.fileGroupCommand_setup(program);
|
|
142
|
-
const dirsGroupHandler = await FileGroupHandler.handler_create("dirs");
|
|
143
|
-
dirsGroupHandler.fileGroupCommand_setup(program);
|
|
144
|
-
}
|
|
145
|
-
catch (e) {
|
|
146
|
-
const err = e instanceof Error ? e.message : String(e);
|
|
147
|
-
const errors = errorStack_getAllOfType("error");
|
|
148
|
-
const warnings = errorStack_getAllOfType("warning");
|
|
149
|
-
console.log(`Note: File group commands (files, dirs, links) are unavailable. Reason: ${err}`);
|
|
150
|
-
if (errors.length > 0) {
|
|
151
|
-
console.log("Errors:");
|
|
152
|
-
errors.forEach(msg => console.log(` - ${msg}`));
|
|
153
|
-
}
|
|
154
|
-
if (warnings.length > 0) {
|
|
155
|
-
console.log("Warnings:");
|
|
156
|
-
warnings.forEach(msg => console.log(` - ${msg}`));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
try {
|
|
160
|
-
const computesOfPluginHandler = await PluginContextGroupHandler.handler_create("computesofplugin");
|
|
161
|
-
computesOfPluginHandler.pluginContextGroupCommand_setup(program);
|
|
162
|
-
const pluginInstancesHandler = await PluginContextGroupHandler.handler_create("instancesofplugin");
|
|
163
|
-
pluginInstancesHandler.pluginContextGroupCommand_setup(program);
|
|
164
|
-
const pluginParametersHandler = await PluginContextGroupHandler.handler_create("parametersofplugin");
|
|
165
|
-
pluginParametersHandler.pluginContextGroupCommand_setup(program);
|
|
166
|
-
}
|
|
167
|
-
catch (e) {
|
|
168
|
-
const err = e instanceof Error ? e.message : String(e);
|
|
169
|
-
const errors = errorStack_getAllOfType("error");
|
|
170
|
-
const warnings = errorStack_getAllOfType("warning");
|
|
171
|
-
console.log(`Note: Plugin context commands are unavailable. Reason: ${err}`);
|
|
172
|
-
if (errors.length > 0) {
|
|
173
|
-
console.log("Errors:");
|
|
174
|
-
errors.forEach(msg => console.log(` - ${msg}`));
|
|
175
|
-
}
|
|
176
|
-
if (warnings.length > 0) {
|
|
177
|
-
console.log("Warnings:");
|
|
178
|
-
warnings.forEach(msg => console.log(` - ${msg}`));
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
commandCompletion_setup();
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Parses the command line arguments to extract context information.
|
|
185
|
-
*
|
|
186
|
-
* @param args - The command line arguments array (process.argv).
|
|
187
|
-
* @returns A tuple containing the context string (if found) and the remaining arguments.
|
|
188
|
-
*/
|
|
189
|
-
function context_parse(args) {
|
|
190
|
-
// Find the first argument that looks like a context string (contains "=" but doesn't start with "-")
|
|
191
|
-
for (let i = 2; i < args.length; i++) {
|
|
192
|
-
const arg = args[i];
|
|
193
|
-
if (arg.includes("=") && !arg.startsWith("-")) {
|
|
194
|
-
const context = arg;
|
|
195
|
-
// Reconstruct args without the context string
|
|
196
|
-
const newArgs = [...args.slice(0, i), ...args.slice(i + 1)];
|
|
197
|
-
return [context, newArgs];
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return [undefined, args];
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Main function to run the ChILI CLI.
|
|
204
|
-
* Handles initialization, context parsing, and command execution.
|
|
62
|
+
* Bin entry: register shell completion, then run the requested chili command.
|
|
205
63
|
*/
|
|
206
64
|
async function main() {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const [context, newArgs] = context_parse(process.argv);
|
|
210
|
-
if (context) {
|
|
211
|
-
const contextSetSuccess = await connection.context_set(context);
|
|
212
|
-
if (!contextSetSuccess) {
|
|
213
|
-
console.error("Failed to set context. Exiting.");
|
|
214
|
-
process.exit(1);
|
|
215
|
-
}
|
|
216
|
-
process.argv = newArgs;
|
|
217
|
-
}
|
|
218
|
-
program
|
|
219
|
-
.name("chili")
|
|
220
|
-
.description("ChILI handles Intelligent Line Interactions")
|
|
221
|
-
.option("-v, --verbose", "enable verbose output")
|
|
222
|
-
.option("-c, --config <path>", "path to config file")
|
|
223
|
-
.option("-s, --nosplash", "disable splash screen");
|
|
224
|
-
connectCommand_setup(program);
|
|
225
|
-
await handlers_initialize(); // Call handlers_initialize here
|
|
226
|
-
program.parseOptions(process.argv);
|
|
227
|
-
const options = program.opts();
|
|
228
|
-
if (!options.nosplash) {
|
|
229
|
-
console.log(figlet.textSync("ChILI"));
|
|
230
|
-
console.log("ChILI handles Intelligent Line Interactions");
|
|
231
|
-
}
|
|
232
|
-
program.parse(process.argv);
|
|
65
|
+
commandCompletion_setup();
|
|
66
|
+
await run(process.argv.slice(2));
|
|
233
67
|
}
|
|
234
68
|
main().catch((error) => {
|
|
235
69
|
console.error("An error occurred:", error);
|
|
236
70
|
process.exit(1);
|
|
237
71
|
});
|
|
238
|
-
//
|
|
239
|
-
export { logical_toPhysical } from
|
|
72
|
+
// Re-export library utilities for consumers that import the package root.
|
|
73
|
+
export { logical_toPhysical } from "./utils/cli.js";
|
package/dist/man/renderer.d.ts
CHANGED
|
@@ -23,4 +23,4 @@ export declare function asciidoc_render(content: string, style: "figlet" | "asci
|
|
|
23
23
|
*
|
|
24
24
|
* @param filePath - The path to the file to open.
|
|
25
25
|
*/
|
|
26
|
-
export declare function browser_open(filePath: string): void
|
|
26
|
+
export declare function browser_open(filePath: string): Promise<void>;
|
package/dist/man/renderer.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import fs from "fs";
|
|
7
7
|
import path from "path";
|
|
8
8
|
import chalk from "chalk";
|
|
9
|
-
import
|
|
9
|
+
import { convert as adoc_convert } from "asciidoctor";
|
|
10
10
|
import { exec } from "child_process";
|
|
11
11
|
import os from "os";
|
|
12
12
|
const headingStyles = [
|
|
@@ -63,9 +63,8 @@ export function projectDir_get() {
|
|
|
63
63
|
* @param content - The AsciiDoc content string.
|
|
64
64
|
* @returns The converted HTML string.
|
|
65
65
|
*/
|
|
66
|
-
function adoc_htmlConvert(content) {
|
|
67
|
-
|
|
68
|
-
let result = ascii.convert(content, {
|
|
66
|
+
async function adoc_htmlConvert(content) {
|
|
67
|
+
let result = await adoc_convert(content, {
|
|
69
68
|
standalone: false,
|
|
70
69
|
attributes: {
|
|
71
70
|
showtitle: "",
|
|
@@ -107,7 +106,7 @@ function text_wrap(text, width) {
|
|
|
107
106
|
* @returns A Promise resolving to the formatted string.
|
|
108
107
|
*/
|
|
109
108
|
export async function asciidoc_render(content, style, width) {
|
|
110
|
-
let result = adoc_htmlConvert(content);
|
|
109
|
+
let result = await adoc_htmlConvert(content);
|
|
111
110
|
function ASCII_create(text, style) {
|
|
112
111
|
const transformedText = style.textTransform(text);
|
|
113
112
|
return style.color(transformedText);
|
|
@@ -159,12 +158,11 @@ export async function asciidoc_render(content, style, width) {
|
|
|
159
158
|
*
|
|
160
159
|
* @param filePath - The path to the file to open.
|
|
161
160
|
*/
|
|
162
|
-
export function browser_open(filePath) {
|
|
163
|
-
const ascii = asciidoctor();
|
|
161
|
+
export async function browser_open(filePath) {
|
|
164
162
|
const tempHtmlPath = path.join(os.tmpdir(), path.basename(filePath).replace(".adoc", ".html"));
|
|
165
163
|
try {
|
|
166
164
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
167
|
-
const html =
|
|
165
|
+
const html = await adoc_convert(content, {
|
|
168
166
|
safe: "safe",
|
|
169
167
|
standalone: true,
|
|
170
168
|
attributes: { showtitle: true },
|
package/dist/path/pathCommand.js
CHANGED
|
@@ -13,7 +13,7 @@ import { table_display, border_draw } from "../screen/screen.js";
|
|
|
13
13
|
import { options_toParams } from "../utils/cli.js";
|
|
14
14
|
import archy from "archy";
|
|
15
15
|
import open from "open";
|
|
16
|
-
import {
|
|
16
|
+
import { execFile } from "child_process";
|
|
17
17
|
import os from "os";
|
|
18
18
|
import { files_downloadWithProgress } from "../commands/fs/download.js";
|
|
19
19
|
/**
|
|
@@ -160,10 +160,13 @@ async function mermaid_renderServerSide(mermaidDefinition, outputFile) {
|
|
|
160
160
|
const tempDir = os.tmpdir();
|
|
161
161
|
const inputFile = path.join(tempDir, "input.mmd");
|
|
162
162
|
fs.writeFileSync(inputFile, mermaidDefinition);
|
|
163
|
+
// Pass args as an array (execFile, no shell) so a user-supplied --save path
|
|
164
|
+
// cannot inject shell commands. Requires `mmdc` (@mermaid-js/mermaid-cli),
|
|
165
|
+
// which is fetched on demand via npx and is not a hard dependency.
|
|
163
166
|
return new Promise((resolve, reject) => {
|
|
164
|
-
|
|
167
|
+
execFile("npx", ["mmdc", "-i", inputFile, "-o", outputFile], (error) => {
|
|
165
168
|
if (error) {
|
|
166
|
-
console.error(`
|
|
169
|
+
console.error(`Mermaid render failed. Ensure @mermaid-js/mermaid-cli is available (npx mmdc): ${error.message}`);
|
|
167
170
|
reject(error);
|
|
168
171
|
return;
|
|
169
172
|
}
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file In-process library entry for the chili (ChILI) CLI.
|
|
3
|
+
*
|
|
4
|
+
* Exposes {@link run}, which builds a fresh Commander program and executes a
|
|
5
|
+
* single chili command, returning when it completes. Unlike the bin entry
|
|
6
|
+
* (`index.ts`), importing this module has no side effect of running the CLI and
|
|
7
|
+
* never calls `process.exit`, so a host process such as chell can drive chili
|
|
8
|
+
* in-process instead of spawning a separate `node` subprocess.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Executes a single chili command in the current process.
|
|
14
|
+
*
|
|
15
|
+
* Builds a fresh Commander program (so repeated calls do not share parser
|
|
16
|
+
* state), wires all command handlers, and parses the supplied arguments. Help,
|
|
17
|
+
* version and usage errors are handled gracefully (Commander's message is
|
|
18
|
+
* already written) instead of terminating the process; genuine errors thrown by
|
|
19
|
+
* a command action propagate to the caller.
|
|
20
|
+
*
|
|
21
|
+
* @param argv - The chili arguments, e.g. `["feeds", "list", "-s"]` (without
|
|
22
|
+
* the leading `node`/script entries).
|
|
23
|
+
*/
|
|
24
|
+
export declare function run(argv: string[]): Promise<void>;
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file In-process library entry for the chili (ChILI) CLI.
|
|
3
|
+
*
|
|
4
|
+
* Exposes {@link run}, which builds a fresh Commander program and executes a
|
|
5
|
+
* single chili command, returning when it completes. Unlike the bin entry
|
|
6
|
+
* (`index.ts`), importing this module has no side effect of running the CLI and
|
|
7
|
+
* never calls `process.exit`, so a host process such as chell can drive chili
|
|
8
|
+
* in-process instead of spawning a separate `node` subprocess.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import { Command, CommanderError } from "commander";
|
|
13
|
+
import figlet from "figlet";
|
|
14
|
+
import { connectCommand_setup } from "./connect/connectHandler.js";
|
|
15
|
+
import { FeedGroupHandler, FeedMemberHandler } from "./feeds/feedHandler.js";
|
|
16
|
+
import { PluginGroupHandler, PluginMemberHandler, } from "./plugins/pluginHandler.js";
|
|
17
|
+
import { PluginMetaGroupHandler } from "./plugins/pluginMetaHandler.js";
|
|
18
|
+
import { PluginContextGroupHandler } from "./plugins/pluginGroupHandler.js";
|
|
19
|
+
import { inodeCommand_setup } from "./filesystem/inodeCommand.js";
|
|
20
|
+
import { contextCommand_setup } from "./context/contextCommand.js";
|
|
21
|
+
import { pathCommand_setup } from "./path/pathCommand.js";
|
|
22
|
+
import { fileBrowserCommand_setup } from "./filesystem/filesystemHandler.js";
|
|
23
|
+
import { manCommand_setup } from "./man/man.js";
|
|
24
|
+
import { chefsCommand_setup } from "./chefs/chefs.js";
|
|
25
|
+
import { PACSServerGroupHandler } from "./pacs/pacsServerHandler.js";
|
|
26
|
+
import { PACSQueryGroupHandler } from "./pacs/pacsQueryHandler.js";
|
|
27
|
+
import { PACSRetrieveGroupHandler } from "./pacs/pacsRetrieveHandler.js";
|
|
28
|
+
import { chrisConnection_init, NodeStorageProvider, errorStack_getAllOfType, } from "@fnndsc/cumin";
|
|
29
|
+
import { FileGroupHandler } from "./filesystem/fileGroupHandler.js";
|
|
30
|
+
/**
|
|
31
|
+
* Suppress the DEP0169 (`url.parse()`) warning emitted transitively by
|
|
32
|
+
* axios -> proxy-from-env, which we do not control. Installed once at import.
|
|
33
|
+
* See the tracking note in the original bin entry for context.
|
|
34
|
+
*/
|
|
35
|
+
const originalEmitWarning = process.emitWarning;
|
|
36
|
+
process.emitWarning = function (warning, ...args) {
|
|
37
|
+
if (typeof warning === "string" &&
|
|
38
|
+
(warning.includes("DEP0169") || warning.includes("url.parse()"))) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
return originalEmitWarning.call(process, warning, ...args);
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Registers every chili command handler on the supplied program. The handler
|
|
45
|
+
* setup functions are program-parameterised, so a fresh program can be wired on
|
|
46
|
+
* each call without sharing Commander state across invocations.
|
|
47
|
+
*
|
|
48
|
+
* @param program - The Commander program to register commands on.
|
|
49
|
+
*/
|
|
50
|
+
async function handlers_initialize(program) {
|
|
51
|
+
// Connection is intentionally not enforced here so that `--help` works; each
|
|
52
|
+
// command fails individually if it needs a connection that is not present.
|
|
53
|
+
fileBrowserCommand_setup(program);
|
|
54
|
+
contextCommand_setup(program);
|
|
55
|
+
pathCommand_setup(program);
|
|
56
|
+
manCommand_setup(program);
|
|
57
|
+
chefsCommand_setup(program);
|
|
58
|
+
const pacsServerHandler = new PACSServerGroupHandler();
|
|
59
|
+
pacsServerHandler.pacsServerCommand_setup(program);
|
|
60
|
+
const pacsQueryHandler = new PACSQueryGroupHandler();
|
|
61
|
+
pacsQueryHandler.pacsQueryCommand_setup(program);
|
|
62
|
+
const pacsRetrieveHandler = new PACSRetrieveGroupHandler();
|
|
63
|
+
pacsRetrieveHandler.pacsRetrieveCommand_setup(program);
|
|
64
|
+
await inodeCommand_setup(program);
|
|
65
|
+
const pluginGroupHandler = new PluginGroupHandler();
|
|
66
|
+
pluginGroupHandler.pluginGroupCommand_setup(program);
|
|
67
|
+
const pluginMetaGroupHandler = new PluginMetaGroupHandler();
|
|
68
|
+
pluginMetaGroupHandler.pluginMetaGroupCommand_setup(program);
|
|
69
|
+
const feedGroupHandler = new FeedGroupHandler();
|
|
70
|
+
feedGroupHandler.feedGroupCommand_setup(program);
|
|
71
|
+
const feedMemberHandler = new FeedMemberHandler();
|
|
72
|
+
feedMemberHandler.feedCommand_setup(program);
|
|
73
|
+
const pluginMemberHandler = new PluginMemberHandler();
|
|
74
|
+
pluginMemberHandler.pluginCommand_setup(program);
|
|
75
|
+
try {
|
|
76
|
+
const filesGroupHandler = await FileGroupHandler.handler_create("files");
|
|
77
|
+
filesGroupHandler.fileGroupCommand_setup(program);
|
|
78
|
+
const linksGroupHandler = await FileGroupHandler.handler_create("links");
|
|
79
|
+
linksGroupHandler.fileGroupCommand_setup(program);
|
|
80
|
+
const dirsGroupHandler = await FileGroupHandler.handler_create("dirs");
|
|
81
|
+
dirsGroupHandler.fileGroupCommand_setup(program);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
const err = e instanceof Error ? e.message : String(e);
|
|
85
|
+
const errors = errorStack_getAllOfType("error");
|
|
86
|
+
const warnings = errorStack_getAllOfType("warning");
|
|
87
|
+
console.log(`Note: File group commands (files, dirs, links) are unavailable. Reason: ${err}`);
|
|
88
|
+
if (errors.length > 0) {
|
|
89
|
+
console.log("Errors:");
|
|
90
|
+
errors.forEach((msg) => console.log(` - ${msg}`));
|
|
91
|
+
}
|
|
92
|
+
if (warnings.length > 0) {
|
|
93
|
+
console.log("Warnings:");
|
|
94
|
+
warnings.forEach((msg) => console.log(` - ${msg}`));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const computesOfPluginHandler = await PluginContextGroupHandler.handler_create("computesofplugin");
|
|
99
|
+
computesOfPluginHandler.pluginContextGroupCommand_setup(program);
|
|
100
|
+
const pluginInstancesHandler = await PluginContextGroupHandler.handler_create("instancesofplugin");
|
|
101
|
+
pluginInstancesHandler.pluginContextGroupCommand_setup(program);
|
|
102
|
+
const pluginParametersHandler = await PluginContextGroupHandler.handler_create("parametersofplugin");
|
|
103
|
+
pluginParametersHandler.pluginContextGroupCommand_setup(program);
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
const err = e instanceof Error ? e.message : String(e);
|
|
107
|
+
const errors = errorStack_getAllOfType("error");
|
|
108
|
+
const warnings = errorStack_getAllOfType("warning");
|
|
109
|
+
console.log(`Note: Plugin context commands are unavailable. Reason: ${err}`);
|
|
110
|
+
if (errors.length > 0) {
|
|
111
|
+
console.log("Errors:");
|
|
112
|
+
errors.forEach((msg) => console.log(` - ${msg}`));
|
|
113
|
+
}
|
|
114
|
+
if (warnings.length > 0) {
|
|
115
|
+
console.log("Warnings:");
|
|
116
|
+
warnings.forEach((msg) => console.log(` - ${msg}`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Extracts a leading `key=value` context string from an argv array.
|
|
122
|
+
*
|
|
123
|
+
* @param args - An argv array shaped like `process.argv` (exec, script, ...).
|
|
124
|
+
* @returns A tuple of the context string (if any) and argv with it removed.
|
|
125
|
+
*/
|
|
126
|
+
function context_parse(args) {
|
|
127
|
+
for (let i = 2; i < args.length; i++) {
|
|
128
|
+
const arg = args[i];
|
|
129
|
+
if (arg.includes("=") && !arg.startsWith("-")) {
|
|
130
|
+
const context = arg;
|
|
131
|
+
const newArgs = [...args.slice(0, i), ...args.slice(i + 1)];
|
|
132
|
+
return [context, newArgs];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return [undefined, args];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Executes a single chili command in the current process.
|
|
139
|
+
*
|
|
140
|
+
* Builds a fresh Commander program (so repeated calls do not share parser
|
|
141
|
+
* state), wires all command handlers, and parses the supplied arguments. Help,
|
|
142
|
+
* version and usage errors are handled gracefully (Commander's message is
|
|
143
|
+
* already written) instead of terminating the process; genuine errors thrown by
|
|
144
|
+
* a command action propagate to the caller.
|
|
145
|
+
*
|
|
146
|
+
* @param argv - The chili arguments, e.g. `["feeds", "list", "-s"]` (without
|
|
147
|
+
* the leading `node`/script entries).
|
|
148
|
+
*/
|
|
149
|
+
export async function run(argv) {
|
|
150
|
+
const nodeStorageProvider = new NodeStorageProvider();
|
|
151
|
+
const connection = await chrisConnection_init(nodeStorageProvider);
|
|
152
|
+
// Commander's default parsing expects argv[0]/argv[1] to be exec/script.
|
|
153
|
+
let fullArgv = ["node", "chili", ...argv];
|
|
154
|
+
const [context, newArgs] = context_parse(fullArgv);
|
|
155
|
+
if (context) {
|
|
156
|
+
const contextSetSuccess = await connection.context_set(context);
|
|
157
|
+
if (!contextSetSuccess) {
|
|
158
|
+
console.error("Failed to set context.");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
fullArgv = newArgs;
|
|
162
|
+
}
|
|
163
|
+
const program = new Command();
|
|
164
|
+
program
|
|
165
|
+
.name("chili")
|
|
166
|
+
.description("ChILI handles Intelligent Line Interactions")
|
|
167
|
+
.version("1.0.1")
|
|
168
|
+
.option("-v, --verbose", "enable verbose output")
|
|
169
|
+
.option("-c, --config <path>", "path to config file")
|
|
170
|
+
.option("-s, --nosplash", "disable splash screen")
|
|
171
|
+
.exitOverride();
|
|
172
|
+
connectCommand_setup(program);
|
|
173
|
+
await handlers_initialize(program);
|
|
174
|
+
program.parseOptions(fullArgv);
|
|
175
|
+
const options = program.opts();
|
|
176
|
+
if (!options.nosplash) {
|
|
177
|
+
console.log(figlet.textSync("ChILI"));
|
|
178
|
+
console.log("ChILI handles Intelligent Line Interactions");
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
await program.parseAsync(fullArgv);
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
// Under exitOverride, --help/--version/usage errors throw a CommanderError
|
|
185
|
+
// whose message Commander has already written. Swallow these so the host
|
|
186
|
+
// (e.g. a chell REPL) is not torn down; rethrow anything else.
|
|
187
|
+
if (err instanceof CommanderError) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Shared shaping helpers for FilteredResourceData prior to display.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { FilteredResourceData } from "@fnndsc/cumin";
|
|
7
|
+
/**
|
|
8
|
+
* Removes duplicate column headers from a FilteredResourceData result.
|
|
9
|
+
*
|
|
10
|
+
* Keeps each selected field once (preserving first-seen order) and projects
|
|
11
|
+
* every table row onto that unique header set.
|
|
12
|
+
*
|
|
13
|
+
* @param results - The resource data to de-duplicate.
|
|
14
|
+
* @returns A new FilteredResourceData with unique selectedFields and matching rows.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resourceColumns_removeDuplicates(results: FilteredResourceData): FilteredResourceData;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Removes duplicate column headers from a FilteredResourceData result.
|
|
3
|
+
*
|
|
4
|
+
* Keeps each selected field once (preserving first-seen order) and projects
|
|
5
|
+
* every table row onto that unique header set.
|
|
6
|
+
*
|
|
7
|
+
* @param results - The resource data to de-duplicate.
|
|
8
|
+
* @returns A new FilteredResourceData with unique selectedFields and matching rows.
|
|
9
|
+
*/
|
|
10
|
+
export function resourceColumns_removeDuplicates(results) {
|
|
11
|
+
const uniqueHeaders = Array.from(new Set(results.selectedFields));
|
|
12
|
+
const uniqueTableData = results.tableData.map((row) => uniqueHeaders.reduce((acc, header) => {
|
|
13
|
+
if (typeof header === "string" && header in row) {
|
|
14
|
+
acc[header] = row[header];
|
|
15
|
+
}
|
|
16
|
+
return acc;
|
|
17
|
+
}, {}));
|
|
18
|
+
return {
|
|
19
|
+
...results,
|
|
20
|
+
selectedFields: uniqueHeaders,
|
|
21
|
+
tableData: uniqueTableData,
|
|
22
|
+
};
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fnndsc/chili",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "ChILI handles Intelligent Line Interactions: A CLI and library for ChRIS, acting as the controller layer for business logic and user presentation.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsc && chmod +x ./dist/index.js",
|
|
27
27
|
"start": "node dist/index.js",
|
|
28
|
-
"test": "jest",
|
|
28
|
+
"test": "jest --coverage",
|
|
29
29
|
"test:coverage": "jest --coverage --coverageProvider=v8",
|
|
30
30
|
"clean": "rm -rf dist types fnndsc-chili*tgz",
|
|
31
31
|
"build:cumin": "cd ../cumin && npm run build",
|
|
@@ -47,14 +47,13 @@
|
|
|
47
47
|
"author": "FNNDSC <dev@babyMRI.org>",
|
|
48
48
|
"license": "MIT",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@fnndsc/cumin": "^3.
|
|
51
|
-
"@fnndsc/salsa": "^3.2.
|
|
50
|
+
"@fnndsc/cumin": "^3.4.0",
|
|
51
|
+
"@fnndsc/salsa": "^3.2.5",
|
|
52
52
|
"@fortawesome/fontawesome-free": "^6.6.0",
|
|
53
53
|
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
|
54
54
|
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
|
55
|
-
"@mermaid-js/mermaid-cli": "^11.12.0",
|
|
56
55
|
"archy": "^1.0.0",
|
|
57
|
-
"asciidoctor": "^
|
|
56
|
+
"asciidoctor": "^4.0.1",
|
|
58
57
|
"axios": "^1.6.0",
|
|
59
58
|
"chalk": "^4.1.2",
|
|
60
59
|
"cli-highlight": "^2.1.11",
|
|
@@ -65,7 +64,6 @@
|
|
|
65
64
|
"js-yaml": "^4.1.0",
|
|
66
65
|
"marked": "^9.1.0",
|
|
67
66
|
"marked-terminal": "^6.1.0",
|
|
68
|
-
"node-fetch": "^3.3.2",
|
|
69
67
|
"omelette": "^0.4.17",
|
|
70
68
|
"open": "^10.1.0",
|
|
71
69
|
"table": "^6.8.1"
|
|
@@ -77,7 +75,7 @@
|
|
|
77
75
|
"@types/jest": "^30.0.0",
|
|
78
76
|
"@types/js-yaml": "^4.0.5",
|
|
79
77
|
"@types/marked-terminal": "^6.1.1",
|
|
80
|
-
"@types/node": "^
|
|
78
|
+
"@types/node": "^22.0.0",
|
|
81
79
|
"@types/node-fetch": "^2.6.11",
|
|
82
80
|
"@types/omelette": "^0.4.4",
|
|
83
81
|
"jest": "^30.2.0",
|