84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import type { IWrappedKvmCommand, TKvmShellHint } from './smartkvm.interfaces.js';
|
|
|
|
export interface IParseWrappedKvmCommandOutputOptions {
|
|
commandId: string;
|
|
startMarker: string;
|
|
endMarkerPrefix: string;
|
|
rawText: string;
|
|
}
|
|
|
|
export interface IParseWrappedKvmCommandOutputResult {
|
|
completed: boolean;
|
|
exitCode?: number;
|
|
combinedText: string;
|
|
}
|
|
|
|
export const createWrappedKvmCommand = (
|
|
command: string,
|
|
shellHint: TKvmShellHint
|
|
): IWrappedKvmCommand => {
|
|
const commandId = plugins.crypto.randomUUID().replace(/-/g, '');
|
|
const startMarker = `SMARTKVM_START_${commandId}`;
|
|
const endMarkerPrefix = `SMARTKVM_END_${commandId}_`;
|
|
|
|
let textToType: string;
|
|
switch (shellHint) {
|
|
case 'powershell':
|
|
textToType = `$__smartkvm_id = "${commandId}"; Write-Output "${startMarker}"; $__smartkvm_status = 0; try { ${command}; if ($null -ne $LASTEXITCODE) { $__smartkvm_status = $LASTEXITCODE } } catch { Write-Output $_; $__smartkvm_status = 1 }; Write-Output "${endMarkerPrefix}$__smartkvm_status"`;
|
|
break;
|
|
case 'cmd':
|
|
textToType = `echo ${startMarker} & ${command} & echo ${endMarkerPrefix}%ERRORLEVEL%`;
|
|
break;
|
|
case 'bash':
|
|
case 'zsh':
|
|
case 'sh':
|
|
case 'unknown':
|
|
default:
|
|
textToType = `printf '\n${startMarker}\n'; ${command}; __smartkvm_status=$?; printf '\n${endMarkerPrefix}%s\n' "$__smartkvm_status"`;
|
|
break;
|
|
}
|
|
|
|
return {
|
|
commandId,
|
|
shellHint,
|
|
command,
|
|
textToType,
|
|
startMarker,
|
|
endMarkerPrefix,
|
|
};
|
|
};
|
|
|
|
export const parseWrappedKvmCommandOutput = (
|
|
options: IParseWrappedKvmCommandOutputOptions
|
|
): IParseWrappedKvmCommandOutputResult => {
|
|
const normalizedRawText = options.rawText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
const startIndex = normalizedRawText.indexOf(options.startMarker);
|
|
if (startIndex === -1) {
|
|
return {
|
|
completed: false,
|
|
combinedText: normalizedRawText,
|
|
};
|
|
}
|
|
|
|
const contentStartIndex = startIndex + options.startMarker.length;
|
|
const endIndex = normalizedRawText.indexOf(options.endMarkerPrefix, contentStartIndex);
|
|
if (endIndex === -1) {
|
|
return {
|
|
completed: false,
|
|
combinedText: normalizedRawText,
|
|
};
|
|
}
|
|
|
|
const endMarkerValueStartIndex = endIndex + options.endMarkerPrefix.length;
|
|
const endMarkerLine = normalizedRawText.slice(endMarkerValueStartIndex).split('\n')[0].trim();
|
|
const exitCodeMatch = endMarkerLine.match(/^-?\d+/);
|
|
const exitCode = exitCodeMatch ? Number.parseInt(exitCodeMatch[0], 10) : undefined;
|
|
|
|
return {
|
|
completed: true,
|
|
exitCode,
|
|
combinedText: normalizedRawText.slice(contentStartIndex, endIndex).trim(),
|
|
};
|
|
};
|