{"version":3,"file":"scanner.cjs","names":["DEFAULT_ENV_PREFIXES","isClientPermittedEnvVar"],"sources":["../src/scanner.ts"],"sourcesContent":["import { isClientPermittedEnvVar, DEFAULT_ENV_PREFIXES } from '#env-classification'\nimport type { EnvAccess } from '#types'\n\n/**\n * Matches `process.env.VAR_NAME` or `import.meta.env.VAR_NAME` in source code\n * and captures the variable name after the dot.\n */\nconst ENV_PROPERTY_ACCESS_PATTERN = /(?:process\\.env|import\\.meta\\.env)\\.([A-Za-z_][A-Za-z0-9_]*)/g\n\n/**\n * Scans a module's source code for accesses to server-only environment variables.\n * Applies a targeted regex pattern to find all `process.env` and\n * `import.meta.env` accesses that are not covered by a configured env prefix\n * (`VITE_` by default) or the explicit allowlist.\n *\n * Each reported access carries the 1-based line and column of its variable name.\n *\n * @param sourceCode - The raw source text of the module to analyse.\n * @param allowClientAccess - The set of variable names explicitly allowed on the client.\n * @param envPrefixes - Prefixes Vite exposes to the client (resolved `envPrefix`).\n *   Defaults to {@link DEFAULT_ENV_PREFIXES} (`VITE_`).\n * @returns All environment variable accesses that are not permitted on the client side.\n */\nexport function scanModuleSource(\n  sourceCode: string,\n  allowClientAccess: Set<string>,\n  envPrefixes: readonly string[] = DEFAULT_ENV_PREFIXES\n): EnvAccess[] {\n  const foundAccesses: EnvAccess[] = []\n\n  for (const regexMatch of sourceCode.matchAll(ENV_PROPERTY_ACCESS_PATTERN)) {\n    const envVarName = regexMatch[1]\n\n    if (isClientPermittedEnvVar(envVarName, allowClientAccess, envPrefixes)) {\n      continue\n    }\n\n    const envVarNameOffset = regexMatch.index + regexMatch[0].length - envVarName.length\n    foundAccesses.push({ envVarName, ...resolveLineAndColumn(sourceCode, envVarNameOffset) })\n  }\n\n  return foundAccesses\n}\n\n/**\n * Resolves a zero-based character offset to its 1-based line and column from the\n * source text that precedes it.\n *\n * @param sourceCode - The source text the offset refers to.\n * @param offset - The zero-based character offset to resolve.\n * @returns The 1-based line and column at that offset.\n */\nfunction resolveLineAndColumn(sourceCode: string, offset: number): { line: number; column: number } {\n  const precedingText = sourceCode.slice(0, offset)\n\n  return {\n    line: precedingText.split('\\n').length,\n    column: offset - precedingText.lastIndexOf('\\n'),\n  }\n}\n"],"mappings":";;;;;;;AAOA,MAAM,8BAA8B;;;;;;;;;;;;;;;AAgBpC,SAAgB,iBACd,YACA,mBACA,cAAiCA,2BAAAA,sBACpB;CACb,MAAM,gBAA6B,EAAE;AAErC,MAAK,MAAM,cAAc,WAAW,SAAS,4BAA4B,EAAE;EACzE,MAAM,aAAa,WAAW;AAE9B,MAAIC,2BAAAA,wBAAwB,YAAY,mBAAmB,YAAY,CACrE;EAGF,MAAM,mBAAmB,WAAW,QAAQ,WAAW,GAAG,SAAS,WAAW;AAC9E,gBAAc,KAAK;GAAE;GAAY,GAAG,qBAAqB,YAAY,iBAAiB;GAAE,CAAC;;AAG3F,QAAO;;;;;;;;;;AAWT,SAAS,qBAAqB,YAAoB,QAAkD;CAClG,MAAM,gBAAgB,WAAW,MAAM,GAAG,OAAO;AAEjD,QAAO;EACL,MAAM,cAAc,MAAM,KAAK,CAAC;EAChC,QAAQ,SAAS,cAAc,YAAY,KAAK;EACjD"}