chore: initialize my-pi extension bundle

This commit is contained in:
云服务部-叶林立
2026-08-18 12:30:48 +08:00
parent 7b7b332912
commit 0637139a16
62 changed files with 11055 additions and 1 deletions
@@ -0,0 +1,162 @@
import { splitLeadingEnvAssignments } from "./shell-env-prefix.js";
import { advanceQuoteEscapeState, readShellChars, type QuoteEscapeState } from "./shell-quote-state.js";
interface ParsedPipeline {
segments: string[];
separators: string[];
suffix: string;
}
interface ProducerRewritePlan {
command: string;
captureStderr: boolean;
}
interface ShellSafetyTarget {
environmentPrelude: string;
command: string;
}
const SINGLE_QUOTED_SHELL_VALUE_PATTERN = "'(?:'\\\\''|[^'])*'";
const SHELL_ENV_VALUE_PATTERN = `(?:"(?:\\\\.|[^"])*"|${SINGLE_QUOTED_SHELL_VALUE_PATTERN}|[^\\s;]+)`;
const LEADING_RTK_DB_PATH_EXPORT_PRELUDE_PATTERN = new RegExp(
`^(\\s*export\\s+RTK_DB_PATH=${SHELL_ENV_VALUE_PATTERN}\\s*;\\s*)([\\s\\S]*)$`,
"u",
);
function splitLeadingRtkDbPathExportPrelude(command: string): ShellSafetyTarget {
const match = command.match(LEADING_RTK_DB_PATH_EXPORT_PRELUDE_PATTERN);
if (!match) {
return { environmentPrelude: "", command };
}
return {
environmentPrelude: match[1] ?? "",
command: match[2] ?? "",
};
}
function parseSimpleTopLevelPipeline(command: string): ParsedPipeline | null {
const segments: string[] = [];
const separators: string[] = [];
const state: QuoteEscapeState = { quote: null, escaped: false };
let segmentStart = 0;
let suffix = "";
for (let index = 0; index < command.length; index += 1) {
const { character, nextCharacter } = readShellChars(command, index);
const previousCharacter = index > 0 ? (command[index - 1] ?? "") : "";
if (advanceQuoteEscapeState(state, character, "\"'`")) {
continue;
}
if (
(character === "|" && nextCharacter === "|") ||
(character === "&" && nextCharacter === "&") ||
character === ";"
) {
if (separators.length === 0) {
return null;
}
segments.push(command.slice(segmentStart, index));
suffix = command.slice(index);
break;
}
if (character === "|" && previousCharacter !== ">") {
const separatorLength = nextCharacter === "&" ? 2 : 1;
segments.push(command.slice(segmentStart, index));
separators.push(command.slice(index, index + separatorLength));
segmentStart = index + separatorLength;
if (separatorLength === 2) {
index += 1;
}
continue;
}
if (character === "&" && nextCharacter !== ">" && previousCharacter !== ">" && previousCharacter !== "<") {
return null;
}
}
if (separators.length === 0) {
return null;
}
if (!suffix) {
segments.push(command.slice(segmentStart));
}
return { segments, separators, suffix };
}
function extractProducerRewritePlan(segment: string, firstSeparator: string): ProducerRewritePlan | null {
const trimmed = segment.trim();
const { envPrefix, command: commandWithOptionalRedirect } = splitLeadingEnvAssignments(trimmed);
if (!/^rtk\s+/i.test(commandWithOptionalRedirect)) {
return null;
}
const stderrMergeMatch = commandWithOptionalRedirect.match(/^(.*?)(?:\s+)?2>\s*&1\s*$/u);
if (stderrMergeMatch) {
const command = stderrMergeMatch[1]?.trimEnd() ?? "";
return command ? { command: `${envPrefix}${command}`.trim(), captureStderr: true } : null;
}
return {
command: `${envPrefix}${commandWithOptionalRedirect}`.trim(),
captureStderr: firstSeparator === "|&",
};
}
function buildBufferedPipelineCommand(
producer: ProducerRewritePlan,
remainder: string,
): string {
const tempFileVariable = "__pi_rtk_pipe_tmp";
const statusVariable = "__pi_rtk_pipe_status";
const producerRedirect = producer.captureStderr ? `> "$${tempFileVariable}" 2>&1` : `> "$${tempFileVariable}"`;
const cleanupTrap = `rm -f "$${tempFileVariable}"`;
return [
"{",
`${tempFileVariable}="$(mktemp)" || exit $?;`,
`${statusVariable}=0;`,
`trap '${cleanupTrap}' EXIT HUP INT TERM;`,
`${producer.command} ${producerRedirect};`,
`${statusVariable}=$?;`,
`if [ $${statusVariable} -eq 0 ]; then (${remainder}) < "$${tempFileVariable}"; ${statusVariable}=$?; fi;`,
`exit $${statusVariable};`,
"}",
].join(" ");
}
export function applyRewrittenCommandShellSafetyFixups(command: string, platform: string = process.platform): string {
if (platform !== "win32") {
return command;
}
const target = splitLeadingRtkDbPathExportPrelude(command);
const parsedPipeline = parseSimpleTopLevelPipeline(target.command);
if (!parsedPipeline) {
return command;
}
const producer = extractProducerRewritePlan(parsedPipeline.segments[0] ?? "", parsedPipeline.separators[0] ?? "");
if (!producer) {
return command;
}
const remainder = parsedPipeline.segments
.slice(1)
.map((segment, index) => `${index === 0 ? "" : (parsedPipeline.separators[index] ?? "")}${segment}`)
.join("")
.trim();
if (!remainder) {
return command;
}
const suffix = parsedPipeline.suffix ? ` ${parsedPipeline.suffix.trimStart()}` : "";
return `${target.environmentPrelude}${buildBufferedPipelineCommand(producer, remainder)}${suffix}`;
}