@walkeros/core 4.8.1-next-1792019907609 → 4.8.2
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/CHANGELOG.md +49 -1
- package/dist/dev.d.mts +808 -47
- package/dist/dev.d.ts +808 -47
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/index.d.mts +466 -136
- package/dist/index.d.ts +466 -136
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +129 -14
- package/dist/node.d.ts +129 -14
- package/dist/node.js +1 -1
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +1 -1
- package/dist/node.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node.ts","../src/types/logger.ts","../src/logger.ts","../src/redactLine.ts","../src/toPrintable.ts","../src/scrubJson.ts"],"sourcesContent":["/**\n * Node entry point (`@walkeros/core/node`).\n *\n * Helpers shared by `@walkeros/cli` and `@walkeros/runner` that do not belong\n * in the browser `.` entry: the temp-path helpers import node builtins, the\n * terminal logger config writes to the console, and the secret redactor and\n * the simulate output formatter (`toPrintable`, it reads `Buffer`) have\n * no browser consumer (in `.` it was not tree-shaken out of walker.js). Core gains no dependency\n * for them: the colouriser is injected by the caller, so chalk stays in the\n * packages that already depend on it.\n */\n\n/* eslint-disable no-console */\nimport os from 'os';\nimport path from 'path';\nimport { createLogger } from './logger';\nimport { maskKnownValues, scrubSecrets } from './redactLine';\n\nexport { scrubSecrets, redactLine } from './redactLine';\nexport type { ScrubOptions } from './redactLine';\nexport { scrubJson } from './scrubJson';\nexport { toPrintable } from './toPrintable';\nimport type { Config, Instance } from './types/logger';\nimport { Level } from './types/logger';\n\nconst DEFAULT_TMP_ROOT = os.tmpdir();\n\n/**\n * Get a path within the temp directory.\n *\n * @param tmpDir - Custom temp directory (optional, for --tmp-dir flag)\n * @param segments - Path segments to join\n * @returns Absolute path within temp directory\n *\n * @example\n * ```typescript\n * getTmpPath() // → \"/tmp\"\n * getTmpPath(undefined, 'entry.js') // → \"/tmp/entry.js\"\n * getTmpPath(undefined, 'cache', 'builds') // → \"/tmp/cache/builds\"\n * getTmpPath('/custom', 'cache') // → \"/custom/cache\"\n * ```\n */\nexport function getTmpPath(tmpDir?: string, ...segments: string[]): string {\n const root = tmpDir || DEFAULT_TMP_ROOT;\n // Always return absolute path (esbuild requirement)\n const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);\n return path.join(absoluteRoot, ...segments);\n}\n\n/**\n * A temp path resolver with the root directory baked in.\n *\n * Use {@link createTmpResolver} at entry points to capture the temp root once,\n * then pass the resolver to downstream functions. This prevents the class of\n * bugs where callers forget to pass tmpDir.\n *\n * @example\n * ```typescript\n * const tmp = createTmpResolver(buildOptions.tempDir);\n * const cacheDir = tmp('cache', 'packages'); // root is baked in\n * ```\n */\nexport type TmpResolver = (...segments: string[]) => string;\n\nexport function createTmpResolver(tmpDir?: string): TmpResolver {\n const root = tmpDir || DEFAULT_TMP_ROOT;\n const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);\n return (...segments: string[]) => path.join(absoluteRoot, ...segments);\n}\n\n/**\n * Get the default temp root directory.\n */\nexport function getDefaultTmpRoot(): string {\n return DEFAULT_TMP_ROOT;\n}\n\nexport interface CLILoggerOptions {\n verbose?: boolean;\n silent?: boolean;\n json?: boolean;\n stderr?: boolean;\n onLine?: (level: Level, message: string) => void;\n /**\n * Exact secret values masked in every line (see `scrubSecrets`). An array is\n * copied at creation; a function is read per line, so values learned after\n * the logger exists (secrets fetched at startup) are masked too.\n */\n knownSecrets?: readonly string[] | (() => readonly string[]);\n}\n\n/** Formats one already-scrubbed line for the terminal. */\nexport type LineFormatter = (line: string) => string;\n\n/**\n * Per-level terminal formatters. Every level defaults to identity, so a caller\n * that passes nothing gets plain uncoloured output.\n */\nexport interface CLILoggerColors {\n error?: LineFormatter;\n warn?: LineFormatter;\n info?: LineFormatter;\n debug?: LineFormatter;\n}\n\nconst identity: LineFormatter = (line) => line;\n\nconst TMP_ROOT_LABEL = '$TMPDIR';\n\n/**\n * Replace each occurrence of the literal temp root, followed by a path\n * separator, with `$TMPDIR`. Only occurrences that start a path count: the\n * character before must not continue a path, so `/mnt/tmp/x` keeps its text\n * when the root is `/tmp`. Literal matching only, never a pattern built from\n * the path.\n */\nfunction labelTmpRoot(line: string, root: string): string {\n if (!root || root === path.sep) return line;\n const needle = root.endsWith(path.sep) ? root : root + path.sep;\n const parts = line.split(needle);\n if (parts.length === 1) return line;\n let result = parts[0];\n for (let i = 1; i < parts.length; i++) {\n const before = result.length > 0 ? result[result.length - 1] : '';\n const startsPath = before === '' || !/[\\w./\\\\~-]/.test(before);\n result += (startsPath ? TMP_ROOT_LABEL + path.sep : needle) + parts[i];\n }\n return result;\n}\n\n/**\n * Build the `Logger.Config` (level + handler + jsonHandler) that backs a\n * terminal logger. Returned separately so the runtime can hand the SAME\n * handler (including the `onLine` ring tap) to the deployed bundle's\n * collector.\n *\n * The collector in a deployed bundle builds its own logger from this config\n * (`config.logger`), so its destination errors flow through the identical\n * `onLine` tap the runtime logger uses, landing in the shared ErrorRing.\n * There is no parallel ring: one handler, one tap.\n *\n * Level: `Level.DEBUG` so the handler sees every line and controls visibility\n * itself (verbose/silent gating). ERROR is therefore always emitted into the\n * ring regardless of `--verbose`.\n *\n * `colors` formats each level for the terminal. It is applied to console\n * output only, never to the line handed to `onLine`.\n */\nexport function createCLILoggerConfig(\n options: CLILoggerOptions = {},\n colors: CLILoggerColors = {},\n): Config {\n const {\n verbose = false,\n silent = false,\n json = false,\n stderr = false,\n knownSecrets,\n } = options;\n const knownCopy =\n typeof knownSecrets === 'function'\n ? undefined\n : knownSecrets\n ? [...knownSecrets]\n : undefined;\n const readKnown = (): readonly string[] | undefined =>\n typeof knownSecrets === 'function' ? knownSecrets() : knownCopy;\n const tmpRoot = os.tmpdir();\n const out = stderr ? console.error : console.log;\n const errorColor = colors.error ?? identity;\n const warnColor = colors.warn ?? identity;\n const infoColor = colors.info ?? identity;\n const debugColor = colors.debug ?? identity;\n\n return {\n // Let handler control visibility: pass everything through. With the gate\n // at DEBUG, ERROR always reaches the handler (and the ring) even without\n // --verbose.\n level: Level.DEBUG,\n handler: (level, message, context, scope) => {\n // Build formatted message\n const scopePath = scope.length > 0 ? `[${scope.join(':')}] ` : '';\n // Serialize the structured context into the line so error details (gRPC\n // status codes, row counts, target tables) reach stderr and the ring.\n // Serialization happens BEFORE scrubSecrets so redaction covers context\n // values too; the heartbeat path's 256-char cap stays as the wire\n // backstop. A context that cannot stringify (circular) must never break\n // logging.\n let meta = '';\n if (Object.keys(context).length > 0) {\n try {\n meta = ` ${JSON.stringify(context)}`;\n } catch {\n meta = ' [unserializable context]';\n }\n }\n // Redact secrets ONCE here, before BOTH the onLine ring tap and the\n // console.* output. stderr is shipped directly by the log collector, so\n // the heartbeat-egress redactor alone would miss it; doing it in the\n // handler scrubs every line routed through this logger (collector and\n // steps) on both paths. Length is preserved here (no truncation); the\n // heartbeat path applies the 256-char wire cap separately as a backstop\n // on already-redacted text.\n // Order: known values first, so the label can never split one (a\n // `sqlite:/tmp/...` URL, or a value that only touches the root at its\n // edge); then the temp root label, since a long per-user root (macOS\n // `/var/folders/...`) would otherwise read as a token; then the\n // pattern rules.\n const fullMessage = scrubSecrets(\n labelTmpRoot(\n maskKnownValues(`${scopePath}${message}${meta}`, readKnown()),\n tmpRoot,\n ),\n );\n\n // Tap every line before any early return so no level is dropped from capture.\n try {\n options.onLine?.(level, fullMessage);\n } catch {\n // Swallow: a throwing consumer must never break logging (and we must\n // not call logger methods here to avoid infinite recursion).\n }\n\n // ERROR: always shown unless json mode\n if (level === Level.ERROR) {\n if (!json) console.error(errorColor(fullMessage));\n return;\n }\n\n // Non-errors suppressed in silent or json mode\n if (silent || json) return;\n\n // DEBUG: only with verbose\n if (level === Level.DEBUG) {\n if (!verbose) return;\n out(` ${debugColor(fullMessage)}`);\n return;\n }\n\n // WARN / INFO: normal output\n out(\n level === Level.WARN ? warnColor(fullMessage) : infoColor(fullMessage),\n );\n },\n jsonHandler: (data) => {\n if (!silent) out(JSON.stringify(data, null, 2));\n },\n };\n}\n\n/**\n * Create a core Logger.Instance with terminal-appropriate behavior.\n *\n * Behavior:\n * - ERROR: always shown (via console.error, `colors.error`) unless --json\n * - WARN: shown unless --silent or --json\n * - INFO: shown unless --silent or --json\n * - DEBUG: shown only with --verbose (and not --silent/--json)\n * - json(): shown unless --silent\n */\nexport function createCLILogger(\n options: CLILoggerOptions = {},\n colors: CLILoggerColors = {},\n): Instance {\n return createLogger(createCLILoggerConfig(options, colors));\n}\n","/**\n * Log levels from most to least severe\n */\nexport enum Level {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n}\n\n/**\n * Normalized error context extracted from Error objects\n */\nexport interface ErrorContext {\n message: string;\n name: string;\n stack?: string;\n cause?: unknown;\n}\n\n/**\n * Context passed to log handlers\n * If an Error was passed, it's normalized into the error property\n */\nexport interface LogContext {\n [key: string]: unknown;\n error?: ErrorContext;\n}\n\n/**\n * Log message function signature\n * Accepts string or Error as message, with optional context\n */\nexport type LogFn = (\n message: string | Error,\n context?: unknown | Error,\n) => void;\n\n/**\n * Throw function signature - logs error then throws\n * Returns never as it always throws\n */\nexport type ThrowFn = (message: string | Error, context?: unknown) => never;\n\n/**\n * Default handler function (passed to custom handlers for chaining)\n */\nexport type DefaultHandler = (\n level: Level,\n message: string,\n context: LogContext,\n scope: string[],\n) => void;\n\n/**\n * Custom log handler function\n * Receives originalHandler to allow middleware-style chaining\n */\nexport type Handler = (\n level: Level,\n message: string,\n context: LogContext,\n scope: string[],\n originalHandler: DefaultHandler,\n) => void;\n\n/**\n * Logger instance with scoping support\n * All logs automatically include trace path from scoping\n */\nexport interface Instance {\n /**\n * Log an error message (always visible unless silenced)\n */\n error: LogFn;\n\n /**\n * Log a warning (degraded state, config issues, transient failures)\n */\n warn: LogFn;\n\n /**\n * Log an informational message\n */\n info: LogFn;\n\n /**\n * Log a debug message\n */\n debug: LogFn;\n\n /**\n * Log an error message and throw an Error\n * Combines logging and throwing in one call\n */\n throw: ThrowFn;\n\n /**\n * Output structured JSON data\n */\n json: (data: unknown) => void;\n\n /**\n * Create a scoped child logger with automatic trace path\n * @param name - Scope name (e.g., destination type, destination key)\n * @returns A new logger instance with the scope applied\n */\n scope: (name: string) => Instance;\n}\n\n/**\n * Logger configuration options\n */\nexport interface Config {\n /**\n * Minimum log level to display\n * @default Level.ERROR\n */\n level?: Level | keyof typeof Level;\n\n /**\n * Custom log handler function\n * Receives originalHandler to preserve default behavior\n */\n handler?: Handler;\n\n /** Custom handler for json() output. Default: console.log(JSON.stringify(data, null, 2)) */\n jsonHandler?: (data: unknown) => void;\n}\n\n/**\n * Internal config with resolved values and scope\n */\nexport interface InternalConfig {\n level: Level;\n handler?: Handler;\n jsonHandler?: (data: unknown) => void;\n scope: string[];\n}\n\n/**\n * Logger factory function type\n */\nexport type Factory = (config?: Config) => Instance;\n","import type {\n Config,\n DefaultHandler,\n ErrorContext,\n Handler,\n Instance,\n InternalConfig,\n LogContext,\n} from './types/logger';\nimport { Level } from './types/logger';\n\n/**\n * Normalize an Error object into ErrorContext\n */\nfunction normalizeError(err: Error): ErrorContext {\n return {\n message: err.message,\n name: err.name,\n stack: err.stack,\n cause: (err as Error & { cause?: unknown }).cause,\n };\n}\n\n/**\n * Normalize message and context parameters\n * Handles Error objects passed as message or context\n */\nfunction normalizeParams(\n message: string | Error,\n context?: unknown | Error,\n): { message: string; context: LogContext } {\n let normalizedMessage: string;\n let normalizedContext: LogContext = {};\n\n // Handle message\n if (message instanceof Error) {\n normalizedMessage = message.message;\n normalizedContext.error = normalizeError(message);\n } else {\n normalizedMessage = message;\n }\n\n // Handle context\n if (context !== undefined) {\n if (context instanceof Error) {\n normalizedContext.error = normalizeError(context);\n } else if (typeof context === 'object' && context !== null) {\n normalizedContext = { ...normalizedContext, ...(context as object) };\n // If context has an error property that's an Error, normalize it\n if (\n 'error' in normalizedContext &&\n normalizedContext.error instanceof Error\n ) {\n normalizedContext.error = normalizeError(\n normalizedContext.error as unknown as Error,\n );\n }\n } else {\n normalizedContext.value = context;\n }\n }\n\n return { message: normalizedMessage, context: normalizedContext };\n}\n\n/**\n * Default console-based log handler\n */\nconst defaultHandler: DefaultHandler = (level, message, context, scope) => {\n const levelName = Level[level];\n const scopePath = scope.length > 0 ? ` [${scope.join(':')}]` : '';\n const prefix = `${levelName}${scopePath}`;\n\n const hasContext = Object.keys(context).length > 0;\n\n const consoleFn =\n level === Level.ERROR\n ? console.error\n : level === Level.WARN\n ? console.warn\n : console.log;\n\n if (hasContext) {\n consoleFn(prefix, message, context);\n } else {\n consoleFn(prefix, message);\n }\n};\n\n/**\n * Normalize log level from string or enum to enum value\n */\nfunction normalizeLevel(level: Level | keyof typeof Level): Level {\n if (typeof level === 'string') {\n return Level[level as keyof typeof Level];\n }\n return level;\n}\n\n/**\n * Create a logger instance\n *\n * @param config - Logger configuration\n * @returns Logger instance with all log methods and scoping support\n *\n * @example\n * ```typescript\n * // Basic usage\n * const logger = createLogger({ level: 'DEBUG' });\n * logger.info('Hello world');\n *\n * // With scoping\n * const destLogger = logger.scope('gtag').scope('myInstance');\n * destLogger.debug('Processing event'); // DEBUG [gtag:myInstance] Processing event\n *\n * // With custom handler\n * const logger = createLogger({\n * handler: (level, message, context, scope, originalHandler) => {\n * // Custom logic (e.g., send to Sentry)\n * originalHandler(level, message, context, scope);\n * }\n * });\n * ```\n *\n * // TODO: Consider compile-time stripping of debug logs in production builds\n * // e.g., if (__DEV__) { logger.debug(...) }\n */\nexport function createLogger(config: Config = {}): Instance {\n const level =\n config.level !== undefined ? normalizeLevel(config.level) : Level.ERROR;\n const customHandler = config.handler;\n const jsonHandler = config.jsonHandler;\n const scope: string[] = [];\n\n return createLoggerInternal({\n level,\n handler: customHandler,\n jsonHandler,\n scope,\n });\n}\n\n/**\n * Internal logger creation with resolved config\n */\nfunction createLoggerInternal(config: InternalConfig): Instance {\n const { level, handler, jsonHandler, scope } = config;\n\n /**\n * Internal log function that checks level and delegates to handler\n */\n const log = (\n logLevel: Level,\n message: string | Error,\n context?: unknown | Error,\n ): void => {\n if (logLevel <= level) {\n const normalized = normalizeParams(message, context);\n\n if (handler) {\n // Custom handler with access to default handler\n handler(\n logLevel,\n normalized.message,\n normalized.context,\n scope,\n defaultHandler,\n );\n } else {\n defaultHandler(logLevel, normalized.message, normalized.context, scope);\n }\n }\n };\n\n /**\n * Log and throw - combines logging and throwing\n */\n const logAndThrow = (message: string | Error, context?: unknown): never => {\n // Always log errors regardless of level\n const normalized = normalizeParams(message, context);\n\n if (handler) {\n handler(\n Level.ERROR,\n normalized.message,\n normalized.context,\n scope,\n defaultHandler,\n );\n } else {\n defaultHandler(\n Level.ERROR,\n normalized.message,\n normalized.context,\n scope,\n );\n }\n\n // Throw with the message\n throw new Error(normalized.message);\n };\n\n return {\n error: (message, context) => log(Level.ERROR, message, context),\n warn: (message, context) => log(Level.WARN, message, context),\n info: (message, context) => log(Level.INFO, message, context),\n debug: (message, context) => log(Level.DEBUG, message, context),\n throw: logAndThrow,\n json: (data: unknown) => {\n if (jsonHandler) {\n jsonHandler(data);\n } else {\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(data, null, 2));\n }\n },\n scope: (name: string) =>\n createLoggerInternal({\n level,\n handler,\n jsonHandler,\n scope: [...scope, name],\n }),\n };\n}\n\n// Re-export Level enum for convenience\nexport { Level };\n","/**\n * Shared secret redactor. One set of patterns for every path that egresses a\n * log line: the CLI logger handler and the runtime logger handler (scrubbing\n * console and the error ring), and the runtime heartbeat (scrubbing the ring\n * snapshot before the POST). A pattern added here covers all of them.\n *\n * Two entry points:\n * - `scrubSecrets(line, { known })`: mask secrets (and the exact known values), keep the message length intact (for\n * console/stderr legibility).\n * - `redactLine(line)`: `scrubSecrets` plus truncation to the 256-char\n * heartbeat wire contract.\n *\n * All regex are linear (single unambiguous quantifiers, no nested quantifiers),\n * so there is no catastrophic backtracking even on a BEGIN-marker-with-no-END\n * input or a long no-space line. Exported from `@walkeros/core/node` only: no\n * browser consumer needs it, and it must not ride into web bundles.\n */\n\nconst MAX_LENGTH = 256;\n\n// Minimum length for a standalone run to be considered a candidate token.\nconst MIN_TOKEN_LEN = 20;\n\n// Shannon entropy threshold (bits/char). Random tokens score high (~4.5-6),\n// natural-language words and identifiers score low (~2-3.5).\nconst ENTROPY_THRESHOLD = 4.0;\n\n// Known secret prefixes that force-mask their run regardless of entropy/shape.\nconst FORCE_MASK_PREFIXES = [\n 'sk-',\n 'sk_',\n 'pk_',\n 'ghp_',\n 'gho_',\n 'xoxb-',\n 'xoxp-',\n 'AKIA',\n];\n\n// ── Regex constants (all linear, no nested quantifiers) ─────────────────────\n\n// URL credentials: scheme://user:password@host, keep user, mask password.\n// The user may be empty (`redis://:pw@host`). Neither part crosses a quote,\n// backslash or `/`, so a URL in serialized JSON never reaches an `@` further\n// along the line (an email in another field).\nconst RE_URL_CREDS = /(:\\/\\/[^/:@\\s\"\\\\]*:)[^@\\s/\"\\\\]+(@)/g;\n\n// JSON service-account field values, catches service-account blobs.\n// `private_key` holds the PEM body; `client_email`, `private_key_id`,\n// `client_id`, and `client_x509_cert_url` identify and pair with the leaked\n// credential and must not ship either (the cert url embeds the URL-encoded\n// client email). Naming them explicitly beats relying on the token-run\n// heuristics, which can miss an email or a URL. The value may contain escaped\n// newlines (\\n as literal backslash-n) which do not split the line. [^\"] is\n// safe: these values contain no embedded quotes. One alternation over the field\n// names keeps the scan single-pass and linear. The escaped `\\\"private_key\\\"`\n// form (a service account inside a serialized JSON string) matches too; its\n// optional backslash is captured and repeated around the mask.\nconst RE_JSON_SA_FIELD =\n /(\\\\?\"(?:private_key|client_email|private_key_id|client_id|client_x509_cert_url)\\\\?\"\\s*:\\s*)(\\\\?)\"[^\"]*\"/g;\n\n// Credential fields by name: the value is a secret whatever its shape (a\n// plain-word password or a `Basic`/`Bearer` header slips past the token\n// heuristics). Word parts may be joined by `-`, `_` or nothing (`api_key`,\n// `apiKey`, `API-Key`), and a header name may carry an `x-` prefix\n// (`X-API-Key`).\nconst SECRET_FIELD_NAMES =\n '(?:x-)?(?:password|passwd|secret|client[-_]?secret|secret[-_]?access[-_]?key|api[-_]?key|api[-_]?secret|access[-_]?token|refresh[-_]?token|auth[-_]?token|id[-_]?token|session[-_]?token|private[-_]?key|token|authorization)';\n\n// Plain `\"key\": value`: a string value runs to its closing quote (an escaped\n// char is consumed as a pair; the alternatives start on different chars, so\n// the scan is linear), a numeric value to its last digit. The mask is a\n// string, so the JSON stays valid.\nconst RE_JSON_SECRET_FIELD = new RegExp(\n `(\"(?:${SECRET_FIELD_NAMES})\"\\\\s*:\\\\s*)(?:\"(?:[^\"\\\\\\\\]|\\\\\\\\.)*\"|-?\\\\d[\\\\d.eE+-]*)`,\n 'gi',\n);\n\n// Escaped `\\\"key\\\":\\\"value\\\"`, the form a serialized request body carries\n// inside a JSON string. A string value ends at the escaped closing quote; a\n// quote or backslash inside it is escaped twice (`\\\\\\\"`, `\\\\\\\\`), so each\n// `\\\\` pair is consumed together with the escape it carries. Every\n// alternative starts on a different char pair, so the scan is linear. A\n// numeric value runs to its last digit.\nconst RE_JSON_SECRET_FIELD_ESCAPED = new RegExp(\n `(\\\\\\\\\"(?:${SECRET_FIELD_NAMES})\\\\\\\\\"\\\\s*:\\\\s*)(?:(\\\\\\\\\")(?:[^\"\\\\\\\\]|\\\\\\\\[^\"\\\\\\\\]|\\\\\\\\\\\\\\\\(?:\\\\\\\\\\\\\\\\|\\\\\\\\\"|[^\"\\\\\\\\]))*|-?\\\\d[\\\\d.eE+-]*)`,\n 'gi',\n);\n\n// A credential-named URL query parameter (`?api_secret=...`,\n// `&access_token=...`): the value runs to the next `&`, `#`, quote, backslash\n// or whitespace.\nconst RE_QUERY_SECRET = new RegExp(\n `([?&]${SECRET_FIELD_NAMES}=)[^&#\\\\s\"\\\\\\\\]+`,\n 'gi',\n);\n\n// A PEM private key inline in one line (a JSON string with escaped newlines),\n// under any field name: marker and body up to the END marker's dashes.\nconst RE_PEM_INLINE = /-----BEGIN [A-Z ]*PRIVATE KEY-----[^-]*/gi;\n\n// PEM block boundaries (structural removal, not regex masking).\n// Case-insensitive, tolerate leading whitespace so a lowercase or indented\n// `-----begin private key-----` block does not leak its body.\nconst RE_PEM_BEGIN = /^\\s*-----BEGIN [A-Z ]*PRIVATE KEY-----/i;\nconst RE_PEM_END = /-----END[A-Z -]*-----/i;\n\n// KEY=value / KEY: value secret pattern.\n// ReDoS-safe: the key is anchored to start-of-line or whitespace and bounded to\n// 64 chars ({0,63} after the first char), so there is no O(n²) backtracking on\n// long no-space lines. The value class includes - and . so hyphenated/dotted\n// tokens are captured whole. Two capture groups are preserved in the\n// replacement: the leading (^|\\s) boundary and the key=.\nconst TOKEN_VALUE_CLASS = '[A-Za-z0-9+/._-]';\nconst RE_KV_SECRET = new RegExp(\n `(^|\\\\s)([A-Za-z_][A-Za-z0-9_.]{0,63}\\\\s*[=:]\\\\s*)(${TOKEN_VALUE_CLASS}{12,}={0,2})`,\n 'g',\n);\n\n// Standalone candidate runs: any run of token chars (incl. - and .) ≥ 20.\n// The decision to mask happens in the callback (shouldMaskToken), keeping the\n// regex itself trivial and linear.\nconst RE_TOKEN_RUN = new RegExp(`${TOKEN_VALUE_CLASS}{${MIN_TOKEN_LEN},}`, 'g');\n\n// Force-mask prefix detector for runs that carry a known secret prefix.\n// Matches a known prefix followed by token chars (any length), so e.g.\n// `ghp_xxxxxxxx` or `xoxb-2384-2384-AbCdEf` is masked even under 20 chars.\n// Built from FORCE_MASK_PREFIXES so the list is the single source of truth.\n// Prefixes are regex-escaped (only `-`/`_` appear, both literal here, but escape\n// defensively) and ordered longest-first so the alternation is unambiguous.\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\nconst PREFIX_ALTERNATION = [...FORCE_MASK_PREFIXES]\n .sort((a, b) => b.length - a.length)\n .map(escapeRegex)\n .join('|');\nconst RE_PREFIXED_TOKEN = new RegExp(\n `(?:${PREFIX_ALTERNATION})${TOKEN_VALUE_CLASS}*`,\n 'g',\n);\n\n// A run right after a backslash starts with that escape's letters (`\\n`, `\\t`,\n// `\\u00e9` in serialized JSON). Masking keeps them so the text stays valid JSON.\nconst RE_ESCAPE_HEAD = /^(?:u[0-9a-fA-F]{4}|[bfnrt])/;\n\n// ── Entropy ──────────────────────────────────────────────────────────────────\n\n/** Shannon entropy in bits per character. Linear in input length. */\nfunction shannonEntropy(s: string): number {\n if (s.length === 0) return 0;\n const counts = new Map<string, number>();\n for (const ch of s) counts.set(ch, (counts.get(ch) ?? 0) + 1);\n let entropy = 0;\n for (const count of counts.values()) {\n const p = count / s.length;\n entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\n// ── Token masking decision ─────────────────────────────────────────────────\n\nconst RE_ALL_HEX = /^[0-9a-fA-F]+$/;\nconst RE_ALL_DIGIT = /^[0-9]+$/;\n// Real base64 padding/special chars. `/` is intentionally EXCLUDED: it is a\n// structural path/URL separator (FQNs, gs:// paths, request paths, googleapis\n// URLs), not a secret signal. Since redaction runs on every logger line,\n// treating `/` as a secret char nuked legitimate BigQuery/GCS diagnostics. Real\n// base64 secrets still carry `+`/`=` padding, are all-hex, or are high-entropy.\nconst RE_BASE64_SPECIAL = /[+=]/;\nconst RE_HAS_DIGIT = /[0-9]/;\nconst RE_HAS_LETTER = /[A-Za-z]/;\n// A dotted run is judged per segment; segments shorter than this (`oauth2`,\n// `com`) are never judged, longer ones only mask when secret-shaped (name\n// parts like `JSONWriter` or `googleapis` are not).\nconst MIN_DOT_SEGMENT_LEN = 8;\n\n/**\n * Decide whether a candidate run (a single token, no `/`) is a secret to mask.\n *\n * Mask when ANY of:\n * - all-hex (digests, SHA, etc.)\n * - all-digit (numeric tokens/ids)\n * - contains a base64 special char (+ =)\n * - contains both a digit and a letter (mixed token)\n * - Shannon entropy ≥ 4.0 bits/char (random all-letter / mixed-case tokens)\n */\nfunction isSecretSegment(run: string): boolean {\n if (RE_ALL_HEX.test(run)) return true;\n if (RE_ALL_DIGIT.test(run)) return true;\n if (RE_BASE64_SPECIAL.test(run)) return true;\n if (RE_HAS_DIGIT.test(run) && RE_HAS_LETTER.test(run)) return true;\n if (shannonEntropy(run) >= ENTROPY_THRESHOLD) return true;\n return false;\n}\n\n/**\n * Decide whether a ≥20-char candidate run is a secret to mask.\n *\n * A run containing `/` is treated as a path/URL structure, not one opaque token.\n * Paths and URLs split into short alphanumeric segments (`v2`, `projects`,\n * `12345`), each of which trips the digit+letter or entropy heuristic on its own\n * even though the whole thing is legible diagnostics. So a `/`-bearing run is\n * masked only when one of its long (≥20-char) segments independently looks like\n * a secret (e.g. a base64 blob embedded in a URL path). A base64 secret with `/`\n * still carries `+`/`=` (handled per-segment) or is hex/high-entropy, so real\n * secrets remain masked while FQNs, gs:// paths, request paths, and googleapis\n * URLs survive.\n *\n * A `.` splits a run (or a path segment) too, with a shorter bar: host names\n * (`oauth2.googleapis.com`) and dotted call paths (`JSONWriter.appendRows`)\n * stay legible, while a dotted run with any secret-shaped segment of 8+\n * chars (each part of a JWT, `abc123def456gh.ghi789...`) is masked. A\n * KEY=value value without `/` (`keyedValue`) is judged whole, dots included:\n * `DB_PASSWORD=Sup3rS3cret.Pass2024` masks although both parts are short.\n *\n * ACCEPTED best-effort limitation: a bare all-letters run with no digit, no\n * special char, no known prefix, and entropy < 4.0 (e.g. `supercalifragilistic`\n * or a long camelCase identifier like `getUserAccountSettings`) may pass through\n * unmasked. Masking every such run would destroy log readability by redacting\n * ordinary identifiers and words, which defeats the purpose of legible\n * diagnostics. This is a deliberate trade-off, not an oversight.\n */\n// A semantic version (optionally v-prefixed, with prerelease and build\n// metadata) is never a secret. Release snapshots such as\n// `4.7.0-next-1790408404259` are long enough to reach the token-run length\n// and would otherwise be masked in image tags and package specifiers.\nconst RE_SEMVER =\n /^v?\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\nfunction shouldMaskToken(run: string, keyedValue = false): boolean {\n if (RE_SEMVER.test(run)) return false;\n if (run.includes('/')) {\n // Per-segment: only mask if a long segment is itself secret-shaped. Short\n // path segments (the bulk of any URL) never qualify, keeping URLs legible.\n return run\n .split('/')\n .filter((segment) => segment.length >= MIN_TOKEN_LEN)\n .some(isSecretDottedRun);\n }\n return keyedValue ? isSecretSegment(run) : isSecretDottedRun(run);\n}\n\n/** A run without `/`: secret when any 8+ char dot segment is secret-shaped. */\nfunction isSecretDottedRun(run: string): boolean {\n if (!run.includes('.')) return isSecretSegment(run);\n return run\n .split('.')\n .filter((segment) => segment.length >= MIN_DOT_SEGMENT_LEN)\n .some(isSecretSegment);\n}\n\n// ── PEM block removal ────────────────────────────────────────────────────────\n\n/**\n * Remove all PEM private-key blocks from an array of lines.\n * A block starts at a BEGIN PRIVATE KEY marker and ends at the matching END\n * marker (inclusive). If no END is found, everything to end of entry is dropped.\n */\nfunction removePemBlocks(lines: string[]): string[] {\n const out: string[] = [];\n let inBlock = false;\n\n for (const line of lines) {\n if (!inBlock) {\n if (RE_PEM_BEGIN.test(line)) {\n inBlock = true;\n continue; // start-of-block line dropped\n }\n out.push(line);\n } else {\n if (RE_PEM_END.test(line)) {\n inBlock = false;\n }\n // drop every in-block line, including the END marker\n }\n }\n\n return out;\n}\n\n// ── Per-line secret masking ──────────────────────────────────────────────────\n\n/**\n * Mask secrets in a single (non-PEM) line.\n * All patterns are applied in order; all regex are linear (no nested quantifiers).\n */\nfunction maskLine(line: string): string {\n let s = line;\n\n // 1. URL credentials: ://user:secret@host → ://user:***@host\n s = s.replace(RE_URL_CREDS, '$1***$2');\n\n // 1a. Credential-named query parameters, whatever the value's shape.\n s = s.replace(RE_QUERY_SECRET, '$1***');\n\n // 1b. A PEM private key inline (a JSON string), whatever its field name.\n s = s.replace(RE_PEM_INLINE, '***');\n\n // 2. KEY=secret / KEY: secret (anchored, bounded key, ReDoS-safe).\n // Mask the value only when it is secret-shaped. This stops `scheme://host/...`\n // (matched as `gs:` / `https:` key + `//...` value) from masking legitimate\n // URLs/paths, while real `TOKEN=secret` values still mask. The `/`-aware\n // shouldMaskToken keeps path-shaped values legible.\n s = s.replace(\n RE_KV_SECRET,\n (match: string, boundary: string, keyPart: string, value: string) =>\n shouldMaskToken(value, true) ? `${boundary}${keyPart}***` : match,\n );\n\n // 3. Known-prefix tokens (force-mask regardless of length/entropy)\n s = s.replace(RE_PREFIXED_TOKEN, '***');\n\n // 4. Standalone candidate runs ≥ 20 chars, mask by shape/entropy\n s = s.replace(\n RE_TOKEN_RUN,\n (match: string, offset: number, input: string) => {\n if (!shouldMaskToken(match)) return match;\n const head =\n offset > 0 && input[offset - 1] === '\\\\'\n ? RE_ESCAPE_HEAD.exec(match)?.[0]\n : undefined;\n return head ? `${head}***` : '***';\n },\n );\n\n return s;\n}\n\n// ── Known secret values ──────────────────────────────────────────────────────\n\n// Shorter values are too likely to occur in ordinary text to mask on sight.\nexport const MIN_KNOWN_LEN = 6;\n\nexport interface ScrubOptions {\n /**\n * Exact secret values to mask wherever they occur (e.g. the resolved\n * `$secret.NAME` values of a flow). Values under 6 characters are ignored.\n */\n known?: readonly string[];\n}\n\n/**\n * Mask every exact occurrence of each known value, raw, JSON-escaped (the\n * form it takes inside serialized JSON), escaped twice (a JSON string\n * serialized again, e.g. a request body inside JSON output) and URL-encoded\n * (a URL, or a form body where a space is `+`), longest first so\n * a value containing another is masked whole. Literal split/join, never a regex built from the\n * value.\n */\nexport function maskKnownValues(\n line: string,\n known?: readonly string[],\n): string {\n if (!known || known.length === 0) return line;\n const forms = new Set<string>();\n for (const value of known) {\n if (value.length < MIN_KNOWN_LEN) continue;\n const escaped = JSON.stringify(value).slice(1, -1);\n forms.add(value);\n forms.add(escaped);\n forms.add(JSON.stringify(escaped).slice(1, -1));\n // In a URL or a form body: `encodeURIComponent` (also with a space as\n // `+`), `encodeURI` (keeps `/ : + =`) and `URLSearchParams` (also\n // encodes `! ' ( ) ~`, a space as `+`).\n const component = uriEncoded(encodeURIComponent, value);\n if (component) {\n forms.add(component);\n forms.add(component.replace(/%20/g, '+'));\n }\n const uri = uriEncoded(encodeURI, value);\n if (uri) forms.add(uri);\n forms.add(new URLSearchParams({ v: value }).toString().slice(2));\n }\n let s = line;\n for (const form of [...forms].sort((a, b) => b.length - a.length)) {\n if (s.includes(form)) s = replaceKnown(s, form);\n }\n return s;\n}\n\n/** `encode(value)`, or undefined for a value it cannot encode (a lone surrogate). */\nfunction uriEncoded(\n encode: (value: string) => string,\n value: string,\n): string | undefined {\n try {\n return encode(value);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Replace every occurrence of `form` with `***`. An occurrence right after an\n * escaping backslash (an odd run of them) keeps the escape's letters, as\n * `maskLine` does, so serialized JSON stays valid.\n */\nfunction replaceKnown(line: string, form: string): string {\n let out = '';\n let from = 0;\n let at = line.indexOf(form);\n while (at !== -1) {\n // Count the backslashes just before the match; text before `from` was\n // an earlier match, now `***`, so the run stops there.\n let slashes = 0;\n while (at - slashes > from && line[at - slashes - 1] === '\\\\') slashes++;\n const head =\n slashes % 2 === 1 ? (RE_ESCAPE_HEAD.exec(form)?.[0] ?? form[0]) : '';\n out += `${line.slice(from, at)}${head}***`;\n from = at + form.length;\n at = line.indexOf(form, from);\n }\n return out + line.slice(from);\n}\n\n// ── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Scrub credential material from a log line (or multi-line entry) WITHOUT\n * truncating. This is the shared secret redactor used by the CLI and runtime\n * logger handlers (covers their console/stderr lines and the ring before\n * egress). Output a dependency writes straight to `console` or stderr never\n * passes through it.\n *\n * Algorithm:\n * 0. Mask each `options.known` value exactly, raw, JSON-escaped and escaped\n * twice, longest first.\n * 1. Mask JSON service-account fields (private_key, client_email,\n * private_key_id, client_id, client_x509_cert_url) and credential-named\n * JSON fields (password, token, authorization, ...) BEFORE splitting\n * (service-account blobs embed PEM blocks as \\\\n-encoded strings; masking\n * first prevents the BEGIN marker from appearing on its own line and dropping\n * surrounding fields).\n * 2. Split on \\\\n.\n * 3. Remove PEM private-key blocks structurally (BEGIN…END inclusive,\n * case-insensitive; a no-END block drops to end of entry).\n * 4. For each surviving line: mask URL creds, inline PEM keys, KEY=secret,\n * prefixed tokens,\n * high-entropy/shape-based token runs.\n * 5. Rejoin with \\\\n.\n */\nexport function scrubSecrets(line: string, options: ScrubOptions = {}): string {\n // Step 0: known secret values, exact, before any pattern can split them\n const withoutKnown = maskKnownValues(line, options.known);\n\n // Step 1: JSON service-account field masking before any line splitting\n const withoutJsonKey = withoutKnown\n .replace(RE_JSON_SA_FIELD, '$1$2\"***$2\"')\n .replace(\n RE_JSON_SECRET_FIELD_ESCAPED,\n (_match: string, keyPart: string, quote: string | undefined) =>\n quote ? `${keyPart}${quote}***` : `${keyPart}\\\\\"***\\\\\"`,\n )\n .replace(RE_JSON_SECRET_FIELD, '$1\"***\"');\n\n // Step 2: split\n const rawLines = withoutJsonKey.split('\\n');\n\n // Step 3: remove PEM blocks (any remaining standalone markers after step 1)\n const cleanLines = removePemBlocks(rawLines);\n\n // Step 4: mask each surviving line\n const maskedLines = cleanLines.map(maskLine);\n\n // Step 5: rejoin\n return maskedLines.join('\\n');\n}\n\n/**\n * Redact a log line and truncate to the heartbeat wire contract (256 chars).\n * This is the heartbeat-egress variant: scrub secrets, then truncate AFTER\n * masking so a token straddling char 256 is masked, not left partially visible.\n *\n * The app's heartbeat schema enforces message .max(256); a 257-char string\n * would fail zod .parse and drop the whole heartbeat. Reserve one char for the\n * ellipsis so the TOTAL length is at most MAX_LENGTH (256).\n */\nexport function redactLine(line: string): string {\n const scrubbed = scrubSecrets(line);\n\n if (scrubbed.length > MAX_LENGTH) {\n return scrubbed.slice(0, MAX_LENGTH - 1) + '…';\n }\n\n return scrubbed;\n}\n","import { TextDecoder } from 'util';\n\n/**\n * Turn a recorded simulate value (call arguments, events, errors) into plain\n * JSON-safe data. One formatter for the CLI `push` output (`--json` and text)\n * and the MCP `flow_simulate` result, so a value a vendor call really\n * receives prints readably and never throws:\n *\n * - `Error` → `{ name, message }`\n * - `Buffer`, any typed array, `DataView`, `ArrayBuffer` → utf8 string of its\n * bytes, or `base64:<...>` when not valid utf8\n * - `bigint` → string\n * - `Map` → array of `[key, value]` entries, `Set` → array of values\n * - a cycle → `\"[Circular]\"`\n * - a function → `\"[Function <name>]\"`\n * - a class instance (an SDK command, say) → `{ <ClassName>: <own fields> }`,\n * named by its `Symbol.toStringTag` when it has one\n * - a value whose getter, `toJSON` or proxy trap throws → `\"[Unprintable]\"`\n *\n * Secrets are not this function's concern: the printed text egresses through\n * `scrubSecrets`.\n */\nexport function toPrintable(value: unknown): unknown {\n return walk(value, new Set());\n}\n\nconst utf8 = new TextDecoder('utf-8', { fatal: true });\n\nfunction bytesToString(bytes: Uint8Array): string {\n try {\n return utf8.decode(bytes);\n } catch {\n return `base64:${Buffer.from(bytes).toString('base64')}`;\n }\n}\n\n// Values can come from another realm (a web flow simulates inside jsdom), where\n// `instanceof` against this realm's constructors fails. The built-in tag does\n// not depend on the realm.\nfunction tagOf(value: object): string {\n return Object.prototype.toString.call(value);\n}\n\nfunction isError(value: object): value is Error {\n return tagOf(value) === '[object Error]';\n}\n\nfunction isArrayBuffer(value: object): value is ArrayBuffer {\n return tagOf(value) === '[object ArrayBuffer]';\n}\n\n/** The raw bytes of a typed array, `DataView` or `ArrayBuffer`. */\nfunction bytesOf(value: object): Uint8Array | undefined {\n if (ArrayBuffer.isView(value))\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n if (isArrayBuffer(value)) return new Uint8Array(value);\n return undefined;\n}\n\nfunction isMap(value: object): value is Map<unknown, unknown> {\n return tagOf(value) === '[object Map]';\n}\n\nfunction isSet(value: object): value is Set<unknown> {\n return tagOf(value) === '[object Set]';\n}\n\nfunction hasToJSON(value: object): value is { toJSON: () => unknown } {\n return 'toJSON' in value && typeof value.toJSON === 'function';\n}\n\n/**\n * Name of a class instance; undefined for plain objects. A custom\n * `Symbol.toStringTag` wins over the constructor name, which a minifier may\n * have renamed.\n */\nfunction className(value: object): string | undefined {\n const tag = tagOf(value).slice('[object '.length, -1);\n if (tag !== 'Object') return tag;\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto === null || proto === Object.prototype) return undefined;\n if (typeof proto !== 'object') return undefined;\n const ctor: unknown = Reflect.get(proto, 'constructor');\n // By name, not identity: a plain object from another realm has that\n // realm's `Object` as its constructor.\n if (typeof ctor !== 'function' || ctor.name === 'Object') return undefined;\n return ctor.name || undefined;\n}\n\nfunction walk(value: unknown, ancestors: Set<object>): unknown {\n if (typeof value === 'bigint') return value.toString();\n if (typeof value === 'function')\n return `[Function ${value.name || 'anonymous'}]`;\n if (typeof value === 'symbol') return value.toString();\n if (value === null || typeof value !== 'object') return value;\n\n // A throwing getter, `toJSON` or proxy trap must not break the output.\n try {\n return walkObject(value, ancestors);\n } catch {\n return '[Unprintable]';\n }\n}\n\nfunction walkObject(value: object, ancestors: Set<object>): unknown {\n if (isError(value)) return { name: value.name, message: value.message };\n const bytes = bytesOf(value);\n if (bytes) return bytesToString(bytes);\n if (ancestors.has(value)) return '[Circular]';\n\n ancestors.add(value);\n try {\n if (isMap(value))\n return Array.from(value.entries(), ([k, v]) => [\n walk(k, ancestors),\n walk(v, ancestors),\n ]);\n if (isSet(value))\n return Array.from(value.values(), (v) => walk(v, ancestors));\n if (Array.isArray(value)) return value.map((v) => walk(v, ancestors));\n if (hasToJSON(value)) return walk(value.toJSON(), ancestors);\n\n const fields: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(value)) {\n fields[key] = walk(field, ancestors);\n }\n const name = className(value);\n return name ? { [name]: fields } : fields;\n } finally {\n ancestors.delete(value);\n }\n}\n","import { MIN_KNOWN_LEN, scrubSecrets, type ScrubOptions } from './redactLine';\nimport { toPrintable } from './toPrintable';\n\n/**\n * A deep copy of `value` in which every number whose printed form contains a\n * known secret (6+ characters, e.g. `12345678`, `-1234567`, `1234567.5`)\n * becomes `'***'`. Masking such a number inside serialized JSON would leave an\n * unquoted `***` and break the JSON, so it runs on the value before\n * `JSON.stringify`. Exported for its unit test; egress goes through\n * `scrubJson`, which owns the order.\n */\nexport function maskKnownNumbers(\n value: unknown,\n known: readonly string[],\n): unknown {\n const candidates = known.filter((secret) => secret.length >= MIN_KNOWN_LEN);\n const mask = (item: unknown): unknown => {\n if (typeof item === 'number') {\n const printed = String(item);\n return candidates.some((secret) => printed.includes(secret))\n ? '***'\n : item;\n }\n if (Array.isArray(item)) return item.map(mask);\n if (item && typeof item === 'object') {\n const copy: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(item)) copy[key] = mask(entry);\n return copy;\n }\n return item;\n };\n return mask(value);\n}\n\n/**\n * Serialize a value for egress with secrets masked: its printable form (see\n * `toPrintable`), numbers that print a known value become `'***'`,\n * `JSON.stringify`, then `scrubSecrets` with the same known values. The order\n * keeps the result valid JSON. A value with no JSON form prints `undefined`.\n */\nexport function scrubJson(\n value: unknown,\n options: ScrubOptions & { space?: number } = {},\n): string {\n const known = options.known ?? [];\n const text =\n JSON.stringify(\n maskKnownNumbers(toPrintable(value), known),\n null,\n options.space,\n ) ?? 'undefined';\n return scrubSecrets(text, { known });\n}\n"],"mappings":"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","names":["Level","os","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/node.ts","../src/types/logger.ts","../src/logger.ts","../src/redactLine.ts","../src/node/toPrintable.ts","../src/node/scrubJson.ts","../src/errorCause.ts","../src/store/codec.ts","../src/node/storeCodec.ts"],"sourcesContent":["/**\n * Node entry point (`@walkeros/core/node`).\n *\n * Helpers shared by `@walkeros/cli`, `@walkeros/runner` and the server stores\n * that do not belong in the browser `.` entry: the temp-path helpers import\n * node builtins, the terminal logger config writes to the console, and the\n * secret redactor, the simulate output formatter (`toPrintable`) and the store\n * byte codec (both read `Buffer`) have no browser consumer. Core gains no\n * dependency for them: the colouriser is injected by the caller, so chalk\n * stays in the packages that already depend on it.\n */\n\n/* eslint-disable no-console */\nimport os from 'os';\nimport path from 'path';\nimport { createLogger } from './logger';\nimport { maskKnownValues, scrubSecrets } from './redactLine';\nimport { maskKnownNumbers } from './node/scrubJson';\n\nexport { scrubSecrets, redactLine } from './redactLine';\nexport type { ScrubOptions } from './redactLine';\nexport { scrubJson } from './node/scrubJson';\nexport { toPrintable } from './node/toPrintable';\nexport {\n serializeStoreValue,\n deserializeStoreValue,\n StoreCodecError,\n} from './node/storeCodec';\nimport type { Config, Format, Instance, LogContext } from './types/logger';\nimport { Level } from './types/logger';\n\nconst DEFAULT_TMP_ROOT = os.tmpdir();\n\n/**\n * Get a path within the temp directory.\n *\n * @param tmpDir - Custom temp directory (optional, for --tmp-dir flag)\n * @param segments - Path segments to join\n * @returns Absolute path within temp directory\n *\n * @example\n * ```typescript\n * getTmpPath() // → \"/tmp\"\n * getTmpPath(undefined, 'entry.js') // → \"/tmp/entry.js\"\n * getTmpPath(undefined, 'cache', 'builds') // → \"/tmp/cache/builds\"\n * getTmpPath('/custom', 'cache') // → \"/custom/cache\"\n * ```\n */\nexport function getTmpPath(tmpDir?: string, ...segments: string[]): string {\n const root = tmpDir || DEFAULT_TMP_ROOT;\n // Always return absolute path (esbuild requirement)\n const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);\n return path.join(absoluteRoot, ...segments);\n}\n\n/**\n * A temp path resolver with the root directory baked in.\n *\n * Use {@link createTmpResolver} at entry points to capture the temp root once,\n * then pass the resolver to downstream functions. This prevents the class of\n * bugs where callers forget to pass tmpDir.\n *\n * @example\n * ```typescript\n * const tmp = createTmpResolver(buildOptions.tempDir);\n * const cacheDir = tmp('cache', 'packages'); // root is baked in\n * ```\n */\nexport type TmpResolver = (...segments: string[]) => string;\n\nexport function createTmpResolver(tmpDir?: string): TmpResolver {\n const root = tmpDir || DEFAULT_TMP_ROOT;\n const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);\n return (...segments: string[]) => path.join(absoluteRoot, ...segments);\n}\n\n/**\n * Get the default temp root directory.\n */\nexport function getDefaultTmpRoot(): string {\n return DEFAULT_TMP_ROOT;\n}\n\n/**\n * One log line as a structured entry: the shape a JSON line prints and the\n * `onLine` tap receives, masked like the text line. `message` is\n * `[scope] message` without the context; `scope` and `context` are omitted\n * when empty. When the line would pass {@link MAX_JSON_LINE_BYTES}, a\n * message above half the cap keeps a prefix (`messageTruncated`), then\n * `context` becomes a string prefix of its JSON (`contextTruncated`).\n */\nexport interface LogEntry {\n severity: 'ERROR' | 'WARNING' | 'INFO' | 'DEBUG';\n message: string;\n messageTruncated?: true;\n scope?: string;\n context?: Record<string, unknown> | string;\n contextTruncated?: true;\n time: string;\n}\n\n/**\n * Size cap of one JSON line, far below the 256 KiB a log platform accepts\n * per entry: a longer entry may be dropped whole rather than cut.\n */\nexport const MAX_JSON_LINE_BYTES = 32 * 1024;\n\nexport interface CLILoggerOptions {\n /**\n * Opens the DEBUG gate. A function is read per line, so a host can open\n * it for the level a flow sets once it knows it.\n */\n verbose?: boolean | (() => boolean);\n silent?: boolean;\n json?: boolean;\n stderr?: boolean;\n /**\n * Taps every line before any visibility gate: the masked text line, and\n * the same line as a structured entry (scope, and the context with fields\n * such as code, status, retryable and suppressed) for forwarding.\n */\n onLine?: (level: Level, message: string, entry: LogEntry) => void;\n /**\n * Exact secret values masked in every line (see `scrubSecrets`). An array is\n * copied at creation; a function is read per line, so values learned after\n * the logger exists (secrets fetched at startup) are masked too.\n */\n knownSecrets?: readonly string[] | (() => readonly string[]);\n /**\n * Output format (`text` by default): `json` prints one JSON object per\n * line, ERROR and WARN to stderr, INFO and DEBUG to stdout, without\n * colour. A function is read per line, so a host can switch to the\n * format a flow sets once it knows it. `json` (machine output) wins.\n */\n format?: Format | (() => Format | undefined);\n}\n\n/** Formats one already-scrubbed line for the terminal. */\nexport type LineFormatter = (line: string) => string;\n\n/**\n * Per-level terminal formatters. Every level defaults to identity, so a caller\n * that passes nothing gets plain uncoloured output.\n */\nexport interface CLILoggerColors {\n error?: LineFormatter;\n warn?: LineFormatter;\n info?: LineFormatter;\n debug?: LineFormatter;\n}\n\nconst identity: LineFormatter = (line) => line;\n\nconst TMP_ROOT_LABEL = '$TMPDIR';\n\n/**\n * Replace each occurrence of the literal temp root, followed by a path\n * separator, with `$TMPDIR`. Only occurrences that start a path count: the\n * character before must not continue a path, so `/mnt/tmp/x` keeps its text\n * when the root is `/tmp`. Literal matching only, never a pattern built from\n * the path.\n */\nfunction labelTmpRoot(line: string, root: string): string {\n if (!root || root === path.sep) return line;\n const needle = root.endsWith(path.sep) ? root : root + path.sep;\n const parts = line.split(needle);\n if (parts.length === 1) return line;\n let result = parts[0];\n for (let i = 1; i < parts.length; i++) {\n const before = result.length > 0 ? result[result.length - 1] : '';\n const startsPath = before === '' || !/[\\w./\\\\~-]/.test(before);\n result += (startsPath ? TMP_ROOT_LABEL + path.sep : needle) + parts[i];\n }\n return result;\n}\n\nconst SEVERITY: Record<Level, LogEntry['severity']> = {\n [Level.ERROR]: 'ERROR',\n [Level.WARN]: 'WARNING',\n [Level.INFO]: 'INFO',\n [Level.DEBUG]: 'DEBUG',\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * The structured entry of one line and its JSON text, masked in the text\n * line's order: numbers that print a known value become `'***'` before\n * serializing (masking inside serialized JSON would break it), then known\n * values, the temp root label and the pattern rules, applied to the message\n * and to the serialized context. A context that cannot serialize, or whose\n * masked form no longer parses, becomes `\"[unserializable context]\"`. A\n * line above {@link MAX_JSON_LINE_BYTES} keeps a prefix of its masked\n * message (when that is above half the cap) and of its masked context JSON,\n * so a cut never splits a secret.\n */\nfunction buildLogEntry(\n level: Level,\n message: string,\n context: LogContext,\n scope: string[],\n mask: (text: string) => string,\n known: readonly string[] | undefined,\n): { entry: LogEntry; line: string } {\n const scopeName = scope.join(':');\n const entry: LogEntry = {\n severity: SEVERITY[level],\n message: mask(`${scopeName ? `[${scopeName}] ` : ''}${message}`),\n time: new Date().toISOString(),\n };\n if (scopeName) entry.scope = scopeName;\n\n let contextJson: string | undefined;\n if (Object.keys(context).length > 0) {\n try {\n contextJson = mask(\n JSON.stringify(maskKnownNumbers(context, known ?? [])),\n );\n const parsed: unknown = JSON.parse(contextJson);\n entry.context = isRecord(parsed) ? parsed : '[unserializable context]';\n } catch {\n contextJson = undefined;\n entry.context = '[unserializable context]';\n }\n }\n\n let line = JSON.stringify(entry);\n if (Buffer.byteLength(line) <= MAX_JSON_LINE_BYTES) return { entry, line };\n\n // The message keeps at most half the cap, the context the rest.\n const half = MAX_JSON_LINE_BYTES / 2;\n if (Buffer.byteLength(entry.message) > half) {\n const message = entry.message;\n let size = half;\n do {\n entry.message = message.slice(0, size);\n size = Math.floor(size / 2);\n } while (Buffer.byteLength(entry.message) > half && size > 0);\n entry.messageTruncated = true;\n line = JSON.stringify(entry);\n }\n if (contextJson && Buffer.byteLength(line) > MAX_JSON_LINE_BYTES) {\n entry.contextTruncated = true;\n let size = MAX_JSON_LINE_BYTES - Buffer.byteLength(entry.message) - 256;\n do {\n entry.context = contextJson.slice(0, Math.max(size, 0));\n line = JSON.stringify(entry);\n size = Math.floor(size / 2);\n } while (Buffer.byteLength(line) > MAX_JSON_LINE_BYTES && size > 0);\n }\n return { entry, line };\n}\n\n/**\n * Build the `Logger.Config` (level + handler + jsonHandler) that backs a\n * terminal logger. Returned separately so the runtime can hand the SAME\n * handler (including the `onLine` ring tap) to the deployed bundle's\n * collector.\n *\n * The collector in a deployed bundle builds its own logger from this config\n * (`config.logger`), so its destination errors flow through the identical\n * `onLine` tap the runtime logger uses, landing in the shared ErrorRing.\n * There is no parallel ring: one handler, one tap.\n *\n * Level: `Level.DEBUG` so the handler sees every line and controls visibility\n * itself (verbose/silent gating). ERROR is therefore always emitted into the\n * ring regardless of `--verbose`.\n *\n * `colors` formats each level for the terminal. It is applied to console\n * output only, never to the line handed to `onLine`.\n */\nexport function createCLILoggerConfig(\n options: CLILoggerOptions = {},\n colors: CLILoggerColors = {},\n): Config {\n const {\n verbose = false,\n silent = false,\n json = false,\n stderr = false,\n knownSecrets,\n format,\n } = options;\n const knownCopy =\n typeof knownSecrets === 'function'\n ? undefined\n : knownSecrets\n ? [...knownSecrets]\n : undefined;\n const readKnown = (): readonly string[] | undefined =>\n typeof knownSecrets === 'function' ? knownSecrets() : knownCopy;\n const tmpRoot = os.tmpdir();\n const out = stderr ? console.error : console.log;\n const errorColor = colors.error ?? identity;\n const warnColor = colors.warn ?? identity;\n const infoColor = colors.info ?? identity;\n const debugColor = colors.debug ?? identity;\n\n const readFormat = (): Format =>\n (typeof format === 'function' ? format() : format) ?? 'text';\n const readVerbose = (): boolean =>\n typeof verbose === 'function' ? verbose() : verbose;\n // The text line's masking order, shared by the JSON entry: known values\n // first, so the label can never split one; then the temp root label; then\n // the pattern rules.\n const mask = (text: string): string =>\n scrubSecrets(labelTmpRoot(maskKnownValues(text, readKnown()), tmpRoot));\n\n return {\n // Let handler control visibility: pass everything through. With the gate\n // at DEBUG, ERROR always reaches the handler (and the ring) even without\n // --verbose.\n level: Level.DEBUG,\n handler: (level, message, context, scope) => {\n // Machine output (`json`) prints only its result; silent keeps errors;\n // DEBUG needs verbose. A line nobody prints and no tap reads costs\n // nothing more.\n const shown =\n !json &&\n (level === Level.ERROR || !silent) &&\n (level !== Level.DEBUG || readVerbose());\n const tap = options.onLine;\n if (!shown && !tap) return;\n const asJson = shown && readFormat() === 'json';\n\n // Build formatted message\n const scopePath = scope.length > 0 ? `[${scope.join(':')}] ` : '';\n // Serialize the structured context into the line so error details (gRPC\n // status codes, row counts, target tables) reach stderr and the ring.\n // Serialization happens BEFORE scrubSecrets so redaction covers context\n // values too; the heartbeat path's 256-char cap stays as the wire\n // backstop. A context that cannot stringify (circular) must never break\n // logging.\n const textLine = (): string => {\n let meta = '';\n if (Object.keys(context).length > 0) {\n try {\n meta = ` ${JSON.stringify(context)}`;\n } catch {\n meta = ' [unserializable context]';\n }\n }\n // Redact secrets ONCE here, before BOTH the onLine ring tap and the\n // console.* output. stderr is shipped directly by the log collector,\n // so the heartbeat-egress redactor alone would miss it; doing it in\n // the handler scrubs every line routed through this logger (collector\n // and steps) on both paths. Length is preserved here (no truncation);\n // the heartbeat path applies the 256-char wire cap separately as a\n // backstop on already-redacted text.\n // Order: known values first, so the label can never split one (a\n // `sqlite:/tmp/...` URL, or a value that only touches the root at its\n // edge); then the temp root label, since a long per-user root (macOS\n // `/var/folders/...`) would otherwise read as a token; then the\n // pattern rules.\n return mask(`${scopePath}${message}${meta}`);\n };\n // The structured entry only where it is used: a JSON line, or the tap.\n const built =\n asJson || tap\n ? buildLogEntry(level, message, context, scope, mask, readKnown())\n : undefined;\n const fullMessage = tap || !asJson ? textLine() : '';\n\n // Tap every line before the gate so no level is dropped from capture.\n if (tap && built) {\n try {\n tap(level, fullMessage, built.entry);\n } catch {\n // Swallow: a throwing consumer must never break logging (and we\n // must not call logger methods here to avoid infinite recursion).\n }\n }\n\n if (!shown) return;\n\n // JSON lines: one object per line, no colour; ERROR and WARN on stderr\n // (where platforms that ship only stderr still see them), INFO and\n // DEBUG on stdout.\n if (asJson && built) {\n if (level === Level.ERROR || level === Level.WARN)\n console.error(built.line);\n else out(built.line);\n return;\n }\n\n if (level === Level.ERROR) console.error(errorColor(fullMessage));\n else if (level === Level.DEBUG) out(` ${debugColor(fullMessage)}`);\n else\n out(\n level === Level.WARN\n ? warnColor(fullMessage)\n : infoColor(fullMessage),\n );\n },\n jsonHandler: (data) => {\n if (!silent) out(JSON.stringify(data, null, 2));\n },\n };\n}\n\n/**\n * Create a core Logger.Instance with terminal-appropriate behavior.\n *\n * Behavior:\n * - ERROR: always shown (via console.error, `colors.error`) unless --json\n * - WARN: shown unless --silent or --json\n * - INFO: shown unless --silent or --json\n * - DEBUG: shown only with --verbose (and not --silent/--json)\n * - json(): shown unless --silent\n */\nexport function createCLILogger(\n options: CLILoggerOptions = {},\n colors: CLILoggerColors = {},\n): Instance {\n return createLogger(createCLILoggerConfig(options, colors));\n}\n","/**\n * Log levels from most to least severe\n */\nexport enum Level {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n}\n\n/**\n * Normalized error context extracted from Error objects\n */\nexport interface ErrorContext {\n message: string;\n name: string;\n stack?: string;\n cause?: unknown;\n}\n\n/**\n * Context passed to log handlers\n * If an Error was passed, it's normalized into the error property\n */\nexport interface LogContext {\n [key: string]: unknown;\n error?: ErrorContext;\n}\n\n/**\n * Log message function signature\n * Accepts string or Error as message, with optional context\n */\nexport type LogFn = (\n message: string | Error,\n context?: unknown | Error,\n) => void;\n\n/**\n * Throw function signature: throws an Error with the message, never logs\n * (the catching collector logs the failure once). Returns never.\n */\nexport type ThrowFn = (message: string | Error, context?: unknown) => never;\n\n/**\n * Default handler function (passed to custom handlers for chaining)\n */\nexport type DefaultHandler = (\n level: Level,\n message: string,\n context: LogContext,\n scope: string[],\n) => void;\n\n/**\n * Custom log handler function\n * Receives originalHandler to allow middleware-style chaining\n */\nexport type Handler = (\n level: Level,\n message: string,\n context: LogContext,\n scope: string[],\n originalHandler: DefaultHandler,\n) => void;\n\n/**\n * Logger instance with scoping support\n * All logs automatically include trace path from scoping\n */\nexport interface Instance {\n /**\n * Log an error message (always visible unless silenced)\n */\n error: LogFn;\n\n /**\n * Log a warning (degraded state, config issues, transient failures)\n */\n warn: LogFn;\n\n /**\n * Log an informational message\n */\n info: LogFn;\n\n /**\n * Log a debug message\n */\n debug: LogFn;\n\n /**\n * Throw an Error with the message. Does not log: the collector's catch\n * writes the one line for the failure.\n */\n throw: ThrowFn;\n\n /**\n * Output structured JSON data\n */\n json: (data: unknown) => void;\n\n /**\n * Create a scoped child logger with automatic trace path\n * @param name - Scope name (e.g., destination type, destination key)\n * @returns A new logger instance with the scope applied\n */\n scope: (name: string) => Instance;\n}\n\n/**\n * Output format of a server terminal logger: one text line per call, or one\n * JSON object per line (`severity`, `message`, `scope`, `context`, `time`),\n * which Cloud Run, Loki and Datadog read as structured entries.\n */\nexport type Format = 'text' | 'json';\n\n/**\n * Logger configuration options\n */\nexport interface Config {\n /**\n * Minimum log level to display\n * @default Level.ERROR\n */\n level?: Level | keyof typeof Level;\n\n /**\n * Output format of a server flow's log lines (`@walkeros/core/node`'s\n * terminal logger, used by `runneros`). Web flows log to the browser\n * console and reject it.\n * @default 'text'\n */\n format?: Format;\n\n /**\n * Custom log handler function\n * Receives originalHandler to preserve default behavior\n */\n handler?: Handler;\n\n /** Custom handler for json() output. Default: console.log(JSON.stringify(data, null, 2)) */\n jsonHandler?: (data: unknown) => void;\n}\n\n/**\n * Internal config with resolved values and scope\n */\nexport interface InternalConfig {\n level: Level;\n handler?: Handler;\n jsonHandler?: (data: unknown) => void;\n scope: string[];\n}\n\n/**\n * Logger factory function type\n */\nexport type Factory = (config?: Config) => Instance;\n","import type {\n Config,\n DefaultHandler,\n ErrorContext,\n Handler,\n Instance,\n InternalConfig,\n LogContext,\n} from './types/logger';\nimport { Level } from './types/logger';\n\n/**\n * An error's `cause` reduced to its name and code: a cause can carry a\n * request, a response body or settings, none of which belong in a log line.\n */\nfunction normalizeCause(\n cause: unknown,\n): { name?: string; code?: string | number } | undefined {\n if (typeof cause !== 'object' || cause === null) return undefined;\n const reduced: { name?: string; code?: string | number } = {};\n if ('name' in cause && typeof cause.name === 'string')\n reduced.name = cause.name;\n if (\n 'code' in cause &&\n (typeof cause.code === 'string' || typeof cause.code === 'number')\n )\n reduced.code = cause.code;\n return reduced;\n}\n\n/**\n * Normalize an Error object into ErrorContext. Never copies a response body\n * (`StepError.body`) and keeps only the cause's name and code.\n */\nfunction normalizeError(err: Error): ErrorContext {\n const context: ErrorContext = {\n message: err.message,\n name: err.name,\n stack: err.stack,\n };\n const cause = 'cause' in err ? normalizeCause(err.cause) : undefined;\n if (cause) context.cause = cause;\n return context;\n}\n\n/**\n * Normalize message and context parameters\n * Handles Error objects passed as message or context\n */\nfunction normalizeParams(\n message: string | Error,\n context?: unknown | Error,\n): { message: string; context: LogContext } {\n let normalizedMessage: string;\n let normalizedContext: LogContext = {};\n\n // Handle message\n if (message instanceof Error) {\n normalizedMessage = message.message;\n normalizedContext.error = normalizeError(message);\n } else {\n normalizedMessage = message;\n }\n\n // Handle context\n if (context !== undefined) {\n if (context instanceof Error) {\n normalizedContext.error = normalizeError(context);\n } else if (typeof context === 'object' && context !== null) {\n normalizedContext = { ...normalizedContext, ...(context as object) };\n // If context has an error property that's an Error, normalize it\n if (\n 'error' in normalizedContext &&\n normalizedContext.error instanceof Error\n ) {\n normalizedContext.error = normalizeError(\n normalizedContext.error as unknown as Error,\n );\n }\n } else {\n normalizedContext.value = context;\n }\n }\n\n return { message: normalizedMessage, context: normalizedContext };\n}\n\n/**\n * Default console-based log handler\n */\nconst defaultHandler: DefaultHandler = (level, message, context, scope) => {\n const levelName = Level[level];\n const scopePath = scope.length > 0 ? ` [${scope.join(':')}]` : '';\n const prefix = `${levelName}${scopePath}`;\n\n const hasContext = Object.keys(context).length > 0;\n\n const consoleFn =\n level === Level.ERROR\n ? console.error\n : level === Level.WARN\n ? console.warn\n : console.log;\n\n if (hasContext) {\n consoleFn(prefix, message, context);\n } else {\n consoleFn(prefix, message);\n }\n};\n\n/**\n * Normalize log level from string or enum to enum value\n */\nfunction normalizeLevel(level: Level | keyof typeof Level): Level {\n if (typeof level === 'string') {\n return Level[level as keyof typeof Level];\n }\n return level;\n}\n\n/**\n * Create a logger instance\n *\n * @param config - Logger configuration\n * @returns Logger instance with all log methods and scoping support\n *\n * @example\n * ```typescript\n * // Basic usage\n * const logger = createLogger({ level: 'DEBUG' });\n * logger.info('Hello world');\n *\n * // With scoping\n * const destLogger = logger.scope('gtag').scope('myInstance');\n * destLogger.debug('Processing event'); // DEBUG [gtag:myInstance] Processing event\n *\n * // With custom handler\n * const logger = createLogger({\n * handler: (level, message, context, scope, originalHandler) => {\n * // Custom logic (e.g., send to Sentry)\n * originalHandler(level, message, context, scope);\n * }\n * });\n * ```\n *\n * // TODO: Consider compile-time stripping of debug logs in production builds\n * // e.g., if (__DEV__) { logger.debug(...) }\n */\nexport function createLogger(config: Config = {}): Instance {\n const level =\n config.level !== undefined ? normalizeLevel(config.level) : Level.ERROR;\n const customHandler = config.handler;\n const jsonHandler = config.jsonHandler;\n const scope: string[] = [];\n\n return createLoggerInternal({\n level,\n handler: customHandler,\n jsonHandler,\n scope,\n });\n}\n\n/**\n * Internal logger creation with resolved config\n */\nfunction createLoggerInternal(config: InternalConfig): Instance {\n const { level, handler, jsonHandler, scope } = config;\n\n /**\n * Internal log function that checks level and delegates to handler\n */\n const log = (\n logLevel: Level,\n message: string | Error,\n context?: unknown | Error,\n ): void => {\n if (logLevel <= level) {\n const normalized = normalizeParams(message, context);\n\n if (handler) {\n // Custom handler with access to default handler\n handler(\n logLevel,\n normalized.message,\n normalized.context,\n scope,\n defaultHandler,\n );\n } else {\n defaultHandler(logLevel, normalized.message, normalized.context, scope);\n }\n }\n };\n\n /**\n * Throw only: the collector's catch writes the one line for the failure,\n * so logging here as well would print every failure twice.\n */\n const throwOnly = (message: string | Error, context?: unknown): never => {\n throw new Error(normalizeParams(message, context).message);\n };\n\n return {\n error: (message, context) => log(Level.ERROR, message, context),\n warn: (message, context) => log(Level.WARN, message, context),\n info: (message, context) => log(Level.INFO, message, context),\n debug: (message, context) => log(Level.DEBUG, message, context),\n throw: throwOnly,\n json: (data: unknown) => {\n if (jsonHandler) {\n jsonHandler(data);\n } else {\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(data, null, 2));\n }\n },\n scope: (name: string) =>\n createLoggerInternal({\n level,\n handler,\n jsonHandler,\n scope: [...scope, name],\n }),\n };\n}\n\n// Re-export Level enum for convenience\nexport { Level };\n","/**\n * Shared secret redactor. One set of patterns for every path that egresses a\n * log line: the CLI logger handler and the runtime logger handler (scrubbing\n * console and the error ring), and the runtime heartbeat (scrubbing the ring\n * snapshot before the POST). A pattern added here covers all of them.\n *\n * Two entry points:\n * - `scrubSecrets(line, { known })`: mask secrets (and the exact known values), keep the message length intact (for\n * console/stderr legibility).\n * - `redactLine(line)`: `scrubSecrets` plus truncation to the 256-char\n * heartbeat wire contract.\n *\n * All regex are linear (single unambiguous quantifiers, no nested quantifiers),\n * so there is no catastrophic backtracking even on a BEGIN-marker-with-no-END\n * input or a long no-space line. Exported from `@walkeros/core/node` only: no\n * browser consumer needs it, and it must not ride into web bundles.\n */\n\nconst MAX_LENGTH = 256;\n\n// Minimum length for a standalone run to be considered a candidate token.\nconst MIN_TOKEN_LEN = 20;\n\n// Shannon entropy threshold (bits/char). Random tokens score high (~4.5-6),\n// natural-language words and identifiers score low (~2-3.5).\nconst ENTROPY_THRESHOLD = 4.0;\n\n// Known secret prefixes that force-mask their run regardless of entropy/shape.\nconst FORCE_MASK_PREFIXES = [\n 'sk-',\n 'sk_',\n 'pk_',\n 'ghp_',\n 'gho_',\n 'xoxb-',\n 'xoxp-',\n 'AKIA',\n];\n\n// ── Regex constants (all linear, no nested quantifiers) ─────────────────────\n\n// URL credentials: scheme://user:password@host, keep user, mask password.\n// The user may be empty (`redis://:pw@host`). Neither part crosses a quote,\n// backslash or `/`, so a URL in serialized JSON never reaches an `@` further\n// along the line (an email in another field).\nconst RE_URL_CREDS = /(:\\/\\/[^/:@\\s\"\\\\]*:)[^@\\s/\"\\\\]+(@)/g;\n\n// JSON service-account field values, catches service-account blobs.\n// `private_key` holds the PEM body; `client_email`, `private_key_id`,\n// `client_id`, and `client_x509_cert_url` identify and pair with the leaked\n// credential and must not ship either (the cert url embeds the URL-encoded\n// client email). Naming them explicitly beats relying on the token-run\n// heuristics, which can miss an email or a URL. The value may contain escaped\n// newlines (\\n as literal backslash-n) which do not split the line. [^\"] is\n// safe: these values contain no embedded quotes. One alternation over the field\n// names keeps the scan single-pass and linear. The escaped `\\\"private_key\\\"`\n// form (a service account inside a serialized JSON string) matches too; its\n// optional backslash is captured and repeated around the mask.\nconst RE_JSON_SA_FIELD =\n /(\\\\?\"(?:private_key|client_email|private_key_id|client_id|client_x509_cert_url)\\\\?\"\\s*:\\s*)(\\\\?)\"[^\"]*\"/g;\n\n// Credential fields by name: the value is a secret whatever its shape (a\n// plain-word password or a `Basic`/`Bearer` header slips past the token\n// heuristics). Word parts may be joined by `-`, `_` or nothing (`api_key`,\n// `apiKey`, `API-Key`), and a header name may carry an `x-` prefix\n// (`X-API-Key`).\nconst SECRET_FIELD_NAMES =\n '(?:x-)?(?:password|passwd|secret|client[-_]?secret|secret[-_]?access[-_]?key|api[-_]?key|api[-_]?secret|access[-_]?token|refresh[-_]?token|auth[-_]?token|id[-_]?token|session[-_]?token|private[-_]?key|token|authorization)';\n\n// Plain `\"key\": value`: a string value runs to its closing quote (an escaped\n// char is consumed as a pair; the alternatives start on different chars, so\n// the scan is linear), a numeric value to its last digit. The mask is a\n// string, so the JSON stays valid.\nconst RE_JSON_SECRET_FIELD = new RegExp(\n `(\"(?:${SECRET_FIELD_NAMES})\"\\\\s*:\\\\s*)(?:\"(?:[^\"\\\\\\\\]|\\\\\\\\.)*\"|-?\\\\d[\\\\d.eE+-]*)`,\n 'gi',\n);\n\n// Escaped `\\\"key\\\":\\\"value\\\"`, the form a serialized request body carries\n// inside a JSON string. A string value ends at the escaped closing quote; a\n// quote or backslash inside it is escaped twice (`\\\\\\\"`, `\\\\\\\\`), so each\n// `\\\\` pair is consumed together with the escape it carries. Every\n// alternative starts on a different char pair, so the scan is linear. A\n// numeric value runs to its last digit.\nconst RE_JSON_SECRET_FIELD_ESCAPED = new RegExp(\n `(\\\\\\\\\"(?:${SECRET_FIELD_NAMES})\\\\\\\\\"\\\\s*:\\\\s*)(?:(\\\\\\\\\")(?:[^\"\\\\\\\\]|\\\\\\\\[^\"\\\\\\\\]|\\\\\\\\\\\\\\\\(?:\\\\\\\\\\\\\\\\|\\\\\\\\\"|[^\"\\\\\\\\]))*|-?\\\\d[\\\\d.eE+-]*)`,\n 'gi',\n);\n\n// A credential-named URL query parameter (`?api_secret=...`,\n// `&access_token=...`): the value runs to the next `&`, `#`, quote, backslash\n// or whitespace.\nconst RE_QUERY_SECRET = new RegExp(\n `([?&]${SECRET_FIELD_NAMES}=)[^&#\\\\s\"\\\\\\\\]+`,\n 'gi',\n);\n\n// A PEM private key inline in one line (a JSON string with escaped newlines),\n// under any field name: marker and body up to the END marker's dashes.\nconst RE_PEM_INLINE = /-----BEGIN [A-Z ]*PRIVATE KEY-----[^-]*/gi;\n\n// PEM block boundaries (structural removal, not regex masking).\n// Case-insensitive, tolerate leading whitespace so a lowercase or indented\n// `-----begin private key-----` block does not leak its body.\nconst RE_PEM_BEGIN = /^\\s*-----BEGIN [A-Z ]*PRIVATE KEY-----/i;\nconst RE_PEM_END = /-----END[A-Z -]*-----/i;\n\n// KEY=value / KEY: value secret pattern.\n// ReDoS-safe: the key is anchored to start-of-line or whitespace and bounded to\n// 64 chars ({0,63} after the first char), so there is no O(n²) backtracking on\n// long no-space lines. The value class includes - and . so hyphenated/dotted\n// tokens are captured whole. Two capture groups are preserved in the\n// replacement: the leading (^|\\s) boundary and the key=.\nconst TOKEN_VALUE_CLASS = '[A-Za-z0-9+/._-]';\nconst RE_KV_SECRET = new RegExp(\n `(^|\\\\s)([A-Za-z_][A-Za-z0-9_.]{0,63}\\\\s*[=:]\\\\s*)(${TOKEN_VALUE_CLASS}{12,}={0,2})`,\n 'g',\n);\n\n// Standalone candidate runs: any run of token chars (incl. - and .) ≥ 20.\n// The decision to mask happens in the callback (shouldMaskToken), keeping the\n// regex itself trivial and linear.\nconst RE_TOKEN_RUN = new RegExp(`${TOKEN_VALUE_CLASS}{${MIN_TOKEN_LEN},}`, 'g');\n\n// Force-mask prefix detector for runs that carry a known secret prefix.\n// Matches a known prefix followed by token chars (any length), so e.g.\n// `ghp_xxxxxxxx` or `xoxb-2384-2384-AbCdEf` is masked even under 20 chars.\n// Built from FORCE_MASK_PREFIXES so the list is the single source of truth.\n// Prefixes are regex-escaped (only `-`/`_` appear, both literal here, but escape\n// defensively) and ordered longest-first so the alternation is unambiguous.\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\nconst PREFIX_ALTERNATION = [...FORCE_MASK_PREFIXES]\n .sort((a, b) => b.length - a.length)\n .map(escapeRegex)\n .join('|');\nconst RE_PREFIXED_TOKEN = new RegExp(\n `(?:${PREFIX_ALTERNATION})${TOKEN_VALUE_CLASS}*`,\n 'g',\n);\n\n// A run right after a backslash starts with that escape's letters (`\\n`, `\\t`,\n// `\\u00e9` in serialized JSON). Masking keeps them so the text stays valid JSON.\nconst RE_ESCAPE_HEAD = /^(?:u[0-9a-fA-F]{4}|[bfnrt])/;\n\n// ── Entropy ──────────────────────────────────────────────────────────────────\n\n/** Shannon entropy in bits per character. Linear in input length. */\nfunction shannonEntropy(s: string): number {\n if (s.length === 0) return 0;\n const counts = new Map<string, number>();\n for (const ch of s) counts.set(ch, (counts.get(ch) ?? 0) + 1);\n let entropy = 0;\n for (const count of counts.values()) {\n const p = count / s.length;\n entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\n// ── Token masking decision ─────────────────────────────────────────────────\n\nconst RE_ALL_HEX = /^[0-9a-fA-F]+$/;\nconst RE_ALL_DIGIT = /^[0-9]+$/;\n// Real base64 padding/special chars. `/` is intentionally EXCLUDED: it is a\n// structural path/URL separator (FQNs, gs:// paths, request paths, googleapis\n// URLs), not a secret signal. Since redaction runs on every logger line,\n// treating `/` as a secret char nuked legitimate BigQuery/GCS diagnostics. Real\n// base64 secrets still carry `+`/`=` padding, are all-hex, or are high-entropy.\nconst RE_BASE64_SPECIAL = /[+=]/;\nconst RE_HAS_DIGIT = /[0-9]/;\nconst RE_HAS_LETTER = /[A-Za-z]/;\n// A dotted run is judged per segment; segments shorter than this (`oauth2`,\n// `com`) are never judged, longer ones only mask when secret-shaped (name\n// parts like `JSONWriter` or `googleapis` are not).\nconst MIN_DOT_SEGMENT_LEN = 8;\n\n/**\n * Decide whether a candidate run (a single token, no `/`) is a secret to mask.\n *\n * Mask when ANY of:\n * - all-hex (digests, SHA, etc.)\n * - all-digit (numeric tokens/ids)\n * - contains a base64 special char (+ =)\n * - contains both a digit and a letter (mixed token)\n * - Shannon entropy ≥ 4.0 bits/char (random all-letter / mixed-case tokens)\n */\nfunction isSecretSegment(run: string): boolean {\n if (RE_ALL_HEX.test(run)) return true;\n if (RE_ALL_DIGIT.test(run)) return true;\n if (RE_BASE64_SPECIAL.test(run)) return true;\n if (RE_HAS_DIGIT.test(run) && RE_HAS_LETTER.test(run)) return true;\n if (shannonEntropy(run) >= ENTROPY_THRESHOLD) return true;\n return false;\n}\n\n/**\n * Decide whether a ≥20-char candidate run is a secret to mask.\n *\n * A run containing `/` is treated as a path/URL structure, not one opaque token.\n * Paths and URLs split into short alphanumeric segments (`v2`, `projects`,\n * `12345`), each of which trips the digit+letter or entropy heuristic on its own\n * even though the whole thing is legible diagnostics. So a `/`-bearing run is\n * masked only when one of its long (≥20-char) segments independently looks like\n * a secret (e.g. a base64 blob embedded in a URL path). A base64 secret with `/`\n * still carries `+`/`=` (handled per-segment) or is hex/high-entropy, so real\n * secrets remain masked while FQNs, gs:// paths, request paths, and googleapis\n * URLs survive.\n *\n * A `.` splits a run (or a path segment) too, with a shorter bar: host names\n * (`oauth2.googleapis.com`) and dotted call paths (`JSONWriter.appendRows`)\n * stay legible, while a dotted run with any secret-shaped segment of 8+\n * chars (each part of a JWT, `abc123def456gh.ghi789...`) is masked. A\n * KEY=value value without `/` (`keyedValue`) is judged whole, dots included:\n * `DB_PASSWORD=Sup3rS3cret.Pass2024` masks although both parts are short.\n *\n * ACCEPTED best-effort limitation: a bare all-letters run with no digit, no\n * special char, no known prefix, and entropy < 4.0 (e.g. `supercalifragilistic`\n * or a long camelCase identifier like `getUserAccountSettings`) may pass through\n * unmasked. Masking every such run would destroy log readability by redacting\n * ordinary identifiers and words, which defeats the purpose of legible\n * diagnostics. This is a deliberate trade-off, not an oversight.\n */\n// A semantic version (optionally v-prefixed, with prerelease and build\n// metadata) is never a secret. Release snapshots such as\n// `4.7.0-next-1790408404259` are long enough to reach the token-run length\n// and would otherwise be masked in image tags and package specifiers.\nconst RE_SEMVER =\n /^v?\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n\nfunction shouldMaskToken(run: string, keyedValue = false): boolean {\n if (RE_SEMVER.test(run)) return false;\n if (run.includes('/')) {\n // Per-segment: only mask if a long segment is itself secret-shaped. Short\n // path segments (the bulk of any URL) never qualify, keeping URLs legible.\n return run\n .split('/')\n .filter((segment) => segment.length >= MIN_TOKEN_LEN)\n .some(isSecretDottedRun);\n }\n return keyedValue ? isSecretSegment(run) : isSecretDottedRun(run);\n}\n\n/** A run without `/`: secret when any 8+ char dot segment is secret-shaped. */\nfunction isSecretDottedRun(run: string): boolean {\n if (!run.includes('.')) return isSecretSegment(run);\n return run\n .split('.')\n .filter((segment) => segment.length >= MIN_DOT_SEGMENT_LEN)\n .some(isSecretSegment);\n}\n\n// ── PEM block removal ────────────────────────────────────────────────────────\n\n/**\n * Remove all PEM private-key blocks from an array of lines.\n * A block starts at a BEGIN PRIVATE KEY marker and ends at the matching END\n * marker (inclusive). If no END is found, everything to end of entry is dropped.\n */\nfunction removePemBlocks(lines: string[]): string[] {\n const out: string[] = [];\n let inBlock = false;\n\n for (const line of lines) {\n if (!inBlock) {\n if (RE_PEM_BEGIN.test(line)) {\n inBlock = true;\n continue; // start-of-block line dropped\n }\n out.push(line);\n } else {\n if (RE_PEM_END.test(line)) {\n inBlock = false;\n }\n // drop every in-block line, including the END marker\n }\n }\n\n return out;\n}\n\n// ── Per-line secret masking ──────────────────────────────────────────────────\n\n/**\n * Mask secrets in a single (non-PEM) line.\n * All patterns are applied in order; all regex are linear (no nested quantifiers).\n */\nfunction maskLine(line: string): string {\n let s = line;\n\n // 1. URL credentials: ://user:secret@host → ://user:***@host\n s = s.replace(RE_URL_CREDS, '$1***$2');\n\n // 1a. Credential-named query parameters, whatever the value's shape.\n s = s.replace(RE_QUERY_SECRET, '$1***');\n\n // 1b. A PEM private key inline (a JSON string), whatever its field name.\n s = s.replace(RE_PEM_INLINE, '***');\n\n // 2. KEY=secret / KEY: secret (anchored, bounded key, ReDoS-safe).\n // Mask the value only when it is secret-shaped. This stops `scheme://host/...`\n // (matched as `gs:` / `https:` key + `//...` value) from masking legitimate\n // URLs/paths, while real `TOKEN=secret` values still mask. The `/`-aware\n // shouldMaskToken keeps path-shaped values legible.\n s = s.replace(\n RE_KV_SECRET,\n (match: string, boundary: string, keyPart: string, value: string) =>\n shouldMaskToken(value, true) ? `${boundary}${keyPart}***` : match,\n );\n\n // 3. Known-prefix tokens (force-mask regardless of length/entropy)\n s = s.replace(RE_PREFIXED_TOKEN, '***');\n\n // 4. Standalone candidate runs ≥ 20 chars, mask by shape/entropy\n s = s.replace(\n RE_TOKEN_RUN,\n (match: string, offset: number, input: string) => {\n if (!shouldMaskToken(match)) return match;\n const head =\n offset > 0 && input[offset - 1] === '\\\\'\n ? RE_ESCAPE_HEAD.exec(match)?.[0]\n : undefined;\n return head ? `${head}***` : '***';\n },\n );\n\n return s;\n}\n\n// ── Known secret values ──────────────────────────────────────────────────────\n\n// Shorter values are too likely to occur in ordinary text to mask on sight.\nexport const MIN_KNOWN_LEN = 6;\n\nexport interface ScrubOptions {\n /**\n * Exact secret values to mask wherever they occur (e.g. the resolved\n * `$secret.NAME` values of a flow). Values under 6 characters are ignored.\n */\n known?: readonly string[];\n}\n\n/**\n * Mask every exact occurrence of each known value, raw, JSON-escaped (the\n * form it takes inside serialized JSON), escaped twice (a JSON string\n * serialized again, e.g. a request body inside JSON output) and URL-encoded\n * (a URL, or a form body where a space is `+`), longest first so\n * a value containing another is masked whole. Literal split/join, never a regex built from the\n * value.\n */\nexport function maskKnownValues(\n line: string,\n known?: readonly string[],\n): string {\n if (!known || known.length === 0) return line;\n const forms = new Set<string>();\n for (const value of known) {\n if (value.length < MIN_KNOWN_LEN) continue;\n const escaped = JSON.stringify(value).slice(1, -1);\n forms.add(value);\n forms.add(escaped);\n forms.add(JSON.stringify(escaped).slice(1, -1));\n // In a URL or a form body: `encodeURIComponent` (also with a space as\n // `+`), `encodeURI` (keeps `/ : + =`) and `URLSearchParams` (also\n // encodes `! ' ( ) ~`, a space as `+`).\n const component = uriEncoded(encodeURIComponent, value);\n if (component) {\n forms.add(component);\n forms.add(component.replace(/%20/g, '+'));\n }\n const uri = uriEncoded(encodeURI, value);\n if (uri) forms.add(uri);\n forms.add(new URLSearchParams({ v: value }).toString().slice(2));\n }\n let s = line;\n for (const form of [...forms].sort((a, b) => b.length - a.length)) {\n if (s.includes(form)) s = replaceKnown(s, form);\n }\n return s;\n}\n\n/** `encode(value)`, or undefined for a value it cannot encode (a lone surrogate). */\nfunction uriEncoded(\n encode: (value: string) => string,\n value: string,\n): string | undefined {\n try {\n return encode(value);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Replace every occurrence of `form` with `***`. An occurrence right after an\n * escaping backslash (an odd run of them) keeps the escape's letters, as\n * `maskLine` does, so serialized JSON stays valid.\n */\nfunction replaceKnown(line: string, form: string): string {\n let out = '';\n let from = 0;\n let at = line.indexOf(form);\n while (at !== -1) {\n // Count the backslashes just before the match; text before `from` was\n // an earlier match, now `***`, so the run stops there.\n let slashes = 0;\n while (at - slashes > from && line[at - slashes - 1] === '\\\\') slashes++;\n const head =\n slashes % 2 === 1 ? (RE_ESCAPE_HEAD.exec(form)?.[0] ?? form[0]) : '';\n out += `${line.slice(from, at)}${head}***`;\n from = at + form.length;\n at = line.indexOf(form, from);\n }\n return out + line.slice(from);\n}\n\n// ── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Scrub credential material from a log line (or multi-line entry) WITHOUT\n * truncating. This is the shared secret redactor used by the CLI and runtime\n * logger handlers (covers their console/stderr lines and the ring before\n * egress). Output a dependency writes straight to `console` or stderr never\n * passes through it.\n *\n * Algorithm:\n * 0. Mask each `options.known` value exactly, raw, JSON-escaped and escaped\n * twice, longest first.\n * 1. Mask JSON service-account fields (private_key, client_email,\n * private_key_id, client_id, client_x509_cert_url) and credential-named\n * JSON fields (password, token, authorization, ...) BEFORE splitting\n * (service-account blobs embed PEM blocks as \\\\n-encoded strings; masking\n * first prevents the BEGIN marker from appearing on its own line and dropping\n * surrounding fields).\n * 2. Split on \\\\n.\n * 3. Remove PEM private-key blocks structurally (BEGIN…END inclusive,\n * case-insensitive; a no-END block drops to end of entry).\n * 4. For each surviving line: mask URL creds, inline PEM keys, KEY=secret,\n * prefixed tokens,\n * high-entropy/shape-based token runs.\n * 5. Rejoin with \\\\n.\n */\nexport function scrubSecrets(line: string, options: ScrubOptions = {}): string {\n // Step 0: known secret values, exact, before any pattern can split them\n const withoutKnown = maskKnownValues(line, options.known);\n\n // Step 1: JSON service-account field masking before any line splitting\n const withoutJsonKey = withoutKnown\n .replace(RE_JSON_SA_FIELD, '$1$2\"***$2\"')\n .replace(\n RE_JSON_SECRET_FIELD_ESCAPED,\n (_match: string, keyPart: string, quote: string | undefined) =>\n quote ? `${keyPart}${quote}***` : `${keyPart}\\\\\"***\\\\\"`,\n )\n .replace(RE_JSON_SECRET_FIELD, '$1\"***\"');\n\n // Step 2: split\n const rawLines = withoutJsonKey.split('\\n');\n\n // Step 3: remove PEM blocks (any remaining standalone markers after step 1)\n const cleanLines = removePemBlocks(rawLines);\n\n // Step 4: mask each surviving line\n const maskedLines = cleanLines.map(maskLine);\n\n // Step 5: rejoin\n return maskedLines.join('\\n');\n}\n\n/**\n * Redact a log line and truncate to the heartbeat wire contract (256 chars).\n * This is the heartbeat-egress variant: scrub secrets, then truncate AFTER\n * masking so a token straddling char 256 is masked, not left partially visible.\n *\n * The app's heartbeat schema enforces message .max(256); a 257-char string\n * would fail zod .parse and drop the whole heartbeat. Reserve one char for the\n * ellipsis so the TOTAL length is at most MAX_LENGTH (256).\n */\nexport function redactLine(line: string): string {\n const scrubbed = scrubSecrets(line);\n\n if (scrubbed.length > MAX_LENGTH) {\n return scrubbed.slice(0, MAX_LENGTH - 1) + '…';\n }\n\n return scrubbed;\n}\n","import { TextDecoder } from 'util';\n\n/**\n * Turn a recorded simulate value (call arguments, events, errors) into plain\n * JSON-safe data. One formatter for the CLI `push` output (`--json` and text)\n * and the MCP `flow_simulate` result, so a value a vendor call really\n * receives prints readably and never throws:\n *\n * - `Error` → `{ name, message }`\n * - `Buffer`, any typed array, `DataView`, `ArrayBuffer` → utf8 string of its\n * bytes, or `base64:<...>` when not valid utf8\n * - `bigint` → string\n * - `Map` → array of `[key, value]` entries, `Set` → array of values\n * - a cycle → `\"[Circular]\"`\n * - a function → `\"[Function <name>]\"`\n * - a class instance (an SDK command, say) → `{ <ClassName>: <own fields> }`,\n * named by its `Symbol.toStringTag` when it has one\n * - a value whose getter, `toJSON` or proxy trap throws → `\"[Unprintable]\"`\n *\n * Secrets are not this function's concern: the printed text egresses through\n * `scrubSecrets`.\n */\nexport function toPrintable(value: unknown): unknown {\n return walk(value, new Set());\n}\n\nconst utf8 = new TextDecoder('utf-8', { fatal: true });\n\nfunction bytesToString(bytes: Uint8Array): string {\n try {\n return utf8.decode(bytes);\n } catch {\n return `base64:${Buffer.from(bytes).toString('base64')}`;\n }\n}\n\n// Values can come from another realm (a web flow simulates inside jsdom), where\n// `instanceof` against this realm's constructors fails. The built-in tag does\n// not depend on the realm.\nfunction tagOf(value: object): string {\n return Object.prototype.toString.call(value);\n}\n\nfunction isError(value: object): value is Error {\n return tagOf(value) === '[object Error]';\n}\n\nfunction isArrayBuffer(value: object): value is ArrayBuffer {\n return tagOf(value) === '[object ArrayBuffer]';\n}\n\n/** The raw bytes of a typed array, `DataView` or `ArrayBuffer`. */\nfunction bytesOf(value: object): Uint8Array | undefined {\n if (ArrayBuffer.isView(value))\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n if (isArrayBuffer(value)) return new Uint8Array(value);\n return undefined;\n}\n\nfunction isMap(value: object): value is Map<unknown, unknown> {\n return tagOf(value) === '[object Map]';\n}\n\nfunction isSet(value: object): value is Set<unknown> {\n return tagOf(value) === '[object Set]';\n}\n\nfunction hasToJSON(value: object): value is { toJSON: () => unknown } {\n return 'toJSON' in value && typeof value.toJSON === 'function';\n}\n\n/**\n * Name of a class instance; undefined for plain objects. A custom\n * `Symbol.toStringTag` wins over the constructor name, which a minifier may\n * have renamed.\n */\nfunction className(value: object): string | undefined {\n const tag = tagOf(value).slice('[object '.length, -1);\n if (tag !== 'Object') return tag;\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto === null || proto === Object.prototype) return undefined;\n if (typeof proto !== 'object') return undefined;\n const ctor: unknown = Reflect.get(proto, 'constructor');\n // By name, not identity: a plain object from another realm has that\n // realm's `Object` as its constructor.\n if (typeof ctor !== 'function' || ctor.name === 'Object') return undefined;\n return ctor.name || undefined;\n}\n\nfunction walk(value: unknown, ancestors: Set<object>): unknown {\n if (typeof value === 'bigint') return value.toString();\n if (typeof value === 'function')\n return `[Function ${value.name || 'anonymous'}]`;\n if (typeof value === 'symbol') return value.toString();\n if (value === null || typeof value !== 'object') return value;\n\n // A throwing getter, `toJSON` or proxy trap must not break the output.\n try {\n return walkObject(value, ancestors);\n } catch {\n return '[Unprintable]';\n }\n}\n\nfunction walkObject(value: object, ancestors: Set<object>): unknown {\n if (isError(value)) return { name: value.name, message: value.message };\n const bytes = bytesOf(value);\n if (bytes) return bytesToString(bytes);\n if (ancestors.has(value)) return '[Circular]';\n\n ancestors.add(value);\n try {\n if (isMap(value))\n return Array.from(value.entries(), ([k, v]) => [\n walk(k, ancestors),\n walk(v, ancestors),\n ]);\n if (isSet(value))\n return Array.from(value.values(), (v) => walk(v, ancestors));\n if (Array.isArray(value)) return value.map((v) => walk(v, ancestors));\n if (hasToJSON(value)) return walk(value.toJSON(), ancestors);\n\n const fields: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(value)) {\n fields[key] = walk(field, ancestors);\n }\n const name = className(value);\n return name ? { [name]: fields } : fields;\n } finally {\n ancestors.delete(value);\n }\n}\n","import { MIN_KNOWN_LEN, scrubSecrets, type ScrubOptions } from '../redactLine';\nimport { toPrintable } from './toPrintable';\n\n/**\n * A deep copy of `value` in which every number whose printed form contains a\n * known secret (6+ characters, e.g. `12345678`, `-1234567`, `1234567.5`)\n * becomes `'***'`. Masking such a number inside serialized JSON would leave an\n * unquoted `***` and break the JSON, so it runs on the value before\n * `JSON.stringify`. Exported for its unit test; egress goes through\n * `scrubJson`, which owns the order.\n */\nexport function maskKnownNumbers(\n value: unknown,\n known: readonly string[],\n): unknown {\n const candidates = known.filter((secret) => secret.length >= MIN_KNOWN_LEN);\n const mask = (item: unknown): unknown => {\n if (typeof item === 'number') {\n const printed = String(item);\n return candidates.some((secret) => printed.includes(secret))\n ? '***'\n : item;\n }\n if (Array.isArray(item)) return item.map(mask);\n if (item && typeof item === 'object') {\n const copy: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(item)) copy[key] = mask(entry);\n return copy;\n }\n return item;\n };\n return mask(value);\n}\n\n/**\n * Serialize a value for egress with secrets masked: its printable form (see\n * `toPrintable`), numbers that print a known value become `'***'`,\n * `JSON.stringify`, then `scrubSecrets` with the same known values. The order\n * keeps the result valid JSON. A value with no JSON form prints `undefined`.\n */\nexport function scrubJson(\n value: unknown,\n options: ScrubOptions & { space?: number } = {},\n): string {\n const known = options.known ?? [];\n const text =\n JSON.stringify(\n maskKnownNumbers(toPrintable(value), known),\n null,\n options.space,\n ) ?? 'undefined';\n return scrubSecrets(text, { known });\n}\n","/**\n * Sets `cause` the way the ES2022 `ErrorOptions` argument does (an own,\n * non-enumerable property), so a cause survives in a browser that drops that\n * argument.\n */\nexport function setCause(error: Error, cause: unknown): void {\n Object.defineProperty(error, 'cause', {\n value: cause,\n writable: true,\n configurable: true,\n });\n}\n","import type { StoreValue } from '../types/store';\n\n/**\n * The neutral half of the store codec: the guard a cache uses to narrow a\n * wide value to `StoreValue`. The byte codec itself reads `Buffer`, so it\n * lives in the node entry (`@walkeros/core/node`, `../node/storeCodec`).\n */\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Recursive type guard: the restored value is structurally a `StoreValue`.\n * The single restore walk (`fromSerializableWith`) is JSON-derived plus\n * `Uint8Array` binary leaves, so this always holds; the guard makes the\n * narrowing explicit and cast-free at the public boundary.\n *\n * The guard accepts exactly what the serializer can encode. An `undefined`\n * object property is dropped and an `undefined` array element becomes `null`\n * on `JSON.stringify`, so an `undefined` nested value does NOT disqualify the\n * containing value (matching the serializer's runtime tolerance at the\n * `unknown -> StoreValue` boundary). The `StoreValue` TYPE still excludes\n * `undefined`; this only mirrors what survives serialization.\n */\nexport function isStoreValue(value: unknown): value is StoreValue {\n if (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value instanceof Uint8Array\n )\n return true;\n if (Array.isArray(value))\n return value.every((v) => v === undefined || isStoreValue(v));\n if (isRecord(value))\n return Object.values(value).every(\n (v) => v === undefined || isStoreValue(v),\n );\n return false;\n}\n","import type { StoreValue } from '../types/store';\nimport { setCause } from '../errorCause';\nimport { isRecord, isStoreValue } from '../store/codec';\n\n/**\n * Shared structured codec for store values.\n *\n * Stateless, format-only: serializes a `StoreValue` to a UTF-8 JSON byte\n * payload and restores it, with no store-type branches. Binary leaves are\n * tagged base64 behind a reserved marker; user objects that happen to carry\n * the marker are escaped, so NO payload can be corrupted. On the store path\n * binary always decodes back to a platform-neutral `Uint8Array`, never a Node\n * `Buffer`.\n */\n\nconst CACHE_MARKER = '__walkeros_cache__';\n\n/**\n * Thrown when a value cannot be serialized (e.g. a cyclic structure that\n * `JSON.stringify` rejects). Catchable and distinguishable from a raw\n * `TypeError` leaking out of the platform JSON implementation.\n */\nexport class StoreCodecError extends Error {\n declare cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = 'StoreCodecError';\n if (options && 'cause' in options) setCause(this, options.cause);\n }\n}\n\n// Precondition: the input is acyclic JSON-shaped data; binary leaves are the\n// only non-JSON values handled. A Node `Buffer`, any `Uint8Array` (e.g. a\n// Fetch-sourced body), and a raw `ArrayBuffer` all normalize to the same\n// base64 'buffer' tag and decode back through the caller-supplied binary\n// factory (see fromSerializableWith). A `Buffer` IS a `Uint8Array`, but under\n// split realms (jsdom test env) a Node `Buffer` fails the `instanceof\n// Uint8Array` check against the realm's `Uint8Array`, so the realm-independent\n// `Buffer.isBuffer` check stays FIRST. The `Uint8Array` branch then handles\n// typed-array views by slicing on byteOffset/byteLength so a subarray view\n// contributes only its own bytes.\nfunction toSerializable(value: unknown): unknown {\n if (Buffer.isBuffer(value))\n return { [CACHE_MARKER]: 'buffer', d: value.toString('base64') };\n if (value instanceof Uint8Array)\n return {\n [CACHE_MARKER]: 'buffer',\n d: Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString(\n 'base64',\n ),\n };\n if (value instanceof ArrayBuffer)\n return {\n [CACHE_MARKER]: 'buffer',\n d: Buffer.from(value).toString('base64'),\n };\n if (Array.isArray(value)) return value.map(toSerializable);\n if (isRecord(value)) {\n if (CACHE_MARKER in value) {\n const inner: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) inner[k] = toSerializable(v);\n return { [CACHE_MARKER]: 'escape', d: inner };\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) out[k] = toSerializable(v);\n return out;\n }\n return value;\n}\n\n/**\n * Single traversal that restores the serialized form. The binary-leaf type is\n * supplied by the caller via `toBinary`; the store path constructs a plain\n * `Uint8Array`. Parametrizing the leaf factory keeps one implementation of the\n * walk while leaving the binary representation to the caller.\n */\nfunction fromSerializableWith(\n value: unknown,\n toBinary: (buf: Buffer) => Uint8Array,\n): unknown {\n if (isRecord(value)) {\n if (CACHE_MARKER in value) {\n const tag = value[CACHE_MARKER];\n const data = value.d;\n if (tag === 'buffer' && typeof data === 'string')\n return toBinary(Buffer.from(data, 'base64'));\n if (tag === 'escape' && isRecord(data)) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(data))\n out[k] = fromSerializableWith(v, toBinary);\n return out;\n }\n // Unrecognized tag (not 'buffer'/'escape'): fall through to default\n // object traversal so a user object that merely carries the marker key,\n // or a value from a future tag version, is preserved verbatim rather\n // than coerced.\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value))\n out[k] = fromSerializableWith(v, toBinary);\n return out;\n }\n if (Array.isArray(value))\n return value.map((v) => fromSerializableWith(v, toBinary));\n return value;\n}\n\n// Store path: binary leaves become a plain, platform-neutral Uint8Array (a\n// standalone view over the exact decoded bytes), never a Node Buffer.\nfunction toStoreBinary(buf: Buffer): Uint8Array {\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n}\n\n/**\n * Serialize a `StoreValue` to its UTF-8 JSON byte payload. Throws\n * `StoreCodecError` if the value cannot be encoded (e.g. a cyclic structure).\n */\nexport function serializeStoreValue(value: StoreValue): Uint8Array {\n let json: string;\n try {\n json = JSON.stringify(toSerializable(value));\n } catch (cause) {\n throw new StoreCodecError(\n 'Failed to serialize store value (likely a cyclic structure).',\n { cause },\n );\n }\n return new Uint8Array(Buffer.from(json, 'utf8'));\n}\n\n/**\n * Restore a `StoreValue` from its UTF-8 JSON byte payload (or a JSON string).\n */\nexport function deserializeStoreValue(raw: Uint8Array | string): StoreValue {\n const text =\n typeof raw === 'string' ? raw : Buffer.from(raw).toString('utf8');\n const restored = fromSerializableWith(JSON.parse(text), toStoreBinary);\n if (!isStoreValue(restored))\n throw new StoreCodecError('Restored value is not a valid StoreValue.');\n return restored;\n}\n"],"mappings":"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","names":["Level","out","os","path","isRecord","message"]}
|
package/dist/node.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"os";import n from"path";var t=(e=>(e[e.ERROR=0]="ERROR",e[e.WARN=1]="WARN",e[e.INFO=2]="INFO",e[e.DEBUG=3]="DEBUG",e))(t||{});function r(e){return{message:e.message,name:e.name,stack:e.stack,cause:e.cause}}function o(e,n){let t,o={};return e instanceof Error?(t=e.message,o.error=r(e)):t=e,void 0!==n&&(n instanceof Error?o.error=r(n):"object"==typeof n&&null!==n?(o={...o,...n},"error"in o&&o.error instanceof Error&&(o.error=r(o.error))):o.value=n),{message:t,context:o}}var s=(e,n,r,o)=>{const s=`${t[e]}${o.length>0?` [${o.join(":")}]`:""}`,i=Object.keys(r).length>0,c=0===e?console.error:1===e?console.warn:console.log;i?c(s,n,r):c(s,n)};function i(e={}){return c({level:void 0!==e.level?function(e){return"string"==typeof e?t[e]:e}(e.level):0,handler:e.handler,jsonHandler:e.jsonHandler,scope:[]})}function c(e){const{level:n,handler:t,jsonHandler:r,scope:i}=e,u=(e,r,c)=>{if(e<=n){const n=o(r,c);t?t(e,n.message,n.context,i,s):s(e,n.message,n.context,i)}};return{error:(e,n)=>u(0,e,n),warn:(e,n)=>u(1,e,n),info:(e,n)=>u(2,e,n),debug:(e,n)=>u(3,e,n),throw:(e,n)=>{const r=o(e,n);throw t?t(0,r.message,r.context,i,s):s(0,r.message,r.context,i),new Error(r.message)},json:e=>{r?r(e):console.log(JSON.stringify(e,null,2))},scope:e=>c({level:n,handler:t,jsonHandler:r,scope:[...i,e]})}}var u=/(:\/\/[^/:@\s"\\]*:)[^@\s/"\\]+(@)/g,f=/(\\?"(?:private_key|client_email|private_key_id|client_id|client_x509_cert_url)\\?"\s*:\s*)(\\?)"[^"]*"/g,l="(?:x-)?(?:password|passwd|secret|client[-_]?secret|secret[-_]?access[-_]?key|api[-_]?key|api[-_]?secret|access[-_]?token|refresh[-_]?token|auth[-_]?token|id[-_]?token|session[-_]?token|private[-_]?key|token|authorization)",a=new RegExp(`("(?:${l})"\\s*:\\s*)(?:"(?:[^"\\\\]|\\\\.)*"|-?\\d[\\d.eE+-]*)`,"gi"),g=new RegExp(`(\\\\"(?:${l})\\\\"\\s*:\\s*)(?:(\\\\")(?:[^"\\\\]|\\\\[^"\\\\]|\\\\\\\\(?:\\\\\\\\|\\\\"|[^"\\\\]))*|-?\\d[\\d.eE+-]*)`,"gi"),p=new RegExp(`([?&]${l}=)[^&#\\s"\\\\]+`,"gi"),d=/-----BEGIN [A-Z ]*PRIVATE KEY-----[^-]*/gi,y=/^\s*-----BEGIN [A-Z ]*PRIVATE KEY-----/i,h=/-----END[A-Z -]*-----/i,m="[A-Za-z0-9+/._-]",$=new RegExp(`(^|\\s)([A-Za-z_][A-Za-z0-9_.]{0,63}\\s*[=:]\\s*)(${m}{12,}={0,2})`,"g"),b=new RegExp(`${m}{20,}`,"g");var v=["sk-","sk_","pk_","ghp_","gho_","xoxb-","xoxp-","AKIA"].sort((e,n)=>n.length-e.length).map(function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("|"),A=new RegExp(`(?:${v})${m}*`,"g"),j=/^(?:u[0-9a-fA-F]{4}|[bfnrt])/;var w=/^[0-9a-fA-F]+$/,O=/^[0-9]+$/,_=/[+=]/,E=/[0-9]/,x=/[A-Za-z]/;function k(e){return!!w.test(e)||(!!O.test(e)||(!!_.test(e)||(!(!E.test(e)||!x.test(e))||function(e){if(0===e.length)return 0;const n=new Map;for(const t of e)n.set(t,(n.get(t)??0)+1);let t=0;for(const r of n.values()){const n=r/e.length;t-=n*Math.log2(n)}return t}(e)>=4)))}var R=/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;function S(e,n=!1){return!R.test(e)&&(e.includes("/")?e.split("/").filter(e=>e.length>=20).some(N):n?k(e):N(e))}function N(e){return e.includes(".")?e.split(".").filter(e=>e.length>=8).some(k):k(e)}function Z(e){let n=e;return n=n.replace(u,"$1***$2"),n=n.replace(p,"$1***"),n=n.replace(d,"***"),n=n.replace($,(e,n,t,r)=>S(r,!0)?`${n}${t}***`:e),n=n.replace(A,"***"),n=n.replace(b,(e,n,t)=>{if(!S(e))return e;const r=n>0&&"\\"===t[n-1]?j.exec(e)?.[0]:void 0;return r?`${r}***`:"***"}),n}function z(e,n){if(!n||0===n.length)return e;const t=new Set;for(const e of n){if(e.length<6)continue;const n=JSON.stringify(e).slice(1,-1);t.add(e),t.add(n),t.add(JSON.stringify(n).slice(1,-1));const r=I(encodeURIComponent,e);r&&(t.add(r),t.add(r.replace(/%20/g,"+")));const o=I(encodeURI,e);o&&t.add(o),t.add(new URLSearchParams({v:e}).toString().slice(2))}let r=e;for(const e of[...t].sort((e,n)=>n.length-e.length))r.includes(e)&&(r=J(r,e));return r}function I(e,n){try{return e(n)}catch{return}}function J(e,n){let t="",r=0,o=e.indexOf(n);for(;-1!==o;){let s=0;for(;o-s>r&&"\\"===e[o-s-1];)s++;const i=s%2==1?j.exec(n)?.[0]??n[0]:"";t+=`${e.slice(r,o)}${i}***`,r=o+n.length,o=e.indexOf(n,r)}return t+e.slice(r)}function U(e,n={}){const t=function(e){const n=[];let t=!1;for(const r of e)if(t)h.test(r)&&(t=!1);else{if(y.test(r)){t=!0;continue}n.push(r)}return n}(z(e,n.known).replace(f,'$1$2"***$2"').replace(g,(e,n,t)=>t?`${n}${t}***`:`${n}\\"***\\"`).replace(a,'$1"***"').split("\n"));return t.map(Z).join("\n")}function B(e){const n=U(e);return n.length>256?n.slice(0,255)+"…":n}import{TextDecoder as F}from"util";function H(e){return M(e,new Set)}var P=new F("utf-8",{fatal:!0});function D(e){return Object.prototype.toString.call(e)}function G(e){return ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):function(e){return"[object ArrayBuffer]"===D(e)}(e)?new Uint8Array(e):void 0}function M(e,n){if("bigint"==typeof e)return e.toString();if("function"==typeof e)return`[Function ${e.name||"anonymous"}]`;if("symbol"==typeof e)return e.toString();if(null===e||"object"!=typeof e)return e;try{return function(e,n){if(function(e){return"[object Error]"===D(e)}(e))return{name:e.name,message:e.message};const t=G(e);if(t)return function(e){try{return P.decode(e)}catch{return`base64:${Buffer.from(e).toString("base64")}`}}(t);if(n.has(e))return"[Circular]";n.add(e);try{if(function(e){return"[object Map]"===D(e)}(e))return Array.from(e.entries(),([e,t])=>[M(e,n),M(t,n)]);if(function(e){return"[object Set]"===D(e)}(e))return Array.from(e.values(),e=>M(e,n));if(Array.isArray(e))return e.map(e=>M(e,n));if(function(e){return"toJSON"in e&&"function"==typeof e.toJSON}(e))return M(e.toJSON(),n);const t={};for(const[r,o]of Object.entries(e))t[r]=M(o,n);const r=function(e){const n=D(e).slice(8,-1);if("Object"!==n)return n;const t=Object.getPrototypeOf(e);if(null===t||t===Object.prototype)return;if("object"!=typeof t)return;const r=Reflect.get(t,"constructor");return"function"==typeof r&&"Object"!==r.name&&r.name||void 0}(e);return r?{[r]:t}:t}finally{n.delete(e)}}(e,n)}catch{return"[Unprintable]"}}function K(e,n={}){const t=n.known??[],r=JSON.stringify(function(e,n){const t=n.filter(e=>e.length>=6),r=e=>{if("number"==typeof e){const n=String(e);return t.some(e=>n.includes(e))?"***":e}if(Array.isArray(e))return e.map(r);if(e&&"object"==typeof e){const n={};for(const[t,o]of Object.entries(e))n[t]=r(o);return n}return e};return r(e)}(H(e),t),null,n.space)??"undefined";return U(r,{known:t})}var L=e.tmpdir();function T(e,...t){const r=e||L,o=n.isAbsolute(r)?r:n.resolve(r);return n.join(o,...t)}function V(e){const t=e||L,r=n.isAbsolute(t)?t:n.resolve(t);return(...e)=>n.join(r,...e)}function W(){return L}var C=e=>e;function Y(t={},r={}){const{verbose:o=!1,silent:s=!1,json:i=!1,stderr:c=!1,knownSecrets:u}=t,f="function"==typeof u?void 0:u?[...u]:void 0,l=e.tmpdir(),a=c?console.error:console.log,g=r.error??C,p=r.warn??C,d=r.info??C,y=r.debug??C;return{level:3,handler:(e,r,c,h)=>{const m=h.length>0?`[${h.join(":")}] `:"";let $="";if(Object.keys(c).length>0)try{$=` ${JSON.stringify(c)}`}catch{$=" [unserializable context]"}const b=U(function(e,t){if(!t||t===n.sep)return e;const r=t.endsWith(n.sep)?t:t+n.sep,o=e.split(r);if(1===o.length)return e;let s=o[0];for(let e=1;e<o.length;e++){const t=s.length>0?s[s.length-1]:"";s+=(""!==t&&/[\w./\\~-]/.test(t)?r:"$TMPDIR"+n.sep)+o[e]}return s}(z(`${m}${r}${$}`,"function"==typeof u?u():f),l));try{t.onLine?.(e,b)}catch{}if(0!==e){if(!s&&!i)if(3!==e)a(1===e?p(b):d(b));else{if(!o)return;a(` ${y(b)}`)}}else i||console.error(g(b))},jsonHandler:e=>{s||a(JSON.stringify(e,null,2))}}}function q(e={},n={}){return i(Y(e,n))}export{q as createCLILogger,Y as createCLILoggerConfig,V as createTmpResolver,W as getDefaultTmpRoot,T as getTmpPath,B as redactLine,K as scrubJson,U as scrubSecrets,H as toPrintable};//# sourceMappingURL=node.mjs.map
|
|
1
|
+
import e from"os";import t from"path";var n=(e=>(e[e.ERROR=0]="ERROR",e[e.WARN=1]="WARN",e[e.INFO=2]="INFO",e[e.DEBUG=3]="DEBUG",e))(n||{});function r(e){const t={message:e.message,name:e.name,stack:e.stack},n="cause"in e?function(e){if("object"!=typeof e||null===e)return;const t={};return"name"in e&&"string"==typeof e.name&&(t.name=e.name),!("code"in e)||"string"!=typeof e.code&&"number"!=typeof e.code||(t.code=e.code),t}(e.cause):void 0;return n&&(t.cause=n),t}function o(e,t){let n,o={};return e instanceof Error?(n=e.message,o.error=r(e)):n=e,void 0!==t&&(t instanceof Error?o.error=r(t):"object"==typeof t&&null!==t?(o={...o,...t},"error"in o&&o.error instanceof Error&&(o.error=r(o.error))):o.value=t),{message:n,context:o}}var i=(e,t,r,o)=>{const i=`${n[e]}${o.length>0?` [${o.join(":")}]`:""}`,s=Object.keys(r).length>0,c=0===e?console.error:1===e?console.warn:console.log;s?c(i,t,r):c(i,t)};function s(e={}){return c({level:void 0!==e.level?function(e){return"string"==typeof e?n[e]:e}(e.level):0,handler:e.handler,jsonHandler:e.jsonHandler,scope:[]})}function c(e){const{level:t,handler:n,jsonHandler:r,scope:s}=e,f=(e,r,c)=>{if(e<=t){const t=o(r,c);n?n(e,t.message,t.context,s,i):i(e,t.message,t.context,s)}};return{error:(e,t)=>f(0,e,t),warn:(e,t)=>f(1,e,t),info:(e,t)=>f(2,e,t),debug:(e,t)=>f(3,e,t),throw:(e,t)=>{throw new Error(o(e,t).message)},json:e=>{r?r(e):console.log(JSON.stringify(e,null,2))},scope:e=>c({level:t,handler:n,jsonHandler:r,scope:[...s,e]})}}var f=/(:\/\/[^/:@\s"\\]*:)[^@\s/"\\]+(@)/g,u=/(\\?"(?:private_key|client_email|private_key_id|client_id|client_x509_cert_url)\\?"\s*:\s*)(\\?)"[^"]*"/g,a="(?:x-)?(?:password|passwd|secret|client[-_]?secret|secret[-_]?access[-_]?key|api[-_]?key|api[-_]?secret|access[-_]?token|refresh[-_]?token|auth[-_]?token|id[-_]?token|session[-_]?token|private[-_]?key|token|authorization)",l=new RegExp(`("(?:${a})"\\s*:\\s*)(?:"(?:[^"\\\\]|\\\\.)*"|-?\\d[\\d.eE+-]*)`,"gi"),g=new RegExp(`(\\\\"(?:${a})\\\\"\\s*:\\s*)(?:(\\\\")(?:[^"\\\\]|\\\\[^"\\\\]|\\\\\\\\(?:\\\\\\\\|\\\\"|[^"\\\\]))*|-?\\d[\\d.eE+-]*)`,"gi"),y=new RegExp(`([?&]${a}=)[^&#\\s"\\\\]+`,"gi"),p=/-----BEGIN [A-Z ]*PRIVATE KEY-----[^-]*/gi,d=/^\s*-----BEGIN [A-Z ]*PRIVATE KEY-----/i,b=/-----END[A-Z -]*-----/i,h="[A-Za-z0-9+/._-]",m=new RegExp(`(^|\\s)([A-Za-z_][A-Za-z0-9_.]{0,63}\\s*[=:]\\s*)(${h}{12,}={0,2})`,"g"),v=new RegExp(`${h}{20,}`,"g");var A=["sk-","sk_","pk_","ghp_","gho_","xoxb-","xoxp-","AKIA"].sort((e,t)=>t.length-e.length).map(function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("|"),O=new RegExp(`(?:${A})${h}*`,"g"),j=/^(?:u[0-9a-fA-F]{4}|[bfnrt])/;var $=/^[0-9a-fA-F]+$/,w=/^[0-9]+$/,S=/[+=]/,_=/[0-9]/,x=/[A-Za-z]/;function E(e){return!!$.test(e)||(!!w.test(e)||(!!S.test(e)||(!(!_.test(e)||!x.test(e))||function(e){if(0===e.length)return 0;const t=new Map;for(const n of e)t.set(n,(t.get(n)??0)+1);let n=0;for(const r of t.values()){const t=r/e.length;n-=t*Math.log2(t)}return n}(e)>=4)))}var N=/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;function R(e,t=!1){return!N.test(e)&&(e.includes("/")?e.split("/").filter(e=>e.length>=20).some(k):t?E(e):k(e))}function k(e){return e.includes(".")?e.split(".").filter(e=>e.length>=8).some(E):E(e)}function B(e){let t=e;return t=t.replace(f,"$1***$2"),t=t.replace(y,"$1***"),t=t.replace(p,"***"),t=t.replace(m,(e,t,n,r)=>R(r,!0)?`${t}${n}***`:e),t=t.replace(O,"***"),t=t.replace(v,(e,t,n)=>{if(!R(e))return e;const r=t>0&&"\\"===n[t-1]?j.exec(e)?.[0]:void 0;return r?`${r}***`:"***"}),t}function J(e,t){if(!t||0===t.length)return e;const n=new Set;for(const e of t){if(e.length<6)continue;const t=JSON.stringify(e).slice(1,-1);n.add(e),n.add(t),n.add(JSON.stringify(t).slice(1,-1));const r=z(encodeURIComponent,e);r&&(n.add(r),n.add(r.replace(/%20/g,"+")));const o=z(encodeURI,e);o&&n.add(o),n.add(new URLSearchParams({v:e}).toString().slice(2))}let r=e;for(const e of[...n].sort((e,t)=>t.length-e.length))r.includes(e)&&(r=I(r,e));return r}function z(e,t){try{return e(t)}catch{return}}function I(e,t){let n="",r=0,o=e.indexOf(t);for(;-1!==o;){let i=0;for(;o-i>r&&"\\"===e[o-i-1];)i++;const s=i%2==1?j.exec(t)?.[0]??t[0]:"";n+=`${e.slice(r,o)}${s}***`,r=o+t.length,o=e.indexOf(t,r)}return n+e.slice(r)}function U(e,t={}){const n=function(e){const t=[];let n=!1;for(const r of e)if(n)b.test(r)&&(n=!1);else{if(d.test(r)){n=!0;continue}t.push(r)}return t}(J(e,t.known).replace(u,'$1$2"***$2"').replace(g,(e,t,n)=>n?`${t}${n}***`:`${t}\\"***\\"`).replace(l,'$1"***"').split("\n"));return n.map(B).join("\n")}function L(e){const t=U(e);return t.length>256?t.slice(0,255)+"…":t}import{TextDecoder as Z}from"util";function F(e){return P(e,new Set)}var M=new Z("utf-8",{fatal:!0});function D(e){return Object.prototype.toString.call(e)}function G(e){return ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):function(e){return"[object ArrayBuffer]"===D(e)}(e)?new Uint8Array(e):void 0}function P(e,t){if("bigint"==typeof e)return e.toString();if("function"==typeof e)return`[Function ${e.name||"anonymous"}]`;if("symbol"==typeof e)return e.toString();if(null===e||"object"!=typeof e)return e;try{return function(e,t){if(function(e){return"[object Error]"===D(e)}(e))return{name:e.name,message:e.message};const n=G(e);if(n)return function(e){try{return M.decode(e)}catch{return`base64:${Buffer.from(e).toString("base64")}`}}(n);if(t.has(e))return"[Circular]";t.add(e);try{if(function(e){return"[object Map]"===D(e)}(e))return Array.from(e.entries(),([e,n])=>[P(e,t),P(n,t)]);if(function(e){return"[object Set]"===D(e)}(e))return Array.from(e.values(),e=>P(e,t));if(Array.isArray(e))return e.map(e=>P(e,t));if(function(e){return"toJSON"in e&&"function"==typeof e.toJSON}(e))return P(e.toJSON(),t);const n={};for(const[r,o]of Object.entries(e))n[r]=P(o,t);const r=function(e){const t=D(e).slice(8,-1);if("Object"!==t)return t;const n=Object.getPrototypeOf(e);if(null===n||n===Object.prototype)return;if("object"!=typeof n)return;const r=Reflect.get(n,"constructor");return"function"==typeof r&&"Object"!==r.name&&r.name||void 0}(e);return r?{[r]:n}:n}finally{t.delete(e)}}(e,t)}catch{return"[Unprintable]"}}function H(e,t){const n=t.filter(e=>e.length>=6),r=e=>{if("number"==typeof e){const t=String(e);return n.some(e=>t.includes(e))?"***":e}if(Array.isArray(e))return e.map(r);if(e&&"object"==typeof e){const t={};for(const[n,o]of Object.entries(e))t[n]=r(o);return t}return e};return r(e)}function T(e,t={}){const n=t.known??[];return U(JSON.stringify(H(F(e),n),null,t.space)??"undefined",{known:n})}function V(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function W(e){return null===e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e||e instanceof Uint8Array||(Array.isArray(e)?e.every(e=>void 0===e||W(e)):!!V(e)&&Object.values(e).every(e=>void 0===e||W(e)))}var C="__walkeros_cache__",K=class extends Error{constructor(e,t){var n,r;super(e),this.name="StoreCodecError",t&&"cause"in t&&(n=this,r=t.cause,Object.defineProperty(n,"cause",{value:r,writable:!0,configurable:!0}))}};function Y(e){if(Buffer.isBuffer(e))return{[C]:"buffer",d:e.toString("base64")};if(e instanceof Uint8Array)return{[C]:"buffer",d:Buffer.from(e.buffer,e.byteOffset,e.byteLength).toString("base64")};if(e instanceof ArrayBuffer)return{[C]:"buffer",d:Buffer.from(e).toString("base64")};if(Array.isArray(e))return e.map(Y);if(V(e)){if(C in e){const t={};for(const[n,r]of Object.entries(e))t[n]=Y(r);return{[C]:"escape",d:t}}const t={};for(const[n,r]of Object.entries(e))t[n]=Y(r);return t}return e}function q(e,t){if(V(e)){if(C in e){const n=e[C],r=e.d;if("buffer"===n&&"string"==typeof r)return t(Buffer.from(r,"base64"));if("escape"===n&&V(r)){const e={};for(const[n,o]of Object.entries(r))e[n]=q(o,t);return e}}const n={};for(const[r,o]of Object.entries(e))n[r]=q(o,t);return n}return Array.isArray(e)?e.map(e=>q(e,t)):e}function Q(e){return new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}function X(e){let t;try{t=JSON.stringify(Y(e))}catch(e){throw new K("Failed to serialize store value (likely a cyclic structure).",{cause:e})}return new Uint8Array(Buffer.from(t,"utf8"))}function ee(e){const t="string"==typeof e?e:Buffer.from(e).toString("utf8"),n=q(JSON.parse(t),Q);if(!W(n))throw new K("Restored value is not a valid StoreValue.");return n}var te=e.tmpdir();function ne(e,...n){const r=e||te,o=t.isAbsolute(r)?r:t.resolve(r);return t.join(o,...n)}function re(e){const n=e||te,r=t.isAbsolute(n)?n:t.resolve(n);return(...e)=>t.join(r,...e)}function oe(){return te}var ie=32768,se=e=>e;var ce={0:"ERROR",1:"WARNING",2:"INFO",3:"DEBUG"};function fe(e,t,n,r,o,i){const s=r.join(":"),c={severity:ce[e],message:o(`${s?`[${s}] `:""}${t}`),time:(new Date).toISOString()};let f;if(s&&(c.scope=s),Object.keys(n).length>0)try{f=o(JSON.stringify(H(n,i??[])));const e=JSON.parse(f);c.context="object"!=typeof(u=e)||null===u||Array.isArray(u)?"[unserializable context]":e}catch{f=void 0,c.context="[unserializable context]"}var u;let a=JSON.stringify(c);if(Buffer.byteLength(a)<=ie)return{entry:c,line:a};const l=16384;if(Buffer.byteLength(c.message)>l){const e=c.message;let t=l;do{c.message=e.slice(0,t),t=Math.floor(t/2)}while(Buffer.byteLength(c.message)>l&&t>0);c.messageTruncated=!0,a=JSON.stringify(c)}if(f&&Buffer.byteLength(a)>ie){c.contextTruncated=!0;let e=ie-Buffer.byteLength(c.message)-256;do{c.context=f.slice(0,Math.max(e,0)),a=JSON.stringify(c),e=Math.floor(e/2)}while(Buffer.byteLength(a)>ie&&e>0)}return{entry:c,line:a}}function ue(n={},r={}){const{verbose:o=!1,silent:i=!1,json:s=!1,stderr:c=!1,knownSecrets:f,format:u}=n,a="function"==typeof f?void 0:f?[...f]:void 0,l=()=>"function"==typeof f?f():a,g=e.tmpdir(),y=c?console.error:console.log,p=r.error??se,d=r.warn??se,b=r.info??se,h=r.debug??se,m=e=>U(function(e,n){if(!n||n===t.sep)return e;const r=n.endsWith(t.sep)?n:n+t.sep,o=e.split(r);if(1===o.length)return e;let i=o[0];for(let e=1;e<o.length;e++){const n=i.length>0?i[i.length-1]:"";i+=(""!==n&&/[\w./\\~-]/.test(n)?r:"$TMPDIR"+t.sep)+o[e]}return i}(J(e,l()),g));return{level:3,handler:(e,t,r,c)=>{const f=!s&&(0===e||!i)&&(3!==e||("function"==typeof o?o():o)),a=n.onLine;if(!f&&!a)return;const g=f&&"json"===(("function"==typeof u?u():u)??"text"),v=c.length>0?`[${c.join(":")}] `:"",A=g||a?fe(e,t,r,c,m,l()):void 0,O=a||!g?(()=>{let e="";if(Object.keys(r).length>0)try{e=` ${JSON.stringify(r)}`}catch{e=" [unserializable context]"}return m(`${v}${t}${e}`)})():"";if(a&&A)try{a(e,O,A.entry)}catch{}f&&(g&&A?0===e||1===e?console.error(A.line):y(A.line):0===e?console.error(p(O)):y(3===e?` ${h(O)}`:1===e?d(O):b(O)))},jsonHandler:e=>{i||y(JSON.stringify(e,null,2))}}}function ae(e={},t={}){return s(ue(e,t))}export{ie as MAX_JSON_LINE_BYTES,K as StoreCodecError,ae as createCLILogger,ue as createCLILoggerConfig,re as createTmpResolver,ee as deserializeStoreValue,oe as getDefaultTmpRoot,ne as getTmpPath,L as redactLine,T as scrubJson,U as scrubSecrets,X as serializeStoreValue,F as toPrintable};//# sourceMappingURL=node.mjs.map
|