@fnndsc/chell 4.2.8
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/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/builtins/debug.d.ts +6 -0
- package/dist/builtins/debug.js +47 -0
- package/dist/builtins/debug.js.map +1 -0
- package/dist/builtins/executable.d.ts +22 -0
- package/dist/builtins/executable.js +115 -0
- package/dist/builtins/executable.js.map +1 -0
- package/dist/builtins/fs/cat.d.ts +16 -0
- package/dist/builtins/fs/cat.js +249 -0
- package/dist/builtins/fs/cat.js.map +1 -0
- package/dist/builtins/fs/cd.d.ts +41 -0
- package/dist/builtins/fs/cd.js +178 -0
- package/dist/builtins/fs/cd.js.map +1 -0
- package/dist/builtins/fs/cp.d.ts +7 -0
- package/dist/builtins/fs/cp.js +73 -0
- package/dist/builtins/fs/cp.js.map +1 -0
- package/dist/builtins/fs/download.d.ts +6 -0
- package/dist/builtins/fs/download.js +41 -0
- package/dist/builtins/fs/download.js.map +1 -0
- package/dist/builtins/fs/du.d.ts +58 -0
- package/dist/builtins/fs/du.js +210 -0
- package/dist/builtins/fs/du.js.map +1 -0
- package/dist/builtins/fs/edit.d.ts +7 -0
- package/dist/builtins/fs/edit.js +86 -0
- package/dist/builtins/fs/edit.js.map +1 -0
- package/dist/builtins/fs/ls.d.ts +8 -0
- package/dist/builtins/fs/ls.js +68 -0
- package/dist/builtins/fs/ls.js.map +1 -0
- package/dist/builtins/fs/mkdir.d.ts +6 -0
- package/dist/builtins/fs/mkdir.js +38 -0
- package/dist/builtins/fs/mkdir.js.map +1 -0
- package/dist/builtins/fs/mv.d.ts +7 -0
- package/dist/builtins/fs/mv.js +75 -0
- package/dist/builtins/fs/mv.js.map +1 -0
- package/dist/builtins/fs/pull.args.d.ts +22 -0
- package/dist/builtins/fs/pull.args.js +30 -0
- package/dist/builtins/fs/pull.args.js.map +1 -0
- package/dist/builtins/fs/pull.d.ts +26 -0
- package/dist/builtins/fs/pull.js +413 -0
- package/dist/builtins/fs/pull.js.map +1 -0
- package/dist/builtins/fs/pwd.d.ts +7 -0
- package/dist/builtins/fs/pwd.js +75 -0
- package/dist/builtins/fs/pwd.js.map +1 -0
- package/dist/builtins/fs/rm.d.ts +31 -0
- package/dist/builtins/fs/rm.js +148 -0
- package/dist/builtins/fs/rm.js.map +1 -0
- package/dist/builtins/fs/touch.d.ts +6 -0
- package/dist/builtins/fs/touch.js +64 -0
- package/dist/builtins/fs/touch.js.map +1 -0
- package/dist/builtins/fs/tree.d.ts +15 -0
- package/dist/builtins/fs/tree.js +84 -0
- package/dist/builtins/fs/tree.js.map +1 -0
- package/dist/builtins/fs/upload.d.ts +6 -0
- package/dist/builtins/fs/upload.js +45 -0
- package/dist/builtins/fs/upload.js.map +1 -0
- package/dist/builtins/help.d.ts +74 -0
- package/dist/builtins/help.js +1217 -0
- package/dist/builtins/help.js.map +1 -0
- package/dist/builtins/index.d.ts +45 -0
- package/dist/builtins/index.js +45 -0
- package/dist/builtins/index.js.map +1 -0
- package/dist/builtins/net/connect.d.ts +7 -0
- package/dist/builtins/net/connect.js +42 -0
- package/dist/builtins/net/connect.js.map +1 -0
- package/dist/builtins/net/cubepath.d.ts +18 -0
- package/dist/builtins/net/cubepath.js +102 -0
- package/dist/builtins/net/cubepath.js.map +1 -0
- package/dist/builtins/net/logout.d.ts +6 -0
- package/dist/builtins/net/logout.js +24 -0
- package/dist/builtins/net/logout.js.map +1 -0
- package/dist/builtins/net/pacs.d.ts +24 -0
- package/dist/builtins/net/pacs.js +121 -0
- package/dist/builtins/net/pacs.js.map +1 -0
- package/dist/builtins/net/pacsUtils.d.ts +85 -0
- package/dist/builtins/net/pacsUtils.js +184 -0
- package/dist/builtins/net/pacsUtils.js.map +1 -0
- package/dist/builtins/net/query.d.ts +60 -0
- package/dist/builtins/net/query.js +304 -0
- package/dist/builtins/net/query.js.map +1 -0
- package/dist/builtins/parametersofplugin.d.ts +13 -0
- package/dist/builtins/parametersofplugin.js +43 -0
- package/dist/builtins/parametersofplugin.js.map +1 -0
- package/dist/builtins/pluginExecute.d.ts +27 -0
- package/dist/builtins/pluginExecute.js +165 -0
- package/dist/builtins/pluginExecute.js.map +1 -0
- package/dist/builtins/proc.d.ts +6 -0
- package/dist/builtins/proc.helpers.d.ts +68 -0
- package/dist/builtins/proc.helpers.js +102 -0
- package/dist/builtins/proc.helpers.js.map +1 -0
- package/dist/builtins/proc.js +289 -0
- package/dist/builtins/proc.js.map +1 -0
- package/dist/builtins/res/compute.d.ts +6 -0
- package/dist/builtins/res/compute.js +55 -0
- package/dist/builtins/res/compute.js.map +1 -0
- package/dist/builtins/res/feed.d.ts +6 -0
- package/dist/builtins/res/feed.js +244 -0
- package/dist/builtins/res/feed.js.map +1 -0
- package/dist/builtins/res/feed.notes.d.ts +28 -0
- package/dist/builtins/res/feed.notes.js +24 -0
- package/dist/builtins/res/feed.notes.js.map +1 -0
- package/dist/builtins/res/files.d.ts +18 -0
- package/dist/builtins/res/files.js +85 -0
- package/dist/builtins/res/files.js.map +1 -0
- package/dist/builtins/res/group.d.ts +6 -0
- package/dist/builtins/res/group.js +54 -0
- package/dist/builtins/res/group.js.map +1 -0
- package/dist/builtins/res/pipeline.args.d.ts +22 -0
- package/dist/builtins/res/pipeline.args.js +28 -0
- package/dist/builtins/res/pipeline.args.js.map +1 -0
- package/dist/builtins/res/pipeline.d.ts +20 -0
- package/dist/builtins/res/pipeline.js +252 -0
- package/dist/builtins/res/pipeline.js.map +1 -0
- package/dist/builtins/res/plugin.d.ts +13 -0
- package/dist/builtins/res/plugin.js +140 -0
- package/dist/builtins/res/plugin.js.map +1 -0
- package/dist/builtins/res/plugininstance.d.ts +6 -0
- package/dist/builtins/res/plugininstance.js +53 -0
- package/dist/builtins/res/plugininstance.js.map +1 -0
- package/dist/builtins/res/pluginmeta.d.ts +6 -0
- package/dist/builtins/res/pluginmeta.js +53 -0
- package/dist/builtins/res/pluginmeta.js.map +1 -0
- package/dist/builtins/res/tag.d.ts +6 -0
- package/dist/builtins/res/tag.js +53 -0
- package/dist/builtins/res/tag.js.map +1 -0
- package/dist/builtins/res/workflow.d.ts +6 -0
- package/dist/builtins/res/workflow.js +53 -0
- package/dist/builtins/res/workflow.js.map +1 -0
- package/dist/builtins/store.d.ts +6 -0
- package/dist/builtins/store.js +108 -0
- package/dist/builtins/store.js.map +1 -0
- package/dist/builtins/sys/context.d.ts +6 -0
- package/dist/builtins/sys/context.js +50 -0
- package/dist/builtins/sys/context.js.map +1 -0
- package/dist/builtins/sys/physicalmode.d.ts +6 -0
- package/dist/builtins/sys/physicalmode.js +41 -0
- package/dist/builtins/sys/physicalmode.js.map +1 -0
- package/dist/builtins/sys/prompt.d.ts +13 -0
- package/dist/builtins/sys/prompt.helpers.d.ts +31 -0
- package/dist/builtins/sys/prompt.helpers.js +36 -0
- package/dist/builtins/sys/prompt.helpers.js.map +1 -0
- package/dist/builtins/sys/prompt.js +182 -0
- package/dist/builtins/sys/prompt.js.map +1 -0
- package/dist/builtins/sys/timing.d.ts +6 -0
- package/dist/builtins/sys/timing.js +41 -0
- package/dist/builtins/sys/timing.js.map +1 -0
- package/dist/builtins/sys/whoami.d.ts +12 -0
- package/dist/builtins/sys/whoami.js +37 -0
- package/dist/builtins/sys/whoami.js.map +1 -0
- package/dist/builtins/utils.d.ts +55 -0
- package/dist/builtins/utils.js +145 -0
- package/dist/builtins/utils.js.map +1 -0
- package/dist/builtins/wildcard.d.ts +26 -0
- package/dist/builtins/wildcard.js +120 -0
- package/dist/builtins/wildcard.js.map +1 -0
- package/dist/chell.d.ts +16 -0
- package/dist/chell.js +1193 -0
- package/dist/chell.js.map +1 -0
- package/dist/command-keys.d.ts +8 -0
- package/dist/command-keys.js +32 -0
- package/dist/command-keys.js.map +1 -0
- package/dist/config/settings.d.ts +39 -0
- package/dist/config/settings.js +93 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/core/bootFlags.d.ts +32 -0
- package/dist/core/bootFlags.js +25 -0
- package/dist/core/bootFlags.js.map +1 -0
- package/dist/core/cli.d.ts +58 -0
- package/dist/core/cli.js +251 -0
- package/dist/core/cli.js.map +1 -0
- package/dist/core/prompt/index.d.ts +80 -0
- package/dist/core/prompt/index.js +29 -0
- package/dist/core/prompt/index.js.map +1 -0
- package/dist/core/prompt/theme_default.d.ts +19 -0
- package/dist/core/prompt/theme_default.js +47 -0
- package/dist/core/prompt/theme_default.js.map +1 -0
- package/dist/core/prompt/theme_p10k.d.ts +22 -0
- package/dist/core/prompt/theme_p10k.js +164 -0
- package/dist/core/prompt/theme_p10k.js.map +1 -0
- package/dist/core/prompt/utils.d.ts +23 -0
- package/dist/core/prompt/utils.js +40 -0
- package/dist/core/prompt/utils.js.map +1 -0
- package/dist/core/question.d.ts +34 -0
- package/dist/core/question.js +76 -0
- package/dist/core/question.js.map +1 -0
- package/dist/core/repl.d.ts +31 -0
- package/dist/core/repl.js +146 -0
- package/dist/core/repl.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/bootsequence.d.ts +62 -0
- package/dist/lib/bootsequence.js +222 -0
- package/dist/lib/bootsequence.js.map +1 -0
- package/dist/lib/completer/index.d.ts +15 -0
- package/dist/lib/completer/index.js +212 -0
- package/dist/lib/completer/index.js.map +1 -0
- package/dist/lib/completer/pathComplete.helpers.d.ts +22 -0
- package/dist/lib/completer/pathComplete.helpers.js +49 -0
- package/dist/lib/completer/pathComplete.helpers.js.map +1 -0
- package/dist/lib/logo.d.ts +47 -0
- package/dist/lib/logo.js +313 -0
- package/dist/lib/logo.js.map +1 -0
- package/dist/lib/parser.d.ts +13 -0
- package/dist/lib/parser.js +52 -0
- package/dist/lib/parser.js.map +1 -0
- package/dist/lib/pipe.d.ts +11 -0
- package/dist/lib/pipe.js +90 -0
- package/dist/lib/pipe.js.map +1 -0
- package/dist/lib/prefetch.d.ts +25 -0
- package/dist/lib/prefetch.js +64 -0
- package/dist/lib/prefetch.js.map +1 -0
- package/dist/lib/semicolonParser.d.ts +22 -0
- package/dist/lib/semicolonParser.js +53 -0
- package/dist/lib/semicolonParser.js.map +1 -0
- package/dist/lib/spinner.d.ts +23 -0
- package/dist/lib/spinner.js +68 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/vfs/providers/static.d.ts +65 -0
- package/dist/lib/vfs/providers/static.js +164 -0
- package/dist/lib/vfs/providers/static.js.map +1 -0
- package/dist/lib/vfs/providers/static_content.d.ts +27 -0
- package/dist/lib/vfs/providers/static_content.js +180 -0
- package/dist/lib/vfs/providers/static_content.js.map +1 -0
- package/dist/lib/vfs/vfs.d.ts +59 -0
- package/dist/lib/vfs/vfs.js +198 -0
- package/dist/lib/vfs/vfs.js.map +1 -0
- package/dist/session/index.d.ts +76 -0
- package/dist/session/index.js +120 -0
- package/dist/session/index.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Builtin cat command.
|
|
3
|
+
* Displays file contents.
|
|
4
|
+
*/
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { path_resolve, error_stripDebugPrefix } from '../utils.js';
|
|
7
|
+
import { files_cat as chefs_cat_cmd, files_catBinary as chefs_catBinary_cmd } from '@fnndsc/chili/commands/fs/cat.js';
|
|
8
|
+
import { cat_render } from '@fnndsc/chili/views/fs.js';
|
|
9
|
+
import { errorStack } from '@fnndsc/cumin';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
/** File extensions that receive syntax highlighting. */
|
|
12
|
+
const HIGHLIGHT_EXTENSIONS = new Set(['.json', '.yaml', '.yml']);
|
|
13
|
+
/**
|
|
14
|
+
* Applies chalk-based syntax highlighting to JSON content.
|
|
15
|
+
* Returns the original string if the content is not valid JSON.
|
|
16
|
+
*
|
|
17
|
+
* @param content - Raw JSON string.
|
|
18
|
+
* @returns Highlighted string, or original on parse failure.
|
|
19
|
+
*/
|
|
20
|
+
function json_highlight(content) {
|
|
21
|
+
try {
|
|
22
|
+
JSON.parse(content);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return content;
|
|
26
|
+
}
|
|
27
|
+
return content.replace(/("(?:\\u[0-9a-fA-F]{4}|\\[^u]|[^\\"])*"(\s*:)?|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, (match) => {
|
|
28
|
+
if (match.endsWith(':'))
|
|
29
|
+
return chalk.cyan(match); // key
|
|
30
|
+
if (match.startsWith('"'))
|
|
31
|
+
return chalk.green(match); // string value
|
|
32
|
+
if (match === 'true' || match === 'false')
|
|
33
|
+
return chalk.yellow(match);
|
|
34
|
+
if (match === 'null')
|
|
35
|
+
return chalk.gray(match);
|
|
36
|
+
return chalk.magenta(match); // number
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Applies chalk-based syntax highlighting to YAML content line by line.
|
|
41
|
+
*
|
|
42
|
+
* @param content - Raw YAML string.
|
|
43
|
+
* @returns Highlighted string.
|
|
44
|
+
*/
|
|
45
|
+
function yaml_highlight(content) {
|
|
46
|
+
return content.split('\n').map((line) => {
|
|
47
|
+
if (/^\s*#/.test(line))
|
|
48
|
+
return chalk.gray(line);
|
|
49
|
+
const kv = line.match(/^(\s*)([\w./-]+)(\s*:\s*)(.*)/);
|
|
50
|
+
if (kv) {
|
|
51
|
+
const [, indent, key, sep, value] = kv;
|
|
52
|
+
const coloredValue = value_yamlColor(value);
|
|
53
|
+
return `${indent}${chalk.cyan(key)}${chalk.gray(sep)}${coloredValue}`;
|
|
54
|
+
}
|
|
55
|
+
const listItem = line.match(/^(\s*-\s+)(.*)/);
|
|
56
|
+
if (listItem) {
|
|
57
|
+
return `${chalk.gray(listItem[1])}${chalk.green(listItem[2])}`;
|
|
58
|
+
}
|
|
59
|
+
return line;
|
|
60
|
+
}).join('\n');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Colors a scalar YAML value based on its type.
|
|
64
|
+
*
|
|
65
|
+
* @param value - The raw value string from a YAML key: value line.
|
|
66
|
+
* @returns Chalk-colored value string.
|
|
67
|
+
*/
|
|
68
|
+
function value_yamlColor(value) {
|
|
69
|
+
if (!value)
|
|
70
|
+
return value;
|
|
71
|
+
if (value === 'true' || value === 'false')
|
|
72
|
+
return chalk.yellow(value);
|
|
73
|
+
if (value === 'null' || value === '~')
|
|
74
|
+
return chalk.gray(value);
|
|
75
|
+
if (/^-?\d+(\.\d+)?$/.test(value))
|
|
76
|
+
return chalk.magenta(value);
|
|
77
|
+
if (/^["']/.test(value))
|
|
78
|
+
return chalk.green(value);
|
|
79
|
+
return chalk.white(value);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Applies syntax highlighting to text content based on file extension.
|
|
83
|
+
* Returns the original string unchanged when stdout is not a TTY (piping).
|
|
84
|
+
*
|
|
85
|
+
* @param content - File content string.
|
|
86
|
+
* @param filePath - Full path used to determine the file type.
|
|
87
|
+
* @returns Highlighted or original content.
|
|
88
|
+
*/
|
|
89
|
+
function content_highlight(content, filePath) {
|
|
90
|
+
if (!process.stdout.isTTY)
|
|
91
|
+
return content;
|
|
92
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
93
|
+
if (ext === '.json')
|
|
94
|
+
return json_highlight(content);
|
|
95
|
+
if (ext === '.yaml' || ext === '.yml')
|
|
96
|
+
return yaml_highlight(content);
|
|
97
|
+
return content;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* List of file extensions that are considered binary.
|
|
101
|
+
*/
|
|
102
|
+
const BINARY_EXTENSIONS = new Set([
|
|
103
|
+
'.dcm', // DICOM medical images
|
|
104
|
+
'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.webp', // Images
|
|
105
|
+
'.pdf', // Documents
|
|
106
|
+
'.zip', '.tar', '.gz', '.bz2', '.xz', '.7z', '.rar', // Archives
|
|
107
|
+
'.exe', '.dll', '.so', '.dylib', '.bin', // Executables/Libraries
|
|
108
|
+
'.mp3', '.mp4', '.avi', '.mov', '.wav', '.flac', // Media
|
|
109
|
+
]);
|
|
110
|
+
/**
|
|
111
|
+
* Checks if a file path has a binary extension.
|
|
112
|
+
*
|
|
113
|
+
* @param filePath - The file path to check.
|
|
114
|
+
* @returns True if the file has a binary extension.
|
|
115
|
+
*/
|
|
116
|
+
function extension_isBinary(filePath) {
|
|
117
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
118
|
+
return BINARY_EXTENSIONS.has(ext);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Writes a buffer to stdout with proper backpressure handling.
|
|
122
|
+
*
|
|
123
|
+
* Splits large buffers into 64KB chunks and waits for drain events when the
|
|
124
|
+
* output buffer is full. This prevents data loss when piping large binary files
|
|
125
|
+
* to external commands. Waits for all data to be flushed before resolving.
|
|
126
|
+
*
|
|
127
|
+
* @param buffer - The buffer to write to stdout.
|
|
128
|
+
* @returns A Promise that resolves when all data has been written and flushed.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const dicomData: Buffer = await fetchDicomFile();
|
|
133
|
+
* await buffer_writeToStdout(dicomData);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
async function buffer_writeToStdout(buffer) {
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
if (buffer.length === 0) {
|
|
139
|
+
resolve();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
let offset = 0;
|
|
143
|
+
const chunkSize = 64 * 1024; // 64KB chunks
|
|
144
|
+
/**
|
|
145
|
+
* Recursively writes the next chunk of data to stdout.
|
|
146
|
+
* Handles backpressure by waiting for drain events when buffer is full.
|
|
147
|
+
*/
|
|
148
|
+
const chunk_writeNext = () => {
|
|
149
|
+
try {
|
|
150
|
+
while (offset < buffer.length) {
|
|
151
|
+
const end = Math.min(offset + chunkSize, buffer.length);
|
|
152
|
+
const chunk = buffer.subarray(offset, end);
|
|
153
|
+
offset = end;
|
|
154
|
+
const canContinue = process.stdout.write(chunk);
|
|
155
|
+
if (!canContinue) {
|
|
156
|
+
// Buffer is full, wait for drain event
|
|
157
|
+
process.stdout.once('drain', chunk_writeNext);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// All chunks written - ensure stdout is flushed before resolving
|
|
162
|
+
// Writing an empty string forces a flush check. If write() returns false,
|
|
163
|
+
// the buffer is full and we must wait for drain. This prevents truncation
|
|
164
|
+
// when piping to external processes, as Node.js won't exit until we resolve.
|
|
165
|
+
if (process.stdout.write('')) {
|
|
166
|
+
// Buffer has space, all data is flushed
|
|
167
|
+
resolve();
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Buffer is full, wait for final drain before resolving
|
|
171
|
+
process.stdout.once('drain', () => resolve());
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
reject(err);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
chunk_writeNext();
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Displays the content of one or more files.
|
|
183
|
+
*
|
|
184
|
+
* Supports multiple files and concatenates their output. Binary mode is applied
|
|
185
|
+
* consistently to all files if any file is detected as binary or --binary is specified.
|
|
186
|
+
*
|
|
187
|
+
* @param args - Command line arguments (file paths and optional --binary flag).
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* await builtin_cat(['file1.txt', 'file2.txt']);
|
|
192
|
+
* await builtin_cat(['--binary', 'image.dcm']);
|
|
193
|
+
* await builtin_cat(['*.json']); // After wildcard expansion
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export async function builtin_cat(args) {
|
|
197
|
+
let binaryMode = false;
|
|
198
|
+
const filePaths = [];
|
|
199
|
+
for (const arg of args) {
|
|
200
|
+
if (arg === '--binary') {
|
|
201
|
+
binaryMode = true;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
filePaths.push(arg);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (filePaths.length === 0) {
|
|
208
|
+
console.error(chalk.red('Usage: cat [--binary] <file> [file...]'));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
for (let i = 0; i < filePaths.length; i++) {
|
|
212
|
+
const pathArg = filePaths[i];
|
|
213
|
+
const target = await path_resolve(pathArg);
|
|
214
|
+
// Auto-detect binary files
|
|
215
|
+
const isBinaryFile = extension_isBinary(target);
|
|
216
|
+
// Inform user about auto-detection only if in interactive mode (stdout is TTY)
|
|
217
|
+
// Don't show warning when piping, as it would corrupt the binary output
|
|
218
|
+
// Only show on first file to avoid spam
|
|
219
|
+
if (i === 0 && isBinaryFile && !binaryMode && process.stdout.isTTY) {
|
|
220
|
+
console.error(chalk.cyan(`Info: ${pathArg} detected as binary file (${path.extname(target)}), using binary mode.`));
|
|
221
|
+
console.error(chalk.cyan('Tip: Use "cat --binary <file>" to explicitly request binary mode.'));
|
|
222
|
+
console.error('');
|
|
223
|
+
}
|
|
224
|
+
// Use binary mode if requested OR if file is detected as binary
|
|
225
|
+
if (binaryMode || isBinaryFile) {
|
|
226
|
+
const result = await chefs_catBinary_cmd(target);
|
|
227
|
+
if (!result.ok) {
|
|
228
|
+
const error = errorStack.stack_pop();
|
|
229
|
+
console.error(chalk.red(`cat: ${pathArg}: ${error ? error_stripDebugPrefix(error.message) : 'Unknown error'}`));
|
|
230
|
+
process.exitCode = 1;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
// Output raw buffer to stdout with backpressure handling
|
|
234
|
+
await buffer_writeToStdout(result.value);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const result = await chefs_cat_cmd(target);
|
|
238
|
+
if (!result.ok) {
|
|
239
|
+
const error = errorStack.stack_pop();
|
|
240
|
+
console.error(chalk.red(`cat: ${pathArg}: ${error ? error_stripDebugPrefix(error.message) : 'Unknown error'}`));
|
|
241
|
+
process.exitCode = 1;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const highlighted = content_highlight(result.value, target);
|
|
245
|
+
console.log(cat_render(highlighted, pathArg));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=cat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cat.js","sourceRoot":"","sources":["../../../src/builtins/fs/cat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface representing a FileBrowserFolder from ChRIS API.
|
|
3
|
+
*/
|
|
4
|
+
interface FileBrowserFolder {
|
|
5
|
+
path?: string;
|
|
6
|
+
data?: {
|
|
7
|
+
path?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes a logical path for VFS comparison by stripping a single trailing
|
|
12
|
+
* slash (except for the root path).
|
|
13
|
+
*
|
|
14
|
+
* @param logicalPath - The resolved logical path.
|
|
15
|
+
* @returns The normalized path.
|
|
16
|
+
*/
|
|
17
|
+
export declare function vfsPath_normalize(logicalPath: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Reports whether a path is a structural VFS container (always valid).
|
|
20
|
+
*
|
|
21
|
+
* @param cleanPath - The normalized path.
|
|
22
|
+
* @returns True if the path is a known structural VFS container.
|
|
23
|
+
*/
|
|
24
|
+
export declare function vfsPath_isStructural(cleanPath: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies if a given FileBrowserFolder object exactly matches the validation path.
|
|
27
|
+
*
|
|
28
|
+
* @param folder - The FileBrowserFolder object to verify.
|
|
29
|
+
* @param validationPath - The path to match against.
|
|
30
|
+
* @returns True if the folder path exactly matches validationPath, false otherwise.
|
|
31
|
+
*/
|
|
32
|
+
export declare function folder_verifyPathMatch(folder: FileBrowserFolder | null | undefined, validationPath: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Changes the current working directory in the ChRIS filesystem context.
|
|
35
|
+
* Validates the existence of the target path before setting it.
|
|
36
|
+
*
|
|
37
|
+
* @param args - An array containing the target path as the first element.
|
|
38
|
+
* @returns A Promise that resolves when the operation is complete.
|
|
39
|
+
*/
|
|
40
|
+
export declare function builtin_cd(args: string[]): Promise<void>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Builtin cd command.
|
|
3
|
+
* Changes the current working directory.
|
|
4
|
+
*/
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { session } from '../../session/index.js';
|
|
7
|
+
import { path_resolve, path_resolveLinks, error_stripDebugPrefix } from '../utils.js';
|
|
8
|
+
/**
|
|
9
|
+
* Structural VFS container paths that exist by definition and need no API
|
|
10
|
+
* validation when `cd`-ing into them.
|
|
11
|
+
*/
|
|
12
|
+
const STRUCTURAL_VFS_PATHS = ['/', '/net', '/net/pacs', '/net/pacs/queries', '/proc', '/proc/jobs'];
|
|
13
|
+
/**
|
|
14
|
+
* Normalizes a logical path for VFS comparison by stripping a single trailing
|
|
15
|
+
* slash (except for the root path).
|
|
16
|
+
*
|
|
17
|
+
* @param logicalPath - The resolved logical path.
|
|
18
|
+
* @returns The normalized path.
|
|
19
|
+
*/
|
|
20
|
+
export function vfsPath_normalize(logicalPath) {
|
|
21
|
+
return logicalPath.endsWith('/') && logicalPath.length > 1 ? logicalPath.slice(0, -1) : logicalPath;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Reports whether a path is a structural VFS container (always valid).
|
|
25
|
+
*
|
|
26
|
+
* @param cleanPath - The normalized path.
|
|
27
|
+
* @returns True if the path is a known structural VFS container.
|
|
28
|
+
*/
|
|
29
|
+
export function vfsPath_isStructural(cleanPath) {
|
|
30
|
+
return STRUCTURAL_VFS_PATHS.includes(cleanPath);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Verifies if a given FileBrowserFolder object exactly matches the validation path.
|
|
34
|
+
*
|
|
35
|
+
* @param folder - The FileBrowserFolder object to verify.
|
|
36
|
+
* @param validationPath - The path to match against.
|
|
37
|
+
* @returns True if the folder path exactly matches validationPath, false otherwise.
|
|
38
|
+
*/
|
|
39
|
+
export function folder_verifyPathMatch(folder, validationPath) {
|
|
40
|
+
if (!folder) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const folderPath = folder.data?.path || folder.path || '';
|
|
44
|
+
// Normalize both by removing all leading and trailing slashes to be robust against API inconsistencies
|
|
45
|
+
const cleanFolder = folderPath.replace(/^\/+|\/+$/g, '');
|
|
46
|
+
const cleanValidation = validationPath.replace(/^\/+|\/+$/g, '');
|
|
47
|
+
return cleanFolder === cleanValidation;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Handles `cd` into a virtual (VFS) path: structural containers are accepted
|
|
51
|
+
* directly, deeper VFS paths are validated and their listing cached.
|
|
52
|
+
*
|
|
53
|
+
* @param cleanPath - The normalized virtual path.
|
|
54
|
+
* @param pathArg - The original user-supplied path (for error messages).
|
|
55
|
+
*/
|
|
56
|
+
async function cdVirtual_handle(cleanPath, pathArg) {
|
|
57
|
+
if (vfsPath_isStructural(cleanPath)) {
|
|
58
|
+
await session.setCWD(cleanPath);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// For deeper VFS paths (e.g. /net/pacs/queries/<id>), validate and cache the
|
|
62
|
+
// result so a subsequent `ls` doesn't need to re-fetch.
|
|
63
|
+
const { vfsDispatcher } = await import('@fnndsc/salsa');
|
|
64
|
+
const listResult = await vfsDispatcher.list(cleanPath);
|
|
65
|
+
if (!listResult.ok) {
|
|
66
|
+
const { errorStack } = await import('@fnndsc/cumin');
|
|
67
|
+
const lastError = errorStack.stack_pop();
|
|
68
|
+
const detail = lastError ? error_stripDebugPrefix(lastError.message) : 'No such file or directory';
|
|
69
|
+
console.error(chalk.red(`cd: ${pathArg}: ${detail}`));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const { listCache_get } = await import('@fnndsc/cumin');
|
|
73
|
+
listCache_get().cache_set(cleanPath, listResult.value);
|
|
74
|
+
await session.setCWD(cleanPath);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Handles `cd` into a real (API-backed) ChRIS folder: resolves the validation
|
|
78
|
+
* path, then confirms the folder exists with an exact path match before setting
|
|
79
|
+
* the working directory.
|
|
80
|
+
*
|
|
81
|
+
* @param logicalPath - The resolved logical path.
|
|
82
|
+
* @param pathArg - The original user-supplied path (for error messages).
|
|
83
|
+
*/
|
|
84
|
+
async function cdReal_handle(logicalPath, pathArg) {
|
|
85
|
+
const client = await session.connection.client_get();
|
|
86
|
+
if (!client) {
|
|
87
|
+
console.error(chalk.red('Not connected to ChRIS.'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
let validationPath;
|
|
91
|
+
if (session.physicalMode_get()) {
|
|
92
|
+
validationPath = await path_resolveLinks(logicalPath);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const { logical_toPhysical } = await import('@fnndsc/chili/utils');
|
|
96
|
+
const physicalResult = await logical_toPhysical(logicalPath);
|
|
97
|
+
if (!physicalResult.ok) {
|
|
98
|
+
console.error(chalk.red(`cd: ${pathArg}: No such file or directory`));
|
|
99
|
+
if (session.connection.config?.debug) {
|
|
100
|
+
console.error(chalk.gray(` Logical path: ${logicalPath}`));
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
validationPath = physicalResult.value;
|
|
105
|
+
}
|
|
106
|
+
if (session.connection.config?.debug) {
|
|
107
|
+
console.log(chalk.gray(`cd: ${pathArg} → logical: ${logicalPath} → validation: ${validationPath}`));
|
|
108
|
+
}
|
|
109
|
+
const cwdPath = session.physicalMode_get() ? validationPath : logicalPath;
|
|
110
|
+
const currentCwd = await session.getCWD();
|
|
111
|
+
if (currentCwd === cwdPath) {
|
|
112
|
+
if (session.connection.config?.debug) {
|
|
113
|
+
console.log(chalk.gray(` Already in target directory, skipping validation`));
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const folder = (await client.getFileBrowserFolderByPath(validationPath));
|
|
119
|
+
if (folder_verifyPathMatch(folder, validationPath)) {
|
|
120
|
+
await session.setCWD(cwdPath);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.error(chalk.red(`cd: ${pathArg}: No such file or directory`));
|
|
124
|
+
if (session.connection.config?.debug) {
|
|
125
|
+
if (!folder) {
|
|
126
|
+
console.error(chalk.gray(` API returned null for path: ${validationPath}`));
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const folderPath = folder.data?.path || folder.path;
|
|
130
|
+
console.error(chalk.gray(` API returned mismatched folder path: ${folderPath} (expected: ${validationPath})`));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (apiError) {
|
|
136
|
+
console.error(chalk.red(`cd: ${pathArg}: No such file or directory`));
|
|
137
|
+
if (session.connection.config?.debug) {
|
|
138
|
+
const msg = apiError instanceof Error ? apiError.message : String(apiError);
|
|
139
|
+
console.error(chalk.gray(` API error: ${msg}`));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Changes the current working directory in the ChRIS filesystem context.
|
|
145
|
+
* Validates the existence of the target path before setting it.
|
|
146
|
+
*
|
|
147
|
+
* @param args - An array containing the target path as the first element.
|
|
148
|
+
* @returns A Promise that resolves when the operation is complete.
|
|
149
|
+
*/
|
|
150
|
+
export async function builtin_cd(args) {
|
|
151
|
+
const pathArg = args.length > 0 ? args.join(' ') : undefined;
|
|
152
|
+
// 'cd' with no args goes to home
|
|
153
|
+
if (!pathArg) {
|
|
154
|
+
return builtin_cd(['~']);
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const logicalPath = await path_resolve(pathArg);
|
|
158
|
+
const { vfsDispatcher } = await import('@fnndsc/salsa');
|
|
159
|
+
const cleanPath = vfsPath_normalize(logicalPath);
|
|
160
|
+
// Treat the path as virtual if it is, or is a parent of, any registered
|
|
161
|
+
// provider prefix (e.g. /proc is parent of /proc/feeds).
|
|
162
|
+
const isParentOfVfs = vfsDispatcher.providers_get().some((p) => p.prefix.startsWith(cleanPath + '/'));
|
|
163
|
+
const isVirtual = cleanPath === '/' ||
|
|
164
|
+
cleanPath === '/net' ||
|
|
165
|
+
isParentOfVfs ||
|
|
166
|
+
vfsDispatcher.provider_get(cleanPath).prefix !== '';
|
|
167
|
+
if (isVirtual) {
|
|
168
|
+
await cdVirtual_handle(cleanPath, pathArg);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
await cdReal_handle(logicalPath, pathArg);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
175
|
+
console.error(chalk.red(`Failed to cd: ${msg}`));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=cd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cd.js","sourceRoot":"","sources":["../../../src/builtins/fs/cd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Builtin cp command.
|
|
3
|
+
* Copies files or directories.
|
|
4
|
+
*/
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { commandArgs_process, path_resolve } from '../utils.js';
|
|
8
|
+
import { files_cp as chefs_cp_cmd } from '@fnndsc/chili/commands/fs/cp.js';
|
|
9
|
+
import { cp_render } from '@fnndsc/chili/views/fs.js';
|
|
10
|
+
import { listCache_get } from '@fnndsc/cumin';
|
|
11
|
+
/**
|
|
12
|
+
* Copies a file or directory.
|
|
13
|
+
* Supports multiple sources when destination is a directory.
|
|
14
|
+
*
|
|
15
|
+
* @param args - [flags, src1, src2, ..., dest]
|
|
16
|
+
*/
|
|
17
|
+
export async function builtin_cp(args) {
|
|
18
|
+
const parsed = commandArgs_process(args);
|
|
19
|
+
const pathArgs = parsed._;
|
|
20
|
+
if (pathArgs.length < 2) {
|
|
21
|
+
console.log(chalk.red('Usage: cp [-r] <source...> <dest>'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const recursive = !!parsed['r'] || !!parsed['recursive'];
|
|
25
|
+
// Last arg is destination, all others are sources
|
|
26
|
+
const dest = pathArgs[pathArgs.length - 1];
|
|
27
|
+
const sources = pathArgs.slice(0, -1);
|
|
28
|
+
const destPath = await path_resolve(dest);
|
|
29
|
+
const listCache = listCache_get();
|
|
30
|
+
let successCount = 0;
|
|
31
|
+
let failCount = 0;
|
|
32
|
+
for (const src of sources) {
|
|
33
|
+
try {
|
|
34
|
+
const srcPath = await path_resolve(src);
|
|
35
|
+
// For multiple sources, show which file we're copying
|
|
36
|
+
if (sources.length > 1) {
|
|
37
|
+
console.log(chalk.gray(`Copying ${srcPath}...`));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(`Copying ${srcPath} to ${destPath}...`);
|
|
41
|
+
}
|
|
42
|
+
const success = await chefs_cp_cmd(srcPath, destPath, { recursive });
|
|
43
|
+
if (sources.length === 1) {
|
|
44
|
+
console.log(cp_render(srcPath, destPath, success));
|
|
45
|
+
}
|
|
46
|
+
if (success) {
|
|
47
|
+
successCount++;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
failCount++;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
55
|
+
console.error(chalk.red(`cp: ${src}: ${msg}`));
|
|
56
|
+
failCount++;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Invalidate destination directory (always, since files copied into it)
|
|
60
|
+
listCache.cache_invalidate(destPath);
|
|
61
|
+
const destParent = path.posix.dirname(destPath);
|
|
62
|
+
listCache.cache_invalidate(destParent);
|
|
63
|
+
// Summary for multiple files
|
|
64
|
+
if (sources.length > 1) {
|
|
65
|
+
if (failCount === 0) {
|
|
66
|
+
console.log(chalk.green(`✓ Copied ${successCount} file(s) to ${destPath}`));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log(chalk.yellow(`⚠ Copied ${successCount} file(s), ${failCount} failed`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=cp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cp.js","sourceRoot":"","sources":["../../../src/builtins/fs/cp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Builtin download command.
|
|
3
|
+
* Downloads files from ChRIS to the local filesystem with progress.
|
|
4
|
+
*/
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { path_resolve } from '../utils.js';
|
|
8
|
+
import { files_downloadWithProgress as chefs_download_cmd, bytes_format } from '@fnndsc/chili/commands/fs/download.js';
|
|
9
|
+
/**
|
|
10
|
+
* Downloads a remote ChRIS file or directory to the local filesystem.
|
|
11
|
+
*
|
|
12
|
+
* @param args - [remotePath, localPath] plus optional -f/--force to overwrite.
|
|
13
|
+
*/
|
|
14
|
+
export async function builtin_download(args) {
|
|
15
|
+
const force = args.includes('-f') || args.includes('--force');
|
|
16
|
+
const cleanArgs = args.filter(arg => arg !== '-f' && arg !== '--force');
|
|
17
|
+
if (cleanArgs.length < 2) {
|
|
18
|
+
console.log(chalk.red('Usage: download <remote_path> <local_path> [-f|--force]'));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const remotePathArg = cleanArgs[0];
|
|
22
|
+
const localPathArg = cleanArgs[1];
|
|
23
|
+
const targetRemote = await path_resolve(remotePathArg);
|
|
24
|
+
const targetLocal = path.resolve(localPathArg);
|
|
25
|
+
try {
|
|
26
|
+
const summary = await chefs_download_cmd(targetRemote, targetLocal, { force });
|
|
27
|
+
console.log('');
|
|
28
|
+
if (summary.failedCount === 0) {
|
|
29
|
+
console.log(chalk.green(`✓ Successfully downloaded ${summary.transferredCount} file(s)`));
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.log(chalk.yellow(`⚠ Downloaded ${summary.transferredCount} file(s), ${summary.failedCount} failed`));
|
|
33
|
+
}
|
|
34
|
+
console.log(chalk.gray(` Total: ${bytes_format(summary.transferSize)} in ${summary.duration.toFixed(1)}s (${bytes_format(summary.speed)}/s)`));
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
38
|
+
console.error(chalk.red(`Download error: ${msg}`));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../src/builtins/fs/download.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,0BAA0B,IAAI,kBAAkB,EAEhD,YAAY,EACb,MAAM,uCAAuC,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAc;IACnD,MAAM,KAAK,GAAY,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvE,MAAM,SAAS,GAAa,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC;IAElF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC,CAAC;QAClF,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAW,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAW,SAAS,CAAC,CAAC,CAAC,CAAC;IAE1C,MAAM,YAAY,GAAW,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAW,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,OAAO,GAAoB,MAAM,kBAAkB,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,IAAI,OAAO,CAAC,WAAW,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,6BAA6B,OAAO,CAAC,gBAAgB,UAAU,CAAC,CAAC,CAAC;QAC5F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,OAAO,CAAC,gBAAgB,aAAa,OAAO,CAAC,WAAW,SAAS,CAAC,CAAC,CAAC;QAC/G,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAClJ,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACpB,MAAM,GAAG,GAAW,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
|