init claude-code
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import memoize from 'lodash-es/memoize.js'
|
||||
import { logForDebugging } from './debug.js'
|
||||
import { hasNodeOption } from './envUtils.js'
|
||||
import { getFsImplementation } from './fsOperations.js'
|
||||
|
||||
/**
|
||||
* Load CA certificates for TLS connections.
|
||||
*
|
||||
* Since setting `ca` on an HTTPS agent replaces the default certificate store,
|
||||
* we must always include base CAs (either system or bundled Mozilla) when returning.
|
||||
*
|
||||
* Returns undefined when no custom CA configuration is needed, allowing the
|
||||
* runtime's default certificate handling to apply.
|
||||
*
|
||||
* Behavior:
|
||||
* - Neither NODE_EXTRA_CA_CERTS nor --use-system-ca/--use-openssl-ca set: undefined (runtime defaults)
|
||||
* - NODE_EXTRA_CA_CERTS only: bundled Mozilla CAs + extra cert file contents
|
||||
* - --use-system-ca or --use-openssl-ca only: system CAs
|
||||
* - --use-system-ca + NODE_EXTRA_CA_CERTS: system CAs + extra cert file contents
|
||||
*
|
||||
* Memoized for performance. Call clearCACertsCache() to invalidate after
|
||||
* environment variable changes (e.g., after trust dialog applies settings.json).
|
||||
*
|
||||
* Reads ONLY `process.env.NODE_EXTRA_CA_CERTS`. `caCertsConfig.ts` populates
|
||||
* that env var from settings.json at CLI init; this module stays config-free
|
||||
* so `proxy.ts`/`mtls.ts` don't transitively pull in the command registry.
|
||||
*/
|
||||
export const getCACertificates = memoize((): string[] | undefined => {
|
||||
const useSystemCA =
|
||||
hasNodeOption('--use-system-ca') || hasNodeOption('--use-openssl-ca')
|
||||
|
||||
const extraCertsPath = process.env.NODE_EXTRA_CA_CERTS
|
||||
|
||||
logForDebugging(
|
||||
`CA certs: useSystemCA=${useSystemCA}, extraCertsPath=${extraCertsPath}`,
|
||||
)
|
||||
|
||||
// If neither is set, return undefined (use runtime defaults, no override)
|
||||
if (!useSystemCA && !extraCertsPath) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
// Deferred load: Bun's node:tls module eagerly materializes ~150 Mozilla
|
||||
// root certificates (~750KB heap) on import, even if tls.rootCertificates
|
||||
// is never accessed. Most users hit the early return above, so we only
|
||||
// pay this cost when custom CA handling is actually needed.
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const tls = require('tls') as typeof import('tls')
|
||||
/* eslint-enable @typescript-eslint/no-require-imports */
|
||||
|
||||
const certs: string[] = []
|
||||
|
||||
if (useSystemCA) {
|
||||
// Load system CA store (Bun API)
|
||||
const getCACerts = (
|
||||
tls as typeof tls & { getCACertificates?: (type: string) => string[] }
|
||||
).getCACertificates
|
||||
const systemCAs = getCACerts?.('system')
|
||||
if (systemCAs && systemCAs.length > 0) {
|
||||
certs.push(...systemCAs)
|
||||
logForDebugging(
|
||||
`CA certs: Loaded ${certs.length} system CA certificates (--use-system-ca)`,
|
||||
)
|
||||
} else if (!getCACerts && !extraCertsPath) {
|
||||
// Under Node.js where getCACertificates doesn't exist and no extra certs,
|
||||
// return undefined to let Node.js handle --use-system-ca natively.
|
||||
logForDebugging(
|
||||
'CA certs: --use-system-ca set but system CA API unavailable, deferring to runtime',
|
||||
)
|
||||
return undefined
|
||||
} else {
|
||||
// System CA API returned empty or unavailable; fall back to bundled root certs
|
||||
certs.push(...tls.rootCertificates)
|
||||
logForDebugging(
|
||||
`CA certs: Loaded ${certs.length} bundled root certificates as base (--use-system-ca fallback)`,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Must include bundled Mozilla CAs as base since ca replaces defaults
|
||||
certs.push(...tls.rootCertificates)
|
||||
logForDebugging(
|
||||
`CA certs: Loaded ${certs.length} bundled root certificates as base`,
|
||||
)
|
||||
}
|
||||
|
||||
// Append extra certs from file
|
||||
if (extraCertsPath) {
|
||||
try {
|
||||
const extraCert = getFsImplementation().readFileSync(extraCertsPath, {
|
||||
encoding: 'utf8',
|
||||
})
|
||||
certs.push(extraCert)
|
||||
logForDebugging(
|
||||
`CA certs: Appended extra certificates from NODE_EXTRA_CA_CERTS (${extraCertsPath})`,
|
||||
)
|
||||
} catch (error) {
|
||||
logForDebugging(
|
||||
`CA certs: Failed to read NODE_EXTRA_CA_CERTS file (${extraCertsPath}): ${error}`,
|
||||
{ level: 'error' },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return certs.length > 0 ? certs : undefined
|
||||
})
|
||||
|
||||
/**
|
||||
* Clear the CA certificates cache.
|
||||
* Call this when environment variables that affect CA certs may have changed
|
||||
* (e.g., NODE_EXTRA_CA_CERTS, NODE_OPTIONS).
|
||||
*/
|
||||
export function clearCACertsCache(): void {
|
||||
getCACertificates.cache.clear?.()
|
||||
logForDebugging('Cleared CA certificates cache')
|
||||
}
|
||||
Reference in New Issue
Block a user