{
  "version": 3,
  "sources": ["../../src/runtime/helpers.ts"],
  "sourcesContent": ["import { type FileHandle, open, opendir, stat } from \"node:fs/promises\";\nimport { basename, delimiter, dirname, extname, join, resolve } from \"node:path\";\nimport type {\n\tCollectorContext,\n\tWorkspaceEntry,\n\tWorkspaceFileSystem,\n\tWorkspaceRefreshInput,\n} from \"./types.js\";\n\nexport const MAX_METADATA_FILE_BYTES = 64 * 1024;\nexport const COMMAND_TIMEOUT_MS = 2_000;\nexport const MAX_COMMAND_OUTPUT_BYTES = 64 * 1024;\nconst MAX_DIRECTORY_ENTRIES = 2_048;\nconst MAX_LABEL_LENGTH = 160;\n\nexport function createFileSystem(input: WorkspaceRefreshInput): WorkspaceFileSystem {\n\tconst defaults: WorkspaceFileSystem = {\n\t\tasync readFile(path, maxBytes) {\n\t\t\tlet handle: FileHandle | undefined;\n\t\t\ttry {\n\t\t\t\thandle = await open(path, \"r\");\n\t\t\t\tconst info = await handle.stat();\n\t\t\t\tif (!info.isFile() || info.size > maxBytes) return undefined;\n\t\t\t\tconst buffer = Buffer.alloc(Math.min(maxBytes + 1, Number(info.size) + 1));\n\t\t\t\tconst { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);\n\t\t\t\tif (bytesRead > maxBytes) return undefined;\n\t\t\t\treturn buffer.subarray(0, bytesRead).toString(\"utf8\");\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t} finally {\n\t\t\t\tawait handle?.close().catch(() => undefined);\n\t\t\t}\n\t\t},\n\t\tasync readDirectory(path) {\n\t\t\tconst entries: WorkspaceEntry[] = [];\n\t\t\ttry {\n\t\t\t\tconst directory = await opendir(path);\n\t\t\t\tfor await (const entry of directory) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\tname: entry.name,\n\t\t\t\t\t\tisFile: entry.isFile(),\n\t\t\t\t\t\tisDirectory: entry.isDirectory(),\n\t\t\t\t\t});\n\t\t\t\t\tif (entries.length >= MAX_DIRECTORY_ENTRIES) break;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\treturn entries;\n\t\t},\n\t\tasync fileExists(path) {\n\t\t\ttry {\n\t\t\t\tawait stat(path);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n\treturn {\n\t\t...defaults,\n\t\t...input.fileSystem,\n\t\t...(input.fileExists ? { fileExists: input.fileExists } : {}),\n\t};\n}\n\nexport function safeMetadata(value: unknown, maxLength = MAX_LABEL_LENGTH): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst sanitized = Array.from(value, (character) => {\n\t\tconst code = character.codePointAt(0) ?? 0;\n\t\treturn code <= 0x1f || (code >= 0x7f && code <= 0x9f) || (code >= 0xd800 && code <= 0xdfff)\n\t\t\t? \"\"\n\t\t\t: character;\n\t})\n\t\t.join(\"\")\n\t\t.trim();\n\tif (!sanitized) return undefined;\n\treturn Array.from(sanitized).slice(0, maxLength).join(\"\");\n}\n\nexport function ownString(record: unknown, key: string): string | undefined {\n\tif (!isRecord(record) || !Object.hasOwn(record, key)) return undefined;\n\treturn safeMetadata(record[key]);\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function setString(record: Record<string, string>, key: string, value: unknown): void {\n\tconst safe = safeMetadata(value);\n\tif (!safe) return;\n\tObject.defineProperty(record, key, {\n\t\tvalue: safe,\n\t\twritable: true,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n}\n\nexport function optionString(\n\tcontext: CollectorContext,\n\tmodule: Parameters<CollectorContext[\"options\"]>[0],\n\tkey: string,\n): string | undefined {\n\tconst value = context.options(module)[key];\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nexport function optionBoolean(\n\tcontext: CollectorContext,\n\tmodule: Parameters<CollectorContext[\"options\"]>[0],\n\tkey: string,\n): boolean {\n\treturn context.options(module)[key] === true;\n}\n\nexport function optionNumber(\n\tcontext: CollectorContext,\n\tmodule: Parameters<CollectorContext[\"options\"]>[0],\n\tkey: string,\n): number | undefined {\n\tconst value = context.options(module)[key];\n\treturn typeof value === \"number\" ? value : undefined;\n}\n\nexport function optionStrings(\n\tcontext: CollectorContext,\n\tmodule: Parameters<CollectorContext[\"options\"]>[0],\n\tkey: string,\n): readonly string[] {\n\tconst value = context.options(module)[key];\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\") ? value : [];\n}\n\nexport function optionMap(\n\tcontext: CollectorContext,\n\tmodule: Parameters<CollectorContext[\"options\"]>[0],\n\tkey: string,\n): Readonly<Record<string, string>> {\n\tconst value = context.options(module)[key];\n\treturn isRecord(value) ? (value as Record<string, string>) : {};\n}\n\nexport function exactAlias(value: string | undefined, aliases: Readonly<Record<string, string>>) {\n\tif (!value) return undefined;\n\treturn Object.hasOwn(aliases, value) ? safeMetadata(aliases[value]) : value;\n}\n\nexport function formatVersion(raw: string, format: string | undefined): string {\n\treturn (format ?? \"v$raw\").replaceAll(\"$raw\", raw.replace(/^v/u, \"\"));\n}\n\nexport async function runBounded(\n\tcontext: CollectorContext,\n\tcommand: string,\n\targs: string[],\n): Promise<string | undefined> {\n\ttry {\n\t\tconst result = await context.input.exec(command, args, {\n\t\t\tcwd: context.input.cwd,\n\t\t\ttimeout: COMMAND_TIMEOUT_MS,\n\t\t\tmaxOutputBytes: MAX_COMMAND_OUTPUT_BYTES,\n\t\t\tsignal: context.input.signal,\n\t\t\tenvironment: context.input.environment,\n\t\t});\n\t\tif (result.code !== 0 || result.killed) return undefined;\n\t\tconst selectedOutput = result.stdout || result.stderr;\n\t\tconst output = Buffer.from(selectedOutput).subarray(0, MAX_COMMAND_OUTPUT_BYTES + 1);\n\t\tif (output.byteLength > MAX_COMMAND_OUTPUT_BYTES) return undefined;\n\t\treturn output.toString(\"utf8\");\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function parseIni(source: string): Record<string, Record<string, string>> {\n\tconst result: Record<string, Record<string, string>> = {};\n\tlet section = \"\";\n\tfor (const rawLine of source.split(/\\r?\\n/u)) {\n\t\tconst line = rawLine.trim();\n\t\tif (!line || line.startsWith(\"#\") || line.startsWith(\";\")) continue;\n\t\tconst sectionMatch = /^\\[([^\\]]+)\\]$/u.exec(line);\n\t\tif (sectionMatch?.[1]) {\n\t\t\tsection = sectionMatch[1].trim();\n\t\t\tif (!Object.hasOwn(result, section)) setOwn(result, section, {});\n\t\t\tcontinue;\n\t\t}\n\t\tconst separator = line.indexOf(\"=\");\n\t\tif (separator <= 0) continue;\n\t\tconst key = line.slice(0, separator).trim();\n\t\tconst value = safeMetadata(line.slice(separator + 1));\n\t\tif (!value) continue;\n\t\tif (!Object.hasOwn(result, section)) setOwn(result, section, {});\n\t\tsetOwn(result[section] as Record<string, string>, key, value);\n\t}\n\treturn result;\n}\n\nexport function envPathList(value: string | undefined): string[] {\n\treturn (value ?? \"\")\n\t\t.split(delimiter)\n\t\t.map((part) => part.trim())\n\t\t.filter(Boolean);\n}\n\nexport function directMatch(\n\tentries: readonly WorkspaceEntry[],\n\tfiles: readonly string[],\n\textensions: readonly string[],\n\tfolders: readonly string[],\n): boolean {\n\tconst positiveFiles = files.filter((value) => !value.startsWith(\"!\"));\n\tconst negativeFiles = new Set(\n\t\tfiles.filter((value) => value.startsWith(\"!\")).map((v) => v.slice(1)),\n\t);\n\tconst positiveExtensions = extensions\n\t\t.filter((value) => !value.startsWith(\"!\"))\n\t\t.map((value) => value.replace(/^\\./u, \"\"));\n\tconst negativeExtensions = new Set(\n\t\textensions\n\t\t\t.filter((value) => value.startsWith(\"!\"))\n\t\t\t.map((value) => value.slice(1).replace(/^\\./u, \"\")),\n\t);\n\tconst positiveFolders = folders.filter((value) => !value.startsWith(\"!\"));\n\tconst negativeFolders = new Set(\n\t\tfolders.filter((value) => value.startsWith(\"!\")).map((value) => value.slice(1)),\n\t);\n\tif (\n\t\tentries.some(\n\t\t\t(entry) =>\n\t\t\t\tnegativeFiles.has(entry.name) ||\n\t\t\t\t(entry.isFile && negativeExtensions.has(extname(entry.name).slice(1))) ||\n\t\t\t\t(entry.isDirectory && negativeFolders.has(entry.name)),\n\t\t)\n\t) {\n\t\treturn false;\n\t}\n\treturn entries.some(\n\t\t(entry) =>\n\t\t\tpositiveFiles.includes(entry.name) ||\n\t\t\t(entry.isFile && positiveExtensions.includes(extname(entry.name).slice(1))) ||\n\t\t\t(entry.isDirectory && positiveFolders.includes(entry.name)),\n\t);\n}\n\nexport function parentDirectories(start: string, limit: number): string[] {\n\tconst result: string[] = [];\n\tlet current = resolve(start);\n\tfor (let index = 0; index < limit; index += 1) {\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tresult.push(parent);\n\t\tcurrent = parent;\n\t}\n\treturn result;\n}\n\nexport function pathName(path: string): string {\n\treturn basename(path.replace(/[\\\\/]+$/u, \"\")) || path;\n}\n\nexport function joinHome(input: WorkspaceRefreshInput, ...parts: string[]): string {\n\treturn join(input.homeDir, ...parts);\n}\n\nfunction setOwn<T>(record: Record<string, T>, key: string, value: T): void {\n\tObject.defineProperty(record, key, {\n\t\tvalue,\n\t\twritable: true,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n}\n"],
  "mappings": "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",
  "names": []
}
