@j0hanz/filesystem-mcp 2.7.6 → 2.8.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/dist/cli.d.ts +1 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/errors.d.ts +4 -3
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +5 -16
- package/dist/core/errors.js.map +1 -1
- package/dist/core/fs.d.ts +11 -11
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +108 -43
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +8 -0
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +192 -29
- package/dist/core/glob.js.map +1 -1
- package/dist/core/input-required.d.ts +12 -0
- package/dist/core/input-required.d.ts.map +1 -1
- package/dist/core/input-required.js +7 -2
- package/dist/core/input-required.js.map +1 -1
- package/dist/core/observability.d.ts +2 -0
- package/dist/core/observability.d.ts.map +1 -1
- package/dist/core/observability.js +7 -0
- package/dist/core/observability.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +11 -30
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path.d.ts +0 -2
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +12 -29
- package/dist/core/path.js.map +1 -1
- package/dist/core/read.d.ts +1 -1
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +13 -14
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts +6 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +17 -3
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +104 -51
- package/dist/core/search.js.map +1 -1
- package/dist/core/store.d.ts +36 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +71 -6
- package/dist/core/store.js.map +1 -1
- package/dist/core/util.d.ts +34 -5
- package/dist/core/util.d.ts.map +1 -1
- package/dist/core/util.js +59 -5
- package/dist/core/util.js.map +1 -1
- package/dist/index.js +5 -16
- package/dist/index.js.map +1 -1
- package/dist/resources.d.ts +5 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +45 -22
- package/dist/resources.js.map +1 -1
- package/dist/server.d.ts +9 -6
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +7 -8
- package/dist/server.js.map +1 -1
- package/dist/tools/create.d.ts.map +1 -1
- package/dist/tools/create.js +8 -19
- package/dist/tools/create.js.map +1 -1
- package/dist/tools/define.d.ts +8 -7
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +48 -16
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete.d.ts.map +1 -1
- package/dist/tools/delete.js +39 -21
- package/dist/tools/delete.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +24 -39
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +49 -60
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/index.d.ts +2 -11
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -9
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +59 -69
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +5 -1
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/patch.d.ts.map +1 -1
- package/dist/tools/patch.js +3 -6
- package/dist/tools/patch.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +31 -40
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts.map +1 -1
- package/dist/tools/replace-text.js +23 -32
- package/dist/tools/replace-text.js.map +1 -1
- package/dist/tools/search-text.d.ts.map +1 -1
- package/dist/tools/search-text.js +48 -64
- package/dist/tools/search-text.js.map +1 -1
- package/dist/transport/http.js +1 -1
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/shared.d.ts +7 -5
- package/dist/transport/shared.d.ts.map +1 -1
- package/dist/transport/shared.js +8 -2
- package/dist/transport/shared.js.map +1 -1
- package/dist/transport/stdio.d.ts +4 -1
- package/dist/transport/stdio.d.ts.map +1 -1
- package/dist/transport/stdio.js +45 -12
- package/dist/transport/stdio.js.map +1 -1
- package/package.json +3 -2
package/dist/cli.d.ts
CHANGED
|
@@ -10,13 +10,5 @@ export declare function parseArgs(): Promise<{
|
|
|
10
10
|
httpHost: string | undefined;
|
|
11
11
|
apiKey: string | undefined;
|
|
12
12
|
}>;
|
|
13
|
-
export declare function runPrintConfig(options:
|
|
14
|
-
allowedDirs: string[];
|
|
15
|
-
allowCwd: boolean;
|
|
16
|
-
readOnly: boolean;
|
|
17
|
-
/** Resolved `--port`. Present means the launch this reports on is an HTTP bind. */
|
|
18
|
-
port?: number;
|
|
19
|
-
httpHost?: string;
|
|
20
|
-
apiKey?: string;
|
|
21
|
-
}): Promise<void>;
|
|
13
|
+
export declare function runPrintConfig(options: Awaited<ReturnType<typeof parseArgs>>): Promise<void>;
|
|
22
14
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA0BA,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAyGD,wBAAsB,SAAS,IAAI,OAAO,CAAC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC,CAqED;AAMD,wBAAsB,cAAc,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA0BA,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAyGD,wBAAsB,SAAS,IAAI,OAAO,CAAC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC,CAqED;AAMD,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAmDf"}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from '@modelcontextprotocol/server';\n\nimport type { Stats } from 'node:fs';\nimport { stat } from 'node:fs/promises';\nimport { parseArgs as utilParseArgs } from 'node:util';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { printHelpAndExit, printVersionAndExit } from './cli-help.ts';\nimport { cli, MODERN_PROTOCOL_REVISION } from './core/config.ts';\nimport { formatUnknownErrorMessage } from './core/errors.ts';\nimport {\n getReservedDeviceNameForPath,\n IS_WINDOWS,\n isWindowsDriveRelativePath,\n normalizePath,\n parseTrueEnvFlag,\n} from './core/path-utils.ts';\nimport { PathGuard } from './core/path.ts';\nimport { describeSensitivePolicy } from './core/sensitive.ts';\nimport { getMaxInboundMessageBytes, getMaxTextFileSize } from './core/util.ts';\nimport { registeredTools } from './tools/index.ts';\n\n// ════════════════════════════════════════════════════════════\n// Path & Config Utilities — pure functions and error types\n// ════════════════════════════════════════════════════════════\n\nexport class CliExitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliExitError';\n }\n}\n\nfunction validateCliPath(inputPath: string): void {\n if (inputPath.includes('\\0')) {\n throw new CliExitError('Path contains null bytes.');\n }\n\n if (isWindowsDriveRelativePath(inputPath)) {\n throw new CliExitError(\n 'Windows drive-relative paths are not allowed. Use C:\\\\path or C:/path instead of C:path.',\n );\n }\n\n const reserved = IS_WINDOWS ? getReservedDeviceNameForPath(inputPath) : undefined;\n if (reserved) {\n throw new CliExitError(`Windows reserved device name not allowed: ${reserved}.`);\n }\n}\n\nasync function validateDirectoryPath(inputPath: string, allowMissing = false): Promise<string> {\n const normalized = normalizePath(inputPath);\n\n let stats: Stats;\n try {\n stats = await stat(normalized);\n } catch (error) {\n if (allowMissing) return normalized;\n // Node's own message already names the syscall and the errno.\n throw new Error(`Cannot access directory ${inputPath}: ${formatUnknownErrorMessage(error)}`, {\n cause: error,\n });\n }\n\n if (!stats.isDirectory()) throw new Error(`${inputPath} is not a directory`);\n return normalized;\n}\n\n// No dedupe here: PathGuard's `normalizeAllowedDirectories` already Set-dedupes\n// the normalized set, and containment checks are case-insensitive where the\n// filesystem is.\nasync function normalizeAndValidateDirs(\n paths: readonly string[],\n allowMissing = false,\n): Promise<string[]> {\n const normalized: string[] = [];\n for (const p of paths) {\n normalized.push(await validateDirectoryPath(p, allowMissing));\n }\n return normalized;\n}\n\nfunction normalizeCliExitMessage(error: unknown): string {\n const rawMessage = formatUnknownErrorMessage(error);\n return rawMessage.startsWith('Error:') ? rawMessage : `Error: ${rawMessage}`;\n}\n\nfunction parsePortOption(raw: unknown): number | undefined {\n // '' reads as unset: FS_PORT set-but-empty (compose templating) means stdio.\n if (raw === undefined || raw === '') return undefined;\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n throw new CliExitError(`Error: --port / FS_PORT must be an integer between 1 and 65535`);\n }\n return n;\n}\n\nconst ENV_PLACEHOLDER = /^\\$\\{([A-Za-z_]\\w*)\\}$/;\n\n/**\n * Plugin hosts start servers outside the project and substitute only the\n * variables they know: Antigravity CLI passes `${PWD}` through verbatim, and\n * Copilot CLI does when the launching shell exported no PWD (PowerShell, cmd).\n * A whole-argument `${NAME}` resolves from this process's environment; unset\n * or empty drops it, so it never becomes a bogus relative root.\n */\nfunction expandEnvPlaceholder(arg: string): string[] {\n const name = ENV_PLACEHOLDER.exec(arg)?.[1];\n if (name === undefined) return [arg];\n const value = process.env[name];\n return value ? [value] : [];\n}\n\nconst CLI_PARSER_CONFIG = {\n options: {\n 'allow-cwd': { type: 'boolean', default: false },\n 'read-only': { type: 'boolean', default: false },\n 'print-config': { type: 'boolean', default: false },\n port: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n 'log-level': { type: 'string' },\n 'http-host': { type: 'string' },\n 'api-key': { type: 'string' },\n 'allow-sensitive': { type: 'boolean', default: false },\n 'root-boundary': { type: 'string' },\n 'max-file-size': { type: 'string' },\n 'walk-cwd': { type: 'boolean', default: false },\n deny: { type: 'string', multiple: true },\n allow: { type: 'string', multiple: true },\n 'allow-missing-roots': { type: 'boolean', default: false },\n },\n strict: true,\n allowPositionals: true,\n} as const;\n\nexport async function parseArgs(): Promise<{\n allowedDirs: string[];\n allowCwd: boolean;\n port: number | undefined;\n readOnly: boolean;\n printConfig: boolean;\n httpHost: string | undefined;\n apiKey: string | undefined;\n}> {\n try {\n const parsed = utilParseArgs(CLI_PARSER_CONFIG);\n\n if (parsed.values.help) {\n printHelpAndExit();\n }\n\n if (parsed.values.version) {\n printVersionAndExit();\n }\n\n const positionals = parsed.positionals.flatMap(expandEnvPlaceholder);\n for (const positional of positionals) {\n validateCliPath(positional);\n }\n\n const v = parsed.values;\n // `--http-host` and `--api-key` are returned to the caller and handed to\n // the server as config. Every other flag lands in the CLI-override store\n // (core/config.ts) — the one owner of the flag-beats-env rule — which deep\n // core readers (path, sensitive, observability, util) consult before\n // falling back to the operator's environment. Nothing writes process.env.\n const httpHost = v['http-host'] ?? process.env['FS_HTTP_HOST'];\n const apiKey = v['api-key'] ?? process.env['FS_API_KEY'];\n if (v['log-level'] !== undefined) cli.logLevel = v['log-level'];\n if (v['max-file-size'] !== undefined) cli.maxFileSize = v['max-file-size'];\n if (v['root-boundary'] !== undefined) cli.rootBoundary = v['root-boundary'];\n if (v['allow-sensitive']) cli.allowSensitive = true;\n if (v['walk-cwd']) cli.allowCwdWalk = true;\n if (v['allow-missing-roots']) cli.allowMissingRoots = true;\n const patternList = (entries: readonly string[] | undefined): readonly string[] => [\n ...new Set((entries ?? []).map((entry) => entry.trim()).filter(Boolean)),\n ];\n const denyPatterns = patternList(v.deny);\n if (denyPatterns.length > 0) cli.denyPatterns = denyPatterns;\n const allowPatterns = patternList(v.allow);\n if (allowPatterns.length > 0) cli.allowPatterns = allowPatterns;\n\n const allowCwd =\n v['allow-cwd'] ||\n v['walk-cwd'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_CWD_WALK'], 'FS_ALLOW_CWD_WALK');\n const readOnly = v['read-only'];\n const printConfig = v['print-config'];\n const port = parsePortOption(v.port ?? process.env['FS_PORT']);\n const allowMissingRoots =\n v['allow-missing-roots'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS');\n\n const allowedDirs =\n positionals.length > 0 ? await normalizeAndValidateDirs(positionals, allowMissingRoots) : [];\n\n return {\n allowedDirs,\n allowCwd,\n port,\n readOnly,\n printConfig,\n httpHost,\n apiKey,\n };\n } catch (error: unknown) {\n if (error instanceof CliExitError) {\n throw error;\n }\n\n throw new CliExitError(normalizeCliExitMessage(error));\n }\n}\n\n// ════════════════════════════════════════════════════════════\n// Effective config reporting — prints the resolved server config as JSON\n// ════════════════════════════════════════════════════════════\n\nexport async function runPrintConfig(options: {\n allowedDirs: string[];\n allowCwd: boolean;\n readOnly: boolean;\n /** Resolved `--port`. Present means the launch this reports on is an HTTP bind. */\n port?: number;\n httpHost?: string;\n apiKey?: string;\n}): Promise<void> {\n const pathGuard = new PathGuard({\n allowCwd: options.allowCwd,\n cliAllowedDirs: options.allowedDirs,\n });\n await pathGuard.recomputeAllowedDirectories();\n const allowedRoots = pathGuard.getRoots();\n\n const tools = registeredTools(options.readOnly).map((t) => t.name);\n\n // Derived, never assumed: `--print-config --port 3000` reports the HTTP bind\n // that `--port` would actually have started, not the stdio default.\n const config = {\n transport:\n options.port !== undefined\n ? `http://${options.httpHost ?? '127.0.0.1'}:${String(options.port)}`\n : 'stdio',\n readOnly: options.readOnly,\n allowedRoots,\n tools,\n apiKey: options.apiKey ? '***' : null,\n limits: {\n maxFileSizeBytes: getMaxTextFileSize(),\n maxInboundMessageBytes: getMaxInboundMessageBytes(),\n },\n // What the binary negotiates with, so an era mismatch (\"unsupported\n // protocol version\") can be diagnosed without attaching a client. The\n // legacy list is the SDK's own; the modern revision has no SDK export.\n // The pins are exact (package.json), so the manifest value is the\n // installed one.\n protocol: {\n modern: MODERN_PROTOCOL_REVISION,\n legacy: { latest: LATEST_PROTOCOL_VERSION, supported: SUPPORTED_PROTOCOL_VERSIONS },\n sdk: {\n server: packageJson.dependencies['@modelcontextprotocol/server'],\n node: packageJson.dependencies['@modelcontextprotocol/node'],\n express: packageJson.dependencies['@modelcontextprotocol/express'],\n },\n },\n // Everything that can produce ACCESS_DENIED, read through the same\n // sources the guard and the matcher use (flag beats env).\n policy: {\n ...describeSensitivePolicy(),\n rootBoundary: cli.rootBoundary ?? process.env['FS_ROOT_BOUNDARY'] ?? null,\n allowMissingRoots:\n cli.allowMissingRoots ??\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS'),\n },\n };\n\n process.stdout.write(`${JSON.stringify(config, null, 2)}\\n`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from '@modelcontextprotocol/server';\n\nimport type { Stats } from 'node:fs';\nimport { stat } from 'node:fs/promises';\nimport { parseArgs as utilParseArgs } from 'node:util';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { printHelpAndExit, printVersionAndExit } from './cli-help.ts';\nimport { cli, MODERN_PROTOCOL_REVISION } from './core/config.ts';\nimport { formatUnknownErrorMessage } from './core/errors.ts';\nimport {\n getReservedDeviceNameForPath,\n IS_WINDOWS,\n isWindowsDriveRelativePath,\n normalizePath,\n parseTrueEnvFlag,\n} from './core/path-utils.ts';\nimport { PathGuard } from './core/path.ts';\nimport { describeSensitivePolicy } from './core/sensitive.ts';\nimport { getMaxInboundMessageBytes, getMaxTextFileSize } from './core/util.ts';\nimport { registeredTools } from './tools/index.ts';\n\n// ════════════════════════════════════════════════════════════\n// Path & Config Utilities — pure functions and error types\n// ════════════════════════════════════════════════════════════\n\nexport class CliExitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliExitError';\n }\n}\n\nfunction validateCliPath(inputPath: string): void {\n if (inputPath.includes('\\0')) {\n throw new CliExitError('Path contains null bytes.');\n }\n\n if (isWindowsDriveRelativePath(inputPath)) {\n throw new CliExitError(\n 'Windows drive-relative paths are not allowed. Use C:\\\\path or C:/path instead of C:path.',\n );\n }\n\n const reserved = IS_WINDOWS ? getReservedDeviceNameForPath(inputPath) : undefined;\n if (reserved) {\n throw new CliExitError(`Windows reserved device name not allowed: ${reserved}.`);\n }\n}\n\nasync function validateDirectoryPath(inputPath: string, allowMissing = false): Promise<string> {\n const normalized = normalizePath(inputPath);\n\n let stats: Stats;\n try {\n stats = await stat(normalized);\n } catch (error) {\n if (allowMissing) return normalized;\n // Node's own message already names the syscall and the errno.\n throw new Error(`Cannot access directory ${inputPath}: ${formatUnknownErrorMessage(error)}`, {\n cause: error,\n });\n }\n\n if (!stats.isDirectory()) throw new Error(`${inputPath} is not a directory`);\n return normalized;\n}\n\n// No dedupe here: PathGuard's `normalizeAllowedDirectories` already Set-dedupes\n// the normalized set, and containment checks are case-insensitive where the\n// filesystem is.\nasync function normalizeAndValidateDirs(\n paths: readonly string[],\n allowMissing = false,\n): Promise<string[]> {\n const normalized: string[] = [];\n for (const p of paths) {\n normalized.push(await validateDirectoryPath(p, allowMissing));\n }\n return normalized;\n}\n\nfunction normalizeCliExitMessage(error: unknown): string {\n const rawMessage = formatUnknownErrorMessage(error);\n return rawMessage.startsWith('Error:') ? rawMessage : `Error: ${rawMessage}`;\n}\n\nfunction parsePortOption(raw: unknown): number | undefined {\n // '' reads as unset: FS_PORT set-but-empty (compose templating) means stdio.\n if (raw === undefined || raw === '') return undefined;\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n throw new CliExitError(`Error: --port / FS_PORT must be an integer between 1 and 65535`);\n }\n return n;\n}\n\nconst ENV_PLACEHOLDER = /^\\$\\{([A-Za-z_]\\w*)\\}$/;\n\n/**\n * Plugin hosts start servers outside the project and substitute only the\n * variables they know: Antigravity CLI passes `${PWD}` through verbatim, and\n * Copilot CLI does when the launching shell exported no PWD (PowerShell, cmd).\n * A whole-argument `${NAME}` resolves from this process's environment; unset\n * or empty drops it, so it never becomes a bogus relative root.\n */\nfunction expandEnvPlaceholder(arg: string): string[] {\n const name = ENV_PLACEHOLDER.exec(arg)?.[1];\n if (name === undefined) return [arg];\n const value = process.env[name];\n return value ? [value] : [];\n}\n\nconst CLI_PARSER_CONFIG = {\n options: {\n 'allow-cwd': { type: 'boolean', default: false },\n 'read-only': { type: 'boolean', default: false },\n 'print-config': { type: 'boolean', default: false },\n port: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n 'log-level': { type: 'string' },\n 'http-host': { type: 'string' },\n 'api-key': { type: 'string' },\n 'allow-sensitive': { type: 'boolean', default: false },\n 'root-boundary': { type: 'string' },\n 'max-file-size': { type: 'string' },\n 'walk-cwd': { type: 'boolean', default: false },\n deny: { type: 'string', multiple: true },\n allow: { type: 'string', multiple: true },\n 'allow-missing-roots': { type: 'boolean', default: false },\n },\n strict: true,\n allowPositionals: true,\n} as const;\n\nexport async function parseArgs(): Promise<{\n allowedDirs: string[];\n allowCwd: boolean;\n port: number | undefined;\n readOnly: boolean;\n printConfig: boolean;\n httpHost: string | undefined;\n apiKey: string | undefined;\n}> {\n try {\n const parsed = utilParseArgs(CLI_PARSER_CONFIG);\n\n if (parsed.values.help) {\n printHelpAndExit();\n }\n\n if (parsed.values.version) {\n printVersionAndExit();\n }\n\n const positionals = parsed.positionals.flatMap(expandEnvPlaceholder);\n for (const positional of positionals) {\n validateCliPath(positional);\n }\n\n const v = parsed.values;\n // `--http-host` and `--api-key` are returned to the caller and handed to\n // the server as config. Every other flag lands in the CLI-override store\n // (core/config.ts) — the one owner of the flag-beats-env rule — which deep\n // core readers (path, sensitive, observability, util) consult before\n // falling back to the operator's environment. Nothing writes process.env.\n const httpHost = v['http-host'] ?? process.env['FS_HTTP_HOST'];\n const apiKey = v['api-key'] ?? process.env['FS_API_KEY'];\n if (v['log-level'] !== undefined) cli.logLevel = v['log-level'];\n if (v['max-file-size'] !== undefined) cli.maxFileSize = v['max-file-size'];\n if (v['root-boundary'] !== undefined) cli.rootBoundary = v['root-boundary'];\n if (v['allow-sensitive']) cli.allowSensitive = true;\n if (v['walk-cwd']) cli.allowCwdWalk = true;\n if (v['allow-missing-roots']) cli.allowMissingRoots = true;\n const patternList = (entries: readonly string[] | undefined): readonly string[] => [\n ...new Set((entries ?? []).map((entry) => entry.trim()).filter(Boolean)),\n ];\n const denyPatterns = patternList(v.deny);\n if (denyPatterns.length > 0) cli.denyPatterns = denyPatterns;\n const allowPatterns = patternList(v.allow);\n if (allowPatterns.length > 0) cli.allowPatterns = allowPatterns;\n\n const allowCwd =\n v['allow-cwd'] ||\n v['walk-cwd'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_CWD_WALK'], 'FS_ALLOW_CWD_WALK');\n const readOnly = v['read-only'];\n const printConfig = v['print-config'];\n const port = parsePortOption(v.port ?? process.env['FS_PORT']);\n const allowMissingRoots =\n v['allow-missing-roots'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS');\n\n const allowedDirs =\n positionals.length > 0 ? await normalizeAndValidateDirs(positionals, allowMissingRoots) : [];\n\n return {\n allowedDirs,\n allowCwd,\n port,\n readOnly,\n printConfig,\n httpHost,\n apiKey,\n };\n } catch (error: unknown) {\n if (error instanceof CliExitError) {\n throw error;\n }\n\n throw new CliExitError(normalizeCliExitMessage(error));\n }\n}\n\n// ════════════════════════════════════════════════════════════\n// Effective config reporting — prints the resolved server config as JSON\n// ════════════════════════════════════════════════════════════\n\nexport async function runPrintConfig(\n options: Awaited<ReturnType<typeof parseArgs>>,\n): Promise<void> {\n const pathGuard = new PathGuard({\n allowCwd: options.allowCwd,\n cliAllowedDirs: options.allowedDirs,\n });\n await pathGuard.recomputeAllowedDirectories();\n const allowedRoots = pathGuard.getRoots();\n\n const tools = registeredTools(options.readOnly).map((t) => t.name);\n\n // Derived, never assumed: `--print-config --port 3000` reports the HTTP bind\n // that `--port` would actually have started, not the stdio default.\n const config = {\n transport:\n options.port !== undefined\n ? `http://${options.httpHost ?? '127.0.0.1'}:${String(options.port)}`\n : 'stdio',\n readOnly: options.readOnly,\n allowedRoots,\n tools,\n apiKey: options.apiKey ? '***' : null,\n limits: {\n maxFileSizeBytes: getMaxTextFileSize(),\n maxInboundMessageBytes: getMaxInboundMessageBytes(),\n },\n // What the binary negotiates with, so an era mismatch (\"unsupported\n // protocol version\") can be diagnosed without attaching a client. The\n // legacy list is the SDK's own; the modern revision has no SDK export.\n // The pins are exact (package.json), so the manifest value is the\n // installed one.\n protocol: {\n modern: MODERN_PROTOCOL_REVISION,\n legacy: { latest: LATEST_PROTOCOL_VERSION, supported: SUPPORTED_PROTOCOL_VERSIONS },\n sdk: {\n server: packageJson.dependencies['@modelcontextprotocol/server'],\n node: packageJson.dependencies['@modelcontextprotocol/node'],\n express: packageJson.dependencies['@modelcontextprotocol/express'],\n },\n },\n // Everything that can produce ACCESS_DENIED, read through the same\n // sources the guard and the matcher use (flag beats env).\n policy: {\n ...describeSensitivePolicy(),\n rootBoundary: cli.rootBoundary ?? process.env['FS_ROOT_BOUNDARY'] ?? null,\n allowMissingRoots:\n cli.allowMissingRoots ??\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS'),\n },\n };\n\n process.stdout.write(`${JSON.stringify(config, null, 2)}\\n`);\n}\n"]}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -21,8 +21,8 @@ export interface Problem {
|
|
|
21
21
|
readonly suggestion?: string;
|
|
22
22
|
}
|
|
23
23
|
interface ProblemFactoryOptions {
|
|
24
|
-
path?: string;
|
|
25
|
-
suggestion?: string;
|
|
24
|
+
path?: string | undefined;
|
|
25
|
+
suggestion?: string | undefined;
|
|
26
26
|
}
|
|
27
27
|
export declare const Problem: {
|
|
28
28
|
readonly invalidInput: (msg: string, o?: ProblemFactoryOptions) => Problem;
|
|
@@ -51,7 +51,8 @@ export declare function formatUnknownErrorMessage(error: unknown): string;
|
|
|
51
51
|
export declare function normalizeUnknownError(error: unknown): Error;
|
|
52
52
|
export declare class FsError extends Error {
|
|
53
53
|
readonly problem: Problem;
|
|
54
|
-
|
|
54
|
+
/** `suggestion` replaces the code's default for a thrower that knows the better next step. */
|
|
55
|
+
constructor(code: ErrorCode, message: string, path?: string, cause?: unknown, suggestion?: string | undefined);
|
|
55
56
|
get code(): ErrorCode;
|
|
56
57
|
}
|
|
57
58
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;CAcZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;CAcZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAWD,eAAO,MAAM,OAAO;iCACE,MAAM,MAAM,qBAAqB,KAAG,OAAO;iCAE3C,MAAM,MAAM,qBAAqB,KAAG,OAAO;8BAE9C,MAAM,MAAM,qBAAqB,KAAG,OAAO;kCAEzC,OAAO,eAAe,SAAS,SAAS,MAAM,KAAG,OAAO;6BAW7D,OAAO,eAAe,SAAS,KAAG,MAAM;CAG9C,CAAC;AAoCX,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,SAAS,CAOpD,CAAC;AA0CH,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS1D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAE1D;AAoBD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAK1E;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAE9E;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAMrD;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQhE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAE3D;AAeD,qBAAa,OAAQ,SAAQ,KAAK;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,8FAA8F;gBAE5F,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,OAAO,EACf,UAAU,GAAE,MAAM,GAAG,SAAqC;IAO5D,IAAI,IAAI,IAAI,SAAS,CAEpB;CACF"}
|
package/dist/core/errors.js
CHANGED
|
@@ -32,11 +32,7 @@ export const Problem = {
|
|
|
32
32
|
const suggestion = (shouldOverride ? DEFAULT_SUGGESTIONS[code] : undefined) ??
|
|
33
33
|
problem.suggestion ??
|
|
34
34
|
DEFAULT_SUGGESTIONS[problem.code];
|
|
35
|
-
|
|
36
|
-
return build(code, problem.message, {
|
|
37
|
-
...(resolvedPath !== undefined ? { path: resolvedPath } : {}),
|
|
38
|
-
...(suggestion !== undefined ? { suggestion } : {}),
|
|
39
|
-
});
|
|
35
|
+
return build(code, problem.message, { path: path ?? problem.path, suggestion });
|
|
40
36
|
},
|
|
41
37
|
toText(error, defaultCode) {
|
|
42
38
|
return formatDetailedError(Problem.fromUnknown(error, defaultCode));
|
|
@@ -121,9 +117,7 @@ export function classifyCauseChain(error) {
|
|
|
121
117
|
if (timedOut)
|
|
122
118
|
return build(ErrorCode.TIMEOUT, message);
|
|
123
119
|
if (errno !== undefined) {
|
|
124
|
-
return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, {
|
|
125
|
-
...(errno.path !== undefined ? { path: errno.path } : {}),
|
|
126
|
-
});
|
|
120
|
+
return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, { path: errno.path });
|
|
127
121
|
}
|
|
128
122
|
return build(ErrorCode.UNKNOWN, message);
|
|
129
123
|
}
|
|
@@ -206,15 +200,10 @@ function formatDetailedError(error) {
|
|
|
206
200
|
}
|
|
207
201
|
export class FsError extends Error {
|
|
208
202
|
problem;
|
|
209
|
-
|
|
203
|
+
/** `suggestion` replaces the code's default for a thrower that knows the better next step. */
|
|
204
|
+
constructor(code, message, path, cause, suggestion = DEFAULT_SUGGESTIONS[code]) {
|
|
210
205
|
super(message, cause === undefined ? {} : { cause });
|
|
211
|
-
|
|
212
|
-
this.problem = {
|
|
213
|
-
code,
|
|
214
|
-
message,
|
|
215
|
-
...(path !== undefined ? { path } : {}),
|
|
216
|
-
...(suggestion !== undefined ? { suggestion } : {}),
|
|
217
|
-
};
|
|
206
|
+
this.problem = build(code, message, { path, suggestion });
|
|
218
207
|
this.name = 'FsError';
|
|
219
208
|
}
|
|
220
209
|
get code() {
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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","sourcesContent":["export const ErrorCode = {\n ACCESS_DENIED: 'ACCESS_DENIED',\n NOT_FOUND: 'NOT_FOUND',\n NOT_FILE: 'NOT_FILE',\n NOT_DIRECTORY: 'NOT_DIRECTORY',\n TOO_LARGE: 'TOO_LARGE',\n TIMEOUT: 'TIMEOUT',\n CANCELLED: 'CANCELLED',\n INVALID_PATTERN: 'INVALID_PATTERN',\n INVALID_INPUT: 'INVALID_INPUT',\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n SYMLINK_NOT_ALLOWED: 'SYMLINK_NOT_ALLOWED',\n IO_ERROR: 'IO_ERROR',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport interface Problem {\n readonly code: ErrorCode;\n readonly message: string;\n readonly path?: string;\n readonly suggestion?: string;\n}\n\ninterface ProblemFactoryOptions {\n path?: string;\n suggestion?: string;\n}\n\nfunction build(code: ErrorCode, message: string, opts: ProblemFactoryOptions = {}): Problem {\n return {\n code,\n message,\n ...(opts.path !== undefined ? { path: opts.path } : {}),\n ...(opts.suggestion !== undefined ? { suggestion: opts.suggestion } : {}),\n };\n}\n\nexport const Problem = {\n invalidInput: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.INVALID_INPUT, msg, o),\n accessDenied: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.ACCESS_DENIED, msg, o),\n cancelled: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.CANCELLED, msg, o),\n fromUnknown(error: unknown, defaultCode: ErrorCode, path?: string): Problem {\n const problem = classify(error);\n const shouldOverride =\n problem.code === ErrorCode.UNKNOWN || problem.code === ErrorCode.IO_ERROR;\n const code = shouldOverride ? defaultCode : problem.code;\n const suggestion =\n (shouldOverride ? DEFAULT_SUGGESTIONS[code] : undefined) ??\n problem.suggestion ??\n DEFAULT_SUGGESTIONS[problem.code];\n const resolvedPath = path ?? problem.path;\n return build(code, problem.message, {\n ...(resolvedPath !== undefined ? { path: resolvedPath } : {}),\n ...(suggestion !== undefined ? { suggestion } : {}),\n });\n },\n toText(error: unknown, defaultCode: ErrorCode): string {\n return formatDetailedError(Problem.fromUnknown(error, defaultCode));\n },\n} as const;\n\nconst DEFAULT_SUGGESTIONS: Readonly<Partial<Record<ErrorCode, string>>> = {\n [ErrorCode.ACCESS_DENIED]: 'Run list_roots to list allowed directories.',\n [ErrorCode.NOT_FOUND]: 'Run list or find_files to verify the path.',\n [ErrorCode.NOT_FILE]: 'Target is a directory, not a file.',\n [ErrorCode.NOT_DIRECTORY]: 'Target is a file, not a directory.',\n [ErrorCode.TOO_LARGE]: 'Use head/tail or line ranges to read partially.',\n [ErrorCode.TIMEOUT]: 'Reduce scope, depth, or maxResults.',\n [ErrorCode.INVALID_PATTERN]: 'Check syntax and escape special characters.',\n [ErrorCode.PERMISSION_DENIED]: 'Check OS file permissions.',\n [ErrorCode.SYMLINK_NOT_ALLOWED]: 'Symlink escapes allowed directories.',\n};\n\nconst ERRNO_MAP: Readonly<Record<string, ErrorCode>> = {\n ENOENT: ErrorCode.NOT_FOUND,\n EACCES: ErrorCode.PERMISSION_DENIED,\n EPERM: ErrorCode.PERMISSION_DENIED,\n ENOTDIR: ErrorCode.NOT_DIRECTORY,\n EISDIR: ErrorCode.NOT_FILE,\n ELOOP: ErrorCode.SYMLINK_NOT_ALLOWED,\n ENAMETOOLONG: ErrorCode.INVALID_INPUT,\n ETIMEDOUT: ErrorCode.TIMEOUT,\n EMFILE: ErrorCode.IO_ERROR,\n ENFILE: ErrorCode.IO_ERROR,\n EBUSY: ErrorCode.IO_ERROR,\n ENOTEMPTY: ErrorCode.NOT_DIRECTORY,\n EEXIST: ErrorCode.INVALID_INPUT,\n EINVAL: ErrorCode.INVALID_INPUT,\n};\n\nconst ERRNO_RE = /^E[A-Z]+$/;\n\n// NOT_FOUND is in here (not just ENOENT) because a dangling symlink whose\n// target sits inside an allowed root surfaces as an FsError NOT_FOUND. Skipping\n// the entry is the point of a listing; rethrowing would fail the whole listing.\nexport const SKIPPABLE_FS_CODES: ReadonlySet<ErrorCode> = new Set([\n ErrorCode.ACCESS_DENIED,\n ErrorCode.NOT_FOUND,\n // OS-level EACCES/EPERM on a symlink target during a listing is exactly as\n // skippable as the other three codes.\n ErrorCode.PERMISSION_DENIED,\n ErrorCode.SYMLINK_NOT_ALLOWED,\n]);\n\nconst SKIPPABLE_ERRNOS: ReadonlySet<string> = new Set(['ENOENT', 'EACCES', 'ELOOP']);\n\n/**\n * Walk `error` and its `cause` chain once for the three facts error handling\n * needs: an abort anywhere, a timeout anywhere, and the FIRST errno seen.\n * `visited` guards a cyclic chain. A node that reads as an abort or a timeout\n * never also contributes its errno.\n */\nfunction scanCauseChain(error: unknown): {\n aborted: boolean;\n timedOut: boolean;\n errno: { code: string; path?: string } | undefined;\n} {\n const visited = new Set<unknown>();\n let aborted = false;\n let timedOut = false;\n let errno: { code: string; path?: string } | undefined;\n\n for (\n let current: unknown = error;\n current !== undefined && current !== null && !visited.has(current);\n current = (current as { cause?: unknown }).cause\n ) {\n visited.add(current);\n if (!(current instanceof Error)) continue;\n const raw = (current as { code?: unknown }).code;\n const code = typeof raw === 'string' ? raw : undefined;\n if (current.name === 'AbortError' || code === 'ABORT_ERR') {\n aborted = true;\n } else if (current.name === 'TimeoutError' || code === 'ETIMEDOUT') {\n timedOut = true;\n } else if (errno === undefined && code !== undefined && ERRNO_RE.test(code)) {\n const { path } = current as NodeJS.ErrnoException;\n errno = { code, ...(typeof path === 'string' ? { path } : {}) };\n }\n }\n\n return { aborted, timedOut, errno };\n}\n\n/** The scan's facts as a Problem: an abort wins, then a timeout, then errno. */\nexport function classifyCauseChain(error: unknown): Problem {\n const message = formatUnknownErrorMessage(error);\n const { aborted, timedOut, errno } = scanCauseChain(error);\n if (aborted) return Problem.cancelled(message);\n if (timedOut) return build(ErrorCode.TIMEOUT, message);\n if (errno !== undefined) {\n return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, {\n ...(errno.path !== undefined ? { path: errno.path } : {}),\n });\n }\n return build(ErrorCode.UNKNOWN, message);\n}\n\nexport function isFsError(error: unknown): error is FsError {\n return error instanceof FsError;\n}\n\nfunction classify(error: unknown): Problem {\n if (error === null || error === undefined) {\n return build(ErrorCode.UNKNOWN, 'Unknown error');\n }\n if (isFsError(error)) return error.problem;\n // No `ZodError` branch, deliberately. Tool arguments are validated by the\n // SDK from the zod schema `defineTool` hands it (tools/define.ts); the SDK\n // formats issues itself and never throws a ZodError into a handler, and\n // nothing in `src/` calls `.parse()`. A ZodError reaching here would fall\n // through to UNKNOWN with Zod's raw JSON-dump `.message`, so if a\n // `.parse()` is ever added, add the branch back with it rather than\n // discovering this.\n if (!(error instanceof Error)) {\n return build(ErrorCode.UNKNOWN, typeof error === 'string' ? error : '[non-Error thrown]');\n }\n return classifyCauseChain(error);\n}\n\nexport function isNodeError(error: unknown): error is NodeJS.ErrnoException {\n if (!(error instanceof Error)) return false;\n if (!('code' in error)) return false;\n const { code } = error as { code?: unknown };\n return typeof code === 'string';\n}\n\n/** True when `error` is a Node errno error with code `ENOENT` (path not found). */\nexport function isNotFoundErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code === 'ENOENT';\n}\n\n/** True when `error` is a Node errno error whose code is in `SKIPPABLE_ERRNOS`. */\nexport function isSkippableErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code !== undefined && SKIPPABLE_ERRNOS.has(error.code);\n}\n\n/**\n * Rethrow when `error` reads as cancelled. Answers the question directly rather\n * than through `classify`, which allocated a Problem — and ran\n * `formatUnknownErrorMessage`, i.e. a `JSON.stringify` on a non-Error — for a\n * boolean. This sits in eight catch blocks, several inside per-entry scan loops.\n */\nexport function rethrowIfAborted(error: unknown): void {\n if (isFsError(error)) {\n if (error.code === ErrorCode.CANCELLED) throw error;\n return;\n }\n if (scanCauseChain(error).aborted) throw error;\n}\n\nexport function formatUnknownErrorMessage(error: unknown): string {\n if (typeof error === 'string') return error;\n if (error instanceof Error) return error.message;\n try {\n return JSON.stringify(error);\n } catch {\n return `[non-serializable: ${Object.prototype.toString.call(error)}]`;\n }\n}\n\nexport function normalizeUnknownError(error: unknown): Error {\n return error instanceof Error ? error : new Error(formatUnknownErrorMessage(error));\n}\n\nfunction formatDetailedError(\n error: Pick<Problem, 'code' | 'message' | 'path' | 'suggestion'>,\n): string {\n const lines: string[] = [`${error.code}: ${error.message}`];\n if (error.path && !error.message.includes(error.path)) {\n lines.push(error.path);\n }\n if (error.suggestion) {\n lines.push(error.suggestion);\n }\n return lines.join('\\n');\n}\n\nexport class FsError extends Error {\n readonly problem: Problem;\n\n constructor(code: ErrorCode, message: string, path?: string, cause?: unknown) {\n super(message, cause === undefined ? {} : { cause });\n const suggestion = DEFAULT_SUGGESTIONS[code];\n this.problem = {\n code,\n message,\n ...(path !== undefined ? { path } : {}),\n ...(suggestion !== undefined ? { suggestion } : {}),\n };\n this.name = 'FsError';\n }\n\n get code(): ErrorCode {\n return this.problem.code;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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","sourcesContent":["export const ErrorCode = {\n ACCESS_DENIED: 'ACCESS_DENIED',\n NOT_FOUND: 'NOT_FOUND',\n NOT_FILE: 'NOT_FILE',\n NOT_DIRECTORY: 'NOT_DIRECTORY',\n TOO_LARGE: 'TOO_LARGE',\n TIMEOUT: 'TIMEOUT',\n CANCELLED: 'CANCELLED',\n INVALID_PATTERN: 'INVALID_PATTERN',\n INVALID_INPUT: 'INVALID_INPUT',\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n SYMLINK_NOT_ALLOWED: 'SYMLINK_NOT_ALLOWED',\n IO_ERROR: 'IO_ERROR',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport interface Problem {\n readonly code: ErrorCode;\n readonly message: string;\n readonly path?: string;\n readonly suggestion?: string;\n}\n\ninterface ProblemFactoryOptions {\n path?: string | undefined;\n suggestion?: string | undefined;\n}\n\nfunction build(code: ErrorCode, message: string, opts: ProblemFactoryOptions = {}): Problem {\n return {\n code,\n message,\n ...(opts.path !== undefined ? { path: opts.path } : {}),\n ...(opts.suggestion !== undefined ? { suggestion: opts.suggestion } : {}),\n };\n}\n\nexport const Problem = {\n invalidInput: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.INVALID_INPUT, msg, o),\n accessDenied: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.ACCESS_DENIED, msg, o),\n cancelled: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.CANCELLED, msg, o),\n fromUnknown(error: unknown, defaultCode: ErrorCode, path?: string): Problem {\n const problem = classify(error);\n const shouldOverride =\n problem.code === ErrorCode.UNKNOWN || problem.code === ErrorCode.IO_ERROR;\n const code = shouldOverride ? defaultCode : problem.code;\n const suggestion =\n (shouldOverride ? DEFAULT_SUGGESTIONS[code] : undefined) ??\n problem.suggestion ??\n DEFAULT_SUGGESTIONS[problem.code];\n return build(code, problem.message, { path: path ?? problem.path, suggestion });\n },\n toText(error: unknown, defaultCode: ErrorCode): string {\n return formatDetailedError(Problem.fromUnknown(error, defaultCode));\n },\n} as const;\n\nconst DEFAULT_SUGGESTIONS: Readonly<Partial<Record<ErrorCode, string>>> = {\n [ErrorCode.ACCESS_DENIED]: 'Run list_roots to list allowed directories.',\n [ErrorCode.NOT_FOUND]: 'Run list or find_files to verify the path.',\n [ErrorCode.NOT_FILE]: 'Target is a directory, not a file.',\n [ErrorCode.NOT_DIRECTORY]: 'Target is a file, not a directory.',\n [ErrorCode.TOO_LARGE]: 'Use head/tail or line ranges to read partially.',\n [ErrorCode.TIMEOUT]: 'Reduce scope, depth, or maxResults.',\n [ErrorCode.INVALID_PATTERN]: 'Check syntax and escape special characters.',\n [ErrorCode.PERMISSION_DENIED]: 'Check OS file permissions.',\n [ErrorCode.SYMLINK_NOT_ALLOWED]: 'Symlink escapes allowed directories.',\n};\n\nconst ERRNO_MAP: Readonly<Record<string, ErrorCode>> = {\n ENOENT: ErrorCode.NOT_FOUND,\n EACCES: ErrorCode.PERMISSION_DENIED,\n EPERM: ErrorCode.PERMISSION_DENIED,\n ENOTDIR: ErrorCode.NOT_DIRECTORY,\n EISDIR: ErrorCode.NOT_FILE,\n ELOOP: ErrorCode.SYMLINK_NOT_ALLOWED,\n ENAMETOOLONG: ErrorCode.INVALID_INPUT,\n ETIMEDOUT: ErrorCode.TIMEOUT,\n EMFILE: ErrorCode.IO_ERROR,\n ENFILE: ErrorCode.IO_ERROR,\n EBUSY: ErrorCode.IO_ERROR,\n ENOTEMPTY: ErrorCode.NOT_DIRECTORY,\n EEXIST: ErrorCode.INVALID_INPUT,\n EINVAL: ErrorCode.INVALID_INPUT,\n};\n\nconst ERRNO_RE = /^E[A-Z]+$/;\n\n// NOT_FOUND is in here (not just ENOENT) because a dangling symlink whose\n// target sits inside an allowed root surfaces as an FsError NOT_FOUND. Skipping\n// the entry is the point of a listing; rethrowing would fail the whole listing.\nexport const SKIPPABLE_FS_CODES: ReadonlySet<ErrorCode> = new Set([\n ErrorCode.ACCESS_DENIED,\n ErrorCode.NOT_FOUND,\n // OS-level EACCES/EPERM on a symlink target during a listing is exactly as\n // skippable as the other three codes.\n ErrorCode.PERMISSION_DENIED,\n ErrorCode.SYMLINK_NOT_ALLOWED,\n]);\n\nconst SKIPPABLE_ERRNOS: ReadonlySet<string> = new Set(['ENOENT', 'EACCES', 'ELOOP']);\n\n/**\n * Walk `error` and its `cause` chain once for the three facts error handling\n * needs: an abort anywhere, a timeout anywhere, and the FIRST errno seen.\n * `visited` guards a cyclic chain. A node that reads as an abort or a timeout\n * never also contributes its errno.\n */\nfunction scanCauseChain(error: unknown): {\n aborted: boolean;\n timedOut: boolean;\n errno: { code: string; path?: string } | undefined;\n} {\n const visited = new Set<unknown>();\n let aborted = false;\n let timedOut = false;\n let errno: { code: string; path?: string } | undefined;\n\n for (\n let current: unknown = error;\n current !== undefined && current !== null && !visited.has(current);\n current = (current as { cause?: unknown }).cause\n ) {\n visited.add(current);\n if (!(current instanceof Error)) continue;\n const raw = (current as { code?: unknown }).code;\n const code = typeof raw === 'string' ? raw : undefined;\n if (current.name === 'AbortError' || code === 'ABORT_ERR') {\n aborted = true;\n } else if (current.name === 'TimeoutError' || code === 'ETIMEDOUT') {\n timedOut = true;\n } else if (errno === undefined && code !== undefined && ERRNO_RE.test(code)) {\n const { path } = current as NodeJS.ErrnoException;\n errno = { code, ...(typeof path === 'string' ? { path } : {}) };\n }\n }\n\n return { aborted, timedOut, errno };\n}\n\n/** The scan's facts as a Problem: an abort wins, then a timeout, then errno. */\nexport function classifyCauseChain(error: unknown): Problem {\n const message = formatUnknownErrorMessage(error);\n const { aborted, timedOut, errno } = scanCauseChain(error);\n if (aborted) return Problem.cancelled(message);\n if (timedOut) return build(ErrorCode.TIMEOUT, message);\n if (errno !== undefined) {\n return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, { path: errno.path });\n }\n return build(ErrorCode.UNKNOWN, message);\n}\n\nexport function isFsError(error: unknown): error is FsError {\n return error instanceof FsError;\n}\n\nfunction classify(error: unknown): Problem {\n if (error === null || error === undefined) {\n return build(ErrorCode.UNKNOWN, 'Unknown error');\n }\n if (isFsError(error)) return error.problem;\n // No `ZodError` branch, deliberately. Tool arguments are validated by the\n // SDK from the zod schema `defineTool` hands it (tools/define.ts); the SDK\n // formats issues itself and never throws a ZodError into a handler, and\n // nothing in `src/` calls `.parse()`. A ZodError reaching here would fall\n // through to UNKNOWN with Zod's raw JSON-dump `.message`, so if a\n // `.parse()` is ever added, add the branch back with it rather than\n // discovering this.\n if (!(error instanceof Error)) {\n return build(ErrorCode.UNKNOWN, typeof error === 'string' ? error : '[non-Error thrown]');\n }\n return classifyCauseChain(error);\n}\n\nexport function isNodeError(error: unknown): error is NodeJS.ErrnoException {\n if (!(error instanceof Error)) return false;\n if (!('code' in error)) return false;\n const { code } = error as { code?: unknown };\n return typeof code === 'string';\n}\n\n/** True when `error` is a Node errno error with code `ENOENT` (path not found). */\nexport function isNotFoundErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code === 'ENOENT';\n}\n\n/** True when `error` is a Node errno error whose code is in `SKIPPABLE_ERRNOS`. */\nexport function isSkippableErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code !== undefined && SKIPPABLE_ERRNOS.has(error.code);\n}\n\n/**\n * Rethrow when `error` reads as cancelled. Answers the question directly rather\n * than through `classify`, which allocated a Problem — and ran\n * `formatUnknownErrorMessage`, i.e. a `JSON.stringify` on a non-Error — for a\n * boolean. This sits in eight catch blocks, several inside per-entry scan loops.\n */\nexport function rethrowIfAborted(error: unknown): void {\n if (isFsError(error)) {\n if (error.code === ErrorCode.CANCELLED) throw error;\n return;\n }\n if (scanCauseChain(error).aborted) throw error;\n}\n\nexport function formatUnknownErrorMessage(error: unknown): string {\n if (typeof error === 'string') return error;\n if (error instanceof Error) return error.message;\n try {\n return JSON.stringify(error);\n } catch {\n return `[non-serializable: ${Object.prototype.toString.call(error)}]`;\n }\n}\n\nexport function normalizeUnknownError(error: unknown): Error {\n return error instanceof Error ? error : new Error(formatUnknownErrorMessage(error));\n}\n\nfunction formatDetailedError(\n error: Pick<Problem, 'code' | 'message' | 'path' | 'suggestion'>,\n): string {\n const lines: string[] = [`${error.code}: ${error.message}`];\n if (error.path && !error.message.includes(error.path)) {\n lines.push(error.path);\n }\n if (error.suggestion) {\n lines.push(error.suggestion);\n }\n return lines.join('\\n');\n}\n\nexport class FsError extends Error {\n readonly problem: Problem;\n\n /** `suggestion` replaces the code's default for a thrower that knows the better next step. */\n constructor(\n code: ErrorCode,\n message: string,\n path?: string,\n cause?: unknown,\n suggestion: string | undefined = DEFAULT_SUGGESTIONS[code],\n ) {\n super(message, cause === undefined ? {} : { cause });\n this.problem = build(code, message, { path, suggestion });\n this.name = 'FsError';\n }\n\n get code(): ErrorCode {\n return this.problem.code;\n }\n}\n"]}
|
package/dist/core/fs.d.ts
CHANGED
|
@@ -6,16 +6,6 @@ import type { PathGuard } from './path.ts';
|
|
|
6
6
|
import type { ReadFileResult, ReadSpec } from './read.ts';
|
|
7
7
|
export type { FileType };
|
|
8
8
|
export type { Stats };
|
|
9
|
-
/**
|
|
10
|
-
* Line count for a file on disk, counting newline bytes in fixed 64 KiB
|
|
11
|
-
* chunks so an arbitrarily large file (one append's result metadata) costs
|
|
12
|
-
* bounded memory. NOT FileHandle.readLines: it decodes each physical line
|
|
13
|
-
* whole, so a multi-GB single-line log OOMs the server after the append has
|
|
14
|
-
* already landed — a reported failure invites a retry that appends twice.
|
|
15
|
-
* Matches read.ts's countLines semantics: a trailing newline does not open
|
|
16
|
-
* a new line, an unterminated final line counts, an empty file is 0.
|
|
17
|
-
*/
|
|
18
|
-
export declare function countFileLines(filePath: string): Promise<number>;
|
|
19
9
|
export declare class GuardedFileSystem {
|
|
20
10
|
#private;
|
|
21
11
|
readonly pathGuard: PathGuard;
|
|
@@ -66,7 +56,17 @@ export declare class GuardedFileSystem {
|
|
|
66
56
|
* file — an append's result must describe the resulting file (which may be
|
|
67
57
|
* a multi-GB log), not the chunk that was appended.
|
|
68
58
|
*/
|
|
69
|
-
readLeadingSample(filePath: string
|
|
59
|
+
readLeadingSample(filePath: string): Promise<Buffer>;
|
|
60
|
+
/**
|
|
61
|
+
* Line count for a file on disk, counting newline bytes in fixed 64 KiB
|
|
62
|
+
* chunks so an arbitrarily large file (one append's result metadata) costs
|
|
63
|
+
* bounded memory. NOT FileHandle.readLines: it decodes each physical line
|
|
64
|
+
* whole, so a multi-GB single-line log OOMs the server after the append has
|
|
65
|
+
* already landed — a reported failure invites a retry that appends twice.
|
|
66
|
+
* Matches read.ts's countLines semantics: a trailing newline does not open
|
|
67
|
+
* a new line, an unterminated final line counts, an empty file is 0.
|
|
68
|
+
*/
|
|
69
|
+
countFileLines(filePath: string): Promise<number>;
|
|
70
70
|
rm(filePath: string, options?: Parameters<typeof fsRm>[1]): Promise<void>;
|
|
71
71
|
rmdir(filePath: string, options?: Parameters<typeof fsRmdir>[1]): Promise<void>;
|
|
72
72
|
cp(source: string, destination: string, options?: Parameters<typeof fsCp>[2]): Promise<void>;
|
package/dist/core/fs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAEL,EAAE,IAAI,IAAI,EAEV,KAAK,IAAI,OAAO,EAIhB,QAAQ,IAAI,UAAU,EAEtB,EAAE,IAAI,IAAI,EACV,KAAK,IAAI,OAAO,EAIjB,MAAM,kBAAkB,CAAC;AAc1B,OAAO,KAAK,EAAE,SAAS,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAW1D,YAAY,EAAE,QAAQ,EAAE,CAAC;AACzB,YAAY,EAAE,KAAK,EAAE,CAAC;AAgCtB
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"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"}
|
package/dist/core/fs.js
CHANGED
|
@@ -1,9 +1,61 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
1
53
|
import { randomUUID } from 'node:crypto';
|
|
2
54
|
import { chmod as fsChmod, cp as fsCp, lstat as fsLstat, mkdir as fsMkdir, open as fsOpen, opendir as fsOpendir, readFile as fsReadFile, readlink as fsReadlink, rename as fsRename, rm as fsRm, rmdir as fsRmdir, stat as fsStat, unlink as fsUnlink, writeFile as fsWriteFile, } from 'node:fs/promises';
|
|
3
55
|
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
4
56
|
import { runExclusive, withAbort } from "./concurrency.js";
|
|
5
57
|
import { ErrorCode, formatUnknownErrorMessage, FsError, isFsError, isNodeError, isNotFoundErrno, } from "./errors.js";
|
|
6
|
-
import { detectMimeFromContent } from "./mime.js";
|
|
58
|
+
import { detectMimeFromContent, MIME_SAMPLE_SIZE } from "./mime.js";
|
|
7
59
|
import { Logger } from "./observability.js";
|
|
8
60
|
import { normalizePath, respellCaseOnlyTarget } from "./path-utils.js";
|
|
9
61
|
import { APPEND_CREATE_NOFOLLOW, APPEND_NOFOLLOW, assertFileStats, createTooLargeError, READ_NOFOLLOW, readFileWithStats, } from "./read.js";
|
|
@@ -33,42 +85,6 @@ async function resolveForWrite(pathGuard, filePath) {
|
|
|
33
85
|
}
|
|
34
86
|
const CHAR_LF = 10;
|
|
35
87
|
const LINE_COUNT_CHUNK_BYTES = 64 * 1024;
|
|
36
|
-
/**
|
|
37
|
-
* Line count for a file on disk, counting newline bytes in fixed 64 KiB
|
|
38
|
-
* chunks so an arbitrarily large file (one append's result metadata) costs
|
|
39
|
-
* bounded memory. NOT FileHandle.readLines: it decodes each physical line
|
|
40
|
-
* whole, so a multi-GB single-line log OOMs the server after the append has
|
|
41
|
-
* already landed — a reported failure invites a retry that appends twice.
|
|
42
|
-
* Matches read.ts's countLines semantics: a trailing newline does not open
|
|
43
|
-
* a new line, an unterminated final line counts, an empty file is 0.
|
|
44
|
-
*/
|
|
45
|
-
export async function countFileLines(filePath) {
|
|
46
|
-
const handle = await fsOpen(filePath, READ_NOFOLLOW);
|
|
47
|
-
try {
|
|
48
|
-
let newlines = 0;
|
|
49
|
-
let lastByte = 0;
|
|
50
|
-
let totalBytes = 0;
|
|
51
|
-
const chunk = Buffer.alloc(LINE_COUNT_CHUNK_BYTES);
|
|
52
|
-
for (;;) {
|
|
53
|
-
const { bytesRead } = await handle.read(chunk, 0, chunk.length, null);
|
|
54
|
-
if (bytesRead === 0)
|
|
55
|
-
break;
|
|
56
|
-
totalBytes += bytesRead;
|
|
57
|
-
for (let i = 0; i < bytesRead; i++) {
|
|
58
|
-
const byte = chunk[i] ?? 0;
|
|
59
|
-
if (byte === CHAR_LF)
|
|
60
|
-
newlines++;
|
|
61
|
-
lastByte = byte;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// totalBytes is the empty-file sentinel: a NUL (0x00) final byte is real
|
|
65
|
-
// content and must count as an unterminated final line, not "empty".
|
|
66
|
-
return totalBytes === 0 ? 0 : lastByte === CHAR_LF ? newlines : newlines + 1;
|
|
67
|
-
}
|
|
68
|
-
finally {
|
|
69
|
-
await handle.close();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
88
|
export class GuardedFileSystem {
|
|
73
89
|
pathGuard;
|
|
74
90
|
constructor(pathGuard) {
|
|
@@ -276,16 +292,65 @@ export class GuardedFileSystem {
|
|
|
276
292
|
* file — an append's result must describe the resulting file (which may be
|
|
277
293
|
* a multi-GB log), not the chunk that was appended.
|
|
278
294
|
*/
|
|
279
|
-
async readLeadingSample(filePath
|
|
280
|
-
const {
|
|
281
|
-
const handle = await fsOpen(validPath, READ_NOFOLLOW);
|
|
295
|
+
async readLeadingSample(filePath) {
|
|
296
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
282
297
|
try {
|
|
283
|
-
const
|
|
284
|
-
const
|
|
298
|
+
const handle = __addDisposableResource(env_1, await this.open(filePath), true);
|
|
299
|
+
const buffer = Buffer.alloc(MIME_SAMPLE_SIZE);
|
|
300
|
+
const { bytesRead } = await handle.read(buffer, 0, MIME_SAMPLE_SIZE, 0);
|
|
285
301
|
return buffer.subarray(0, bytesRead);
|
|
286
302
|
}
|
|
303
|
+
catch (e_1) {
|
|
304
|
+
env_1.error = e_1;
|
|
305
|
+
env_1.hasError = true;
|
|
306
|
+
}
|
|
287
307
|
finally {
|
|
288
|
-
|
|
308
|
+
const result_1 = __disposeResources(env_1);
|
|
309
|
+
if (result_1)
|
|
310
|
+
await result_1;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Line count for a file on disk, counting newline bytes in fixed 64 KiB
|
|
315
|
+
* chunks so an arbitrarily large file (one append's result metadata) costs
|
|
316
|
+
* bounded memory. NOT FileHandle.readLines: it decodes each physical line
|
|
317
|
+
* whole, so a multi-GB single-line log OOMs the server after the append has
|
|
318
|
+
* already landed — a reported failure invites a retry that appends twice.
|
|
319
|
+
* Matches read.ts's countLines semantics: a trailing newline does not open
|
|
320
|
+
* a new line, an unterminated final line counts, an empty file is 0.
|
|
321
|
+
*/
|
|
322
|
+
async countFileLines(filePath) {
|
|
323
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
324
|
+
try {
|
|
325
|
+
const handle = __addDisposableResource(env_2, await this.open(filePath), true);
|
|
326
|
+
let newlines = 0;
|
|
327
|
+
let lastByte = 0;
|
|
328
|
+
let totalBytes = 0;
|
|
329
|
+
const chunk = Buffer.alloc(LINE_COUNT_CHUNK_BYTES);
|
|
330
|
+
for (;;) {
|
|
331
|
+
const { bytesRead } = await handle.read(chunk, 0, chunk.length, null);
|
|
332
|
+
if (bytesRead === 0)
|
|
333
|
+
break;
|
|
334
|
+
totalBytes += bytesRead;
|
|
335
|
+
for (let i = 0; i < bytesRead; i++) {
|
|
336
|
+
const byte = chunk[i] ?? 0;
|
|
337
|
+
if (byte === CHAR_LF)
|
|
338
|
+
newlines++;
|
|
339
|
+
lastByte = byte;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// totalBytes is the empty-file sentinel: a NUL (0x00) final byte is real
|
|
343
|
+
// content and must count as an unterminated final line, not "empty".
|
|
344
|
+
return totalBytes === 0 ? 0 : lastByte === CHAR_LF ? newlines : newlines + 1;
|
|
345
|
+
}
|
|
346
|
+
catch (e_2) {
|
|
347
|
+
env_2.error = e_2;
|
|
348
|
+
env_2.hasError = true;
|
|
349
|
+
}
|
|
350
|
+
finally {
|
|
351
|
+
const result_2 = __disposeResources(env_2);
|
|
352
|
+
if (result_2)
|
|
353
|
+
await result_2;
|
|
289
354
|
}
|
|
290
355
|
}
|
|
291
356
|
async rm(filePath, options) {
|