@cdxgen/cdxgen 0.0.1 → 13.0.1
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/README.md +921 -87
- package/bin/audit.js +239 -0
- package/bin/cdxgen.js +2335 -0
- package/bin/convert.js +220 -0
- package/bin/evinse.js +353 -0
- package/bin/hbom.js +504 -0
- package/bin/repl.js +2224 -0
- package/bin/sign.js +195 -0
- package/bin/tracebom.js +303 -0
- package/bin/validate.js +268 -0
- package/bin/verify.js +189 -0
- package/data/README.md +307 -0
- package/data/bom-1.4.schema.json +1605 -0
- package/data/bom-1.5.schema.json +3660 -0
- package/data/bom-1.6.schema.json +5511 -0
- package/data/bom-1.7.schema.json +6700 -0
- package/data/cbomosdb-queries.json +68 -0
- package/data/component-tags.json +339 -0
- package/data/container-knowledge-index.json +125 -0
- package/data/cosdb-queries.json +17 -0
- package/data/crypto-oid.json +1998 -0
- package/data/cryptography-defs.json +3793 -0
- package/data/cryptography-defs.schema.json +576 -0
- package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
- package/data/frameworks-list.json +219 -0
- package/data/glibc-stdlib.json +117 -0
- package/data/gtfobins-index.json +6296 -0
- package/data/helpers/init.gradle +71 -0
- package/data/jsf-0.82.schema.json +211 -0
- package/data/known-licenses.json +82 -0
- package/data/lic-mapping.json +338 -0
- package/data/license-aliases.json +6624 -0
- package/data/license-db.json +39059 -0
- package/data/license-deprecations.json +302 -0
- package/data/lolbas-index.json +150 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/pypi-pkg-aliases.json +1199 -0
- package/data/python-stdlib.json +308 -0
- package/data/queries-darwin.json +193 -0
- package/data/queries-win.json +257 -0
- package/data/queries.json +268 -0
- package/data/ruby-known-modules.json +281 -0
- package/data/rules/ai-agent-governance.yaml +323 -0
- package/data/rules/ai-bom.yaml +268 -0
- package/data/rules/ai-oversight.yaml +186 -0
- package/data/rules/ai-provenance.yaml +92 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/cbom-security.yaml +165 -0
- package/data/rules/chrome-extensions.yaml +248 -0
- package/data/rules/ci-permissions.yaml +802 -0
- package/data/rules/container-risk.yaml +353 -0
- package/data/rules/dependency-sources.yaml +236 -0
- package/data/rules/golem-go.yaml +229 -0
- package/data/rules/hbom-compliance.yaml +325 -0
- package/data/rules/hbom-performance.yaml +307 -0
- package/data/rules/hbom-security.yaml +248 -0
- package/data/rules/host-topology.yaml +165 -0
- package/data/rules/mcp-servers.yaml +388 -0
- package/data/rules/obom-runtime.yaml +1776 -0
- package/data/rules/package-integrity.yaml +364 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +237 -0
- package/data/spdx-export.schema.json +6794 -0
- package/data/spdx-license-list.json +7449 -0
- package/data/spdx-licenses.json +759 -0
- package/data/spdx.schema.json +819 -0
- package/data/templates/README.md +3 -0
- package/data/templates/asvs-4.0.3.cdx.json +2943 -0
- package/data/templates/asvs-5.0.cdx.json +3046 -0
- package/data/templates/bsimm-v13.cdx.json +1008 -0
- package/data/templates/masvs-2.0.0.cdx.json +225 -0
- package/data/templates/nist-ssdf-1.1.cdx.json +828 -0
- package/data/templates/pcissc-secure-slc-1.1.cdx.json +1027 -0
- package/data/templates/scvs-1.0.0.cdx.json +813 -0
- package/data/templates/ssaf-DRAFT-2023-11.cdx.json +127 -0
- package/data/vendor-alias.json +41967 -0
- package/data/wrapdb-releases.json +4227 -0
- package/index.cjs +15 -0
- package/lib/audit/index.js +2800 -0
- package/lib/audit/progress.js +114 -0
- package/lib/audit/reporters.js +937 -0
- package/lib/audit/scoring.js +560 -0
- package/lib/audit/targets.js +798 -0
- package/lib/cli/bomAssembly.js +1882 -0
- package/lib/cli/cliOptions.js +543 -0
- package/lib/cli/index.js +2759 -0
- package/lib/cli/jsBom.js +2087 -0
- package/lib/cli/jvmBom.js +1858 -0
- package/lib/cli/managedBom.js +2083 -0
- package/lib/cli/nativeBom.js +2125 -0
- package/lib/core/activity.js +1087 -0
- package/lib/core/env.js +719 -0
- package/lib/core/fs.js +1058 -0
- package/lib/core/httpClient.js +730 -0
- package/lib/core/logger.js +280 -0
- package/lib/core/parallel.js +323 -0
- package/lib/core/paths.js +70 -0
- package/lib/core/projectConfig.js +122 -0
- package/lib/core/propertySanitizer.js +174 -0
- package/lib/core/spdx.js +5 -0
- package/lib/core/state.js +59 -0
- package/lib/core/text.js +207 -0
- package/lib/core/ui.js +920 -0
- package/lib/core/urls.js +84 -0
- package/lib/ecosystems/asarutils.js +1636 -0
- package/lib/ecosystems/bunutils.js +402 -0
- package/lib/ecosystems/caxa.js +77 -0
- package/lib/ecosystems/chromextutils.js +1174 -0
- package/lib/ecosystems/cmakeResolver.js +587 -0
- package/lib/ecosystems/cppEvidence.js +305 -0
- package/lib/ecosystems/denoutils.js +1094 -0
- package/lib/ecosystems/dotnetutils.js +132 -0
- package/lib/ecosystems/ecosystems.js +2772 -0
- package/lib/ecosystems/golem.js +1807 -0
- package/lib/ecosystems/gradleutils.js +1048 -0
- package/lib/ecosystems/jsEvidence.js +317 -0
- package/lib/ecosystems/npmutils.js +586 -0
- package/lib/ecosystems/parsers-bazel.js +875 -0
- package/lib/ecosystems/parsers-dotnet.js +1430 -0
- package/lib/ecosystems/parsers-gleam.js +302 -0
- package/lib/ecosystems/parsers-go.js +818 -0
- package/lib/ecosystems/parsers-js.js +4222 -0
- package/lib/ecosystems/parsers-jvm.js +948 -0
- package/lib/ecosystems/parsers-misc.js +3191 -0
- package/lib/ecosystems/parsers-python.js +2070 -0
- package/lib/ecosystems/parsers-rust.js +1294 -0
- package/lib/ecosystems/parsers-zig.js +861 -0
- package/lib/ecosystems/pep770.js +341 -0
- package/lib/ecosystems/pylockutils.js +427 -0
- package/lib/ecosystems/pythonutils.js +1281 -0
- package/lib/ecosystems/registryProvenance.js +1003 -0
- package/lib/ecosystems/remote/huggingface.js +1343 -0
- package/lib/ecosystems/rubyutils.js +1629 -0
- package/lib/ecosystems/rusi.js +820 -0
- package/lib/ecosystems/sbtutils.js +972 -0
- package/lib/ecosystems/tea.js +607 -0
- package/lib/ecosystems/utils.js +583 -0
- package/lib/ecosystems/zigResolver.js +410 -0
- package/lib/evinser/db.js +145 -0
- package/lib/evinser/evinser.js +2362 -0
- package/lib/evinser/scalasem.js +65 -0
- package/lib/evinser/swiftsem.js +767 -0
- package/lib/helpers/annotationFormatter.js +84 -0
- package/lib/helpers/bomSigner.js +312 -0
- package/lib/helpers/exportUtils.js +160 -0
- package/lib/helpers/remote/dependency-track.js +117 -0
- package/lib/helpers/versutils.js +202 -0
- package/lib/helpers/vsixutils.js +1069 -0
- package/lib/inventory/agentFormulationParser.js +322 -0
- package/lib/inventory/aiCollector.js +2140 -0
- package/lib/inventory/aiInventory.js +414 -0
- package/lib/inventory/aiModelVariants.js +121 -0
- package/lib/inventory/aiOversightCollector.js +661 -0
- package/lib/inventory/aiProvenanceCollector.js +822 -0
- package/lib/inventory/analyzer.js +6089 -0
- package/lib/inventory/analyzerScope.js +807 -0
- package/lib/inventory/astWorker.js +20 -0
- package/lib/inventory/atomUtils.js +1092 -0
- package/lib/inventory/auditCategories.js +192 -0
- package/lib/inventory/bomUtils.js +369 -0
- package/lib/inventory/cacheCommands.js +182 -0
- package/lib/inventory/cacheDir.js +104 -0
- package/lib/inventory/cbomutils.js +590 -0
- package/lib/inventory/cdxrs.js +434 -0
- package/lib/inventory/ciParsers/azurePipelines.js +295 -0
- package/lib/inventory/ciParsers/circleCi.js +286 -0
- package/lib/inventory/ciParsers/common.js +24 -0
- package/lib/inventory/ciParsers/githubActions.js +2434 -0
- package/lib/inventory/ciParsers/gitlabCi.js +213 -0
- package/lib/inventory/ciParsers/jenkins.js +180 -0
- package/lib/inventory/citations.js +234 -0
- package/lib/inventory/communityAiConfigParser.js +756 -0
- package/lib/inventory/containerRisk.js +204 -0
- package/lib/inventory/cryptoAlgorithmFamily.js +258 -0
- package/lib/inventory/deps.js +807 -0
- package/lib/inventory/depsUtils.js +588 -0
- package/lib/inventory/display.js +2128 -0
- package/lib/inventory/dosai.js +601 -0
- package/lib/inventory/dosaiParsers.js +154 -0
- package/lib/inventory/dynamic.js +145 -0
- package/lib/inventory/envcontext.js +1793 -0
- package/lib/inventory/evidenceUtils.js +774 -0
- package/lib/inventory/fetchBatch.js +779 -0
- package/lib/inventory/fetchRate.js +255 -0
- package/lib/inventory/forgeEnricher.js +300 -0
- package/lib/inventory/formulationParsers.js +422 -0
- package/lib/inventory/gtfobins.js +339 -0
- package/lib/inventory/hbom.js +719 -0
- package/lib/inventory/hbomAnalysis.js +310 -0
- package/lib/inventory/hbomLoader.js +35 -0
- package/lib/inventory/hostTopology.js +835 -0
- package/lib/inventory/inventoryStats.js +100 -0
- package/lib/inventory/jsonLike.js +121 -0
- package/lib/inventory/licenseEnhancer.js +918 -0
- package/lib/inventory/lolbas.js +285 -0
- package/lib/inventory/mcp.js +253 -0
- package/lib/inventory/mcpConfigParser.js +683 -0
- package/lib/inventory/mcpDiscovery.js +112 -0
- package/lib/inventory/mcpPinning.js +209 -0
- package/lib/inventory/osPackageResolver.js +493 -0
- package/lib/inventory/osinfo.js +383 -0
- package/lib/inventory/osqueryTransform.js +274 -0
- package/lib/inventory/plugins.js +466 -0
- package/lib/inventory/protobom.js +231 -0
- package/lib/inventory/protobomLoader.js +43 -0
- package/lib/inventory/provenanceUtils.js +224 -0
- package/lib/inventory/purl.js +749 -0
- package/lib/inventory/rustFormulationParser.js +339 -0
- package/lib/inventory/sbomDocument.js +340 -0
- package/lib/inventory/source.js +1488 -0
- package/lib/inventory/spdx.js +361 -0
- package/lib/inventory/spdxExpression.js +512 -0
- package/lib/inventory/spdxUtils.js +107 -0
- package/lib/inventory/table.js +267 -0
- package/lib/inventory/traceRunner.js +439 -0
- package/lib/inventory/unicodeScan.js +147 -0
- package/lib/managers/binary.js +3459 -0
- package/lib/managers/containerutils.js +125 -0
- package/lib/managers/docker.js +2145 -0
- package/lib/managers/dockerConnection.js +162 -0
- package/lib/managers/oci.js +704 -0
- package/lib/managers/piptree.js +267 -0
- package/lib/parsers/cmakeCache.js +199 -0
- package/lib/parsers/gguf.js +492 -0
- package/lib/parsers/gitAiNotes.js +233 -0
- package/lib/parsers/gitmodules.js +239 -0
- package/lib/parsers/htmlExtract.js +610 -0
- package/lib/parsers/huggingfaceManifest.js +551 -0
- package/lib/parsers/huggingfaceUtils.js +506 -0
- package/lib/parsers/iri.js +618 -0
- package/lib/parsers/npmrc.js +99 -0
- package/lib/parsers/ollama.js +101 -0
- package/lib/parsers/xml.js +841 -0
- package/lib/server/openapi.yaml +433 -0
- package/lib/server/server.js +616 -0
- package/lib/stages/postgen/annotator.js +977 -0
- package/lib/stages/postgen/auditBom.js +468 -0
- package/lib/stages/postgen/postgen.js +1239 -0
- package/lib/stages/postgen/ruleEngine.js +731 -0
- package/lib/stages/postgen/sortBom.js +195 -0
- package/lib/stages/postgen/spdxConverter.js +796 -0
- package/lib/stages/postgen/specVersionCompat.js +703 -0
- package/lib/stages/pregen/envAudit.js +388 -0
- package/lib/stages/pregen/pregen.js +637 -0
- package/lib/third-party/README.md +9 -0
- package/lib/third-party/arborist/CHANGELOG.md +1109 -0
- package/lib/third-party/arborist/LICENSE.md +20 -0
- package/lib/third-party/arborist/README.md +315 -0
- package/lib/third-party/arborist/lib/arborist/index.js +258 -0
- package/lib/third-party/arborist/lib/arborist/load-actual.js +605 -0
- package/lib/third-party/arborist/lib/arborist/load-virtual.js +300 -0
- package/lib/third-party/arborist/lib/bin-links.js +120 -0
- package/lib/third-party/arborist/lib/calc-dep-flags.js +130 -0
- package/lib/third-party/arborist/lib/case-insensitive-map.js +51 -0
- package/lib/third-party/arborist/lib/consistent-resolve.js +42 -0
- package/lib/third-party/arborist/lib/debug.js +50 -0
- package/lib/third-party/arborist/lib/dep-valid.js +190 -0
- package/lib/third-party/arborist/lib/edge.js +417 -0
- package/lib/third-party/arborist/lib/from-path.js +36 -0
- package/lib/third-party/arborist/lib/gather-dep-set.js +43 -0
- package/lib/third-party/arborist/lib/index.js +22 -0
- package/lib/third-party/arborist/lib/inventory.js +138 -0
- package/lib/third-party/arborist/lib/link.js +169 -0
- package/lib/third-party/arborist/lib/node.js +1673 -0
- package/lib/third-party/arborist/lib/npm-extension.js +45 -0
- package/lib/third-party/arborist/lib/override-resolves.js +11 -0
- package/lib/third-party/arborist/lib/override-set.js +319 -0
- package/lib/third-party/arborist/lib/package-extensions.js +289 -0
- package/lib/third-party/arborist/lib/printable.js +210 -0
- package/lib/third-party/arborist/lib/proc-log.js +30 -0
- package/lib/third-party/arborist/lib/realpath.js +100 -0
- package/lib/third-party/arborist/lib/relpath.js +4 -0
- package/lib/third-party/arborist/lib/shrinkwrap.js +1291 -0
- package/lib/third-party/arborist/lib/spec-from-lock.js +34 -0
- package/lib/third-party/arborist/lib/tree-check.js +165 -0
- package/lib/third-party/arborist/lib/validate-npm-package-name.js +107 -0
- package/lib/third-party/arborist/lib/version-from-tgz.js +51 -0
- package/lib/third-party/arborist/lib/yarn-lock.js +397 -0
- package/lib/validator/bomValidator.js +985 -0
- package/lib/validator/complianceEngine.js +241 -0
- package/lib/validator/complianceRules.js +1680 -0
- package/lib/validator/generated/runtime.mjs +17 -0
- package/lib/validator/generated/validate-1.6.mjs +21258 -0
- package/lib/validator/generated/validate-1.7.mjs +24803 -0
- package/lib/validator/generated/validate-2.0.mjs +22931 -0
- package/lib/validator/index.js +246 -0
- package/lib/validator/reporters/annotations.js +142 -0
- package/lib/validator/reporters/console.js +160 -0
- package/lib/validator/reporters/index.js +41 -0
- package/lib/validator/reporters/json.js +37 -0
- package/lib/validator/reporters/sarif.js +184 -0
- package/package.json +209 -26
- package/types/bin/audit.d.ts +3 -0
- package/types/bin/audit.d.ts.map +1 -0
- package/types/bin/cdxgen.d.ts +3 -0
- package/types/bin/cdxgen.d.ts.map +1 -0
- package/types/bin/convert.d.ts +3 -0
- package/types/bin/convert.d.ts.map +1 -0
- package/types/bin/evinse.d.ts +3 -0
- package/types/bin/evinse.d.ts.map +1 -0
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts +3 -0
- package/types/bin/repl.d.ts.map +1 -0
- package/types/bin/sign.d.ts +3 -0
- package/types/bin/sign.d.ts.map +1 -0
- package/types/bin/tracebom.d.ts +3 -0
- package/types/bin/tracebom.d.ts.map +1 -0
- package/types/bin/validate.d.ts +14 -0
- package/types/bin/validate.d.ts.map +1 -0
- package/types/bin/verify.d.ts +3 -0
- package/types/bin/verify.d.ts.map +1 -0
- package/types/lib/audit/index.d.ts +153 -0
- package/types/lib/audit/index.d.ts.map +1 -0
- package/types/lib/audit/progress.d.ts +31 -0
- package/types/lib/audit/progress.d.ts.map +1 -0
- package/types/lib/audit/reporters.d.ts +62 -0
- package/types/lib/audit/reporters.d.ts.map +1 -0
- package/types/lib/audit/scoring.d.ts +36 -0
- package/types/lib/audit/scoring.d.ts.map +1 -0
- package/types/lib/audit/targets.d.ts +77 -0
- package/types/lib/audit/targets.d.ts.map +1 -0
- package/types/lib/cli/bomAssembly.d.ts +329 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -0
- package/types/lib/cli/cliOptions.d.ts +156 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -0
- package/types/lib/cli/index.d.ts +107 -0
- package/types/lib/cli/index.d.ts.map +1 -0
- package/types/lib/cli/jsBom.d.ts +94 -0
- package/types/lib/cli/jsBom.d.ts.map +1 -0
- package/types/lib/cli/jvmBom.d.ts +54 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -0
- package/types/lib/cli/managedBom.d.ts +105 -0
- package/types/lib/cli/managedBom.d.ts.map +1 -0
- package/types/lib/cli/nativeBom.d.ts +143 -0
- package/types/lib/cli/nativeBom.d.ts.map +1 -0
- package/types/lib/core/activity.d.ts +178 -0
- package/types/lib/core/activity.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +192 -0
- package/types/lib/core/env.d.ts.map +1 -0
- package/types/lib/core/fs.d.ts +158 -0
- package/types/lib/core/fs.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +149 -0
- package/types/lib/core/httpClient.d.ts.map +1 -0
- package/types/lib/core/logger.d.ts +50 -0
- package/types/lib/core/logger.d.ts.map +1 -0
- package/types/lib/core/parallel.d.ts +95 -0
- package/types/lib/core/parallel.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +36 -0
- package/types/lib/core/paths.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts +23 -0
- package/types/lib/core/projectConfig.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +23 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -0
- package/types/lib/core/spdx.d.ts +5 -0
- package/types/lib/core/spdx.d.ts.map +1 -0
- package/types/lib/core/state.d.ts +20 -0
- package/types/lib/core/state.d.ts.map +1 -0
- package/types/lib/core/text.d.ts +78 -0
- package/types/lib/core/text.d.ts.map +1 -0
- package/types/lib/core/ui.d.ts +87 -0
- package/types/lib/core/ui.d.ts.map +1 -0
- package/types/lib/core/urls.d.ts +43 -0
- package/types/lib/core/urls.d.ts.map +1 -0
- package/types/lib/ecosystems/asarutils.d.ts +71 -0
- package/types/lib/ecosystems/asarutils.d.ts.map +1 -0
- package/types/lib/ecosystems/bunutils.d.ts +38 -0
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -0
- package/types/lib/ecosystems/caxa.d.ts +8 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -0
- package/types/lib/ecosystems/chromextutils.d.ts +97 -0
- package/types/lib/ecosystems/chromextutils.d.ts.map +1 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts +176 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +35 -0
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/denoutils.d.ts +76 -0
- package/types/lib/ecosystems/denoutils.d.ts.map +1 -0
- package/types/lib/ecosystems/dotnetutils.d.ts +45 -0
- package/types/lib/ecosystems/dotnetutils.d.ts.map +1 -0
- package/types/lib/ecosystems/ecosystems.d.ts +279 -0
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts +60 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -0
- package/types/lib/ecosystems/gradleutils.d.ts +139 -0
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -0
- package/types/lib/ecosystems/jsEvidence.d.ts +17 -0
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/npmutils.d.ts +183 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts +36 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts +116 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts +33 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-go.d.ts +92 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-js.d.ts +242 -0
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts +100 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-misc.d.ts +450 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts +145 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rust.d.ts +56 -0
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-zig.d.ts +83 -0
- package/types/lib/ecosystems/parsers-zig.d.ts.map +1 -0
- package/types/lib/ecosystems/pep770.d.ts +38 -0
- package/types/lib/ecosystems/pep770.d.ts.map +1 -0
- package/types/lib/ecosystems/pylockutils.d.ts +68 -0
- package/types/lib/ecosystems/pylockutils.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +70 -0
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -0
- package/types/lib/ecosystems/registryProvenance.d.ts +26 -0
- package/types/lib/ecosystems/registryProvenance.d.ts.map +1 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts +31 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -0
- package/types/lib/ecosystems/rubyutils.d.ts +182 -0
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -0
- package/types/lib/ecosystems/rusi.d.ts +40 -0
- package/types/lib/ecosystems/rusi.d.ts.map +1 -0
- package/types/lib/ecosystems/sbtutils.d.ts +179 -0
- package/types/lib/ecosystems/sbtutils.d.ts.map +1 -0
- package/types/lib/ecosystems/tea.d.ts +180 -0
- package/types/lib/ecosystems/tea.d.ts.map +1 -0
- package/types/lib/ecosystems/utils.d.ts +41 -0
- package/types/lib/ecosystems/utils.d.ts.map +1 -0
- package/types/lib/ecosystems/zigResolver.d.ts +70 -0
- package/types/lib/ecosystems/zigResolver.d.ts.map +1 -0
- package/types/lib/evinser/db.d.ts +17 -0
- package/types/lib/evinser/db.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +354 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -0
- package/types/lib/evinser/scalasem.d.ts +15 -0
- package/types/lib/evinser/scalasem.d.ts.map +1 -0
- package/types/lib/evinser/swiftsem.d.ts +103 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -0
- package/types/lib/helpers/annotationFormatter.d.ts +23 -0
- package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
- package/types/lib/helpers/bomSigner.d.ts +28 -0
- package/types/lib/helpers/bomSigner.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts +52 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +23 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/versutils.d.ts +8 -0
- package/types/lib/helpers/versutils.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +130 -0
- package/types/lib/helpers/vsixutils.d.ts.map +1 -0
- package/types/lib/inventory/agentFormulationParser.d.ts +21 -0
- package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts +61 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiInventory.d.ts +103 -0
- package/types/lib/inventory/aiInventory.d.ts.map +1 -0
- package/types/lib/inventory/aiModelVariants.d.ts +31 -0
- package/types/lib/inventory/aiModelVariants.d.ts.map +1 -0
- package/types/lib/inventory/aiOversightCollector.d.ts +28 -0
- package/types/lib/inventory/aiOversightCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts +13 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts.map +1 -0
- package/types/lib/inventory/analyzer.d.ts +157 -0
- package/types/lib/inventory/analyzer.d.ts.map +1 -0
- package/types/lib/inventory/analyzerScope.d.ts +106 -0
- package/types/lib/inventory/analyzerScope.d.ts.map +1 -0
- package/types/lib/inventory/astWorker.d.ts +9 -0
- package/types/lib/inventory/astWorker.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +159 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -0
- package/types/lib/inventory/auditCategories.d.ts +80 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts +145 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -0
- package/types/lib/inventory/cacheCommands.d.ts +28 -0
- package/types/lib/inventory/cacheCommands.d.ts.map +1 -0
- package/types/lib/inventory/cacheDir.d.ts +55 -0
- package/types/lib/inventory/cacheDir.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +37 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -0
- package/types/lib/inventory/cdxrs.d.ts +90 -0
- package/types/lib/inventory/cdxrs.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts +27 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts +27 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/common.d.ts +11 -0
- package/types/lib/inventory/ciParsers/common.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts +38 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts +26 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts +26 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +90 -0
- package/types/lib/inventory/citations.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts +14 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/containerRisk.d.ts +20 -0
- package/types/lib/inventory/containerRisk.d.ts.map +1 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts +37 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +140 -0
- package/types/lib/inventory/deps.d.ts.map +1 -0
- package/types/lib/inventory/depsUtils.d.ts +74 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -0
- package/types/lib/inventory/display.d.ts +227 -0
- package/types/lib/inventory/display.d.ts.map +1 -0
- package/types/lib/inventory/dosai.d.ts +130 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -0
- package/types/lib/inventory/dosaiParsers.d.ts +59 -0
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -0
- package/types/lib/inventory/dynamic.d.ts +25 -0
- package/types/lib/inventory/dynamic.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +377 -0
- package/types/lib/inventory/envcontext.d.ts.map +1 -0
- package/types/lib/inventory/evidenceUtils.d.ts +74 -0
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -0
- package/types/lib/inventory/fetchBatch.d.ts +127 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -0
- package/types/lib/inventory/fetchRate.d.ts +118 -0
- package/types/lib/inventory/fetchRate.d.ts.map +1 -0
- package/types/lib/inventory/forgeEnricher.d.ts +31 -0
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -0
- package/types/lib/inventory/formulationParsers.d.ts +50 -0
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/gtfobins.d.ts +27 -0
- package/types/lib/inventory/gtfobins.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts +58 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -0
- package/types/lib/inventory/hbomAnalysis.d.ts +56 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/inventory/hbomLoader.d.ts +7 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -0
- package/types/lib/inventory/hostTopology.d.ts +47 -0
- package/types/lib/inventory/hostTopology.d.ts.map +1 -0
- package/types/lib/inventory/inventoryStats.d.ts +42 -0
- package/types/lib/inventory/inventoryStats.d.ts.map +1 -0
- package/types/lib/inventory/jsonLike.d.ts +23 -0
- package/types/lib/inventory/jsonLike.d.ts.map +1 -0
- package/types/lib/inventory/licenseEnhancer.d.ts +70 -0
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -0
- package/types/lib/inventory/lolbas.d.ts +16 -0
- package/types/lib/inventory/lolbas.d.ts.map +1 -0
- package/types/lib/inventory/mcp.d.ts +29 -0
- package/types/lib/inventory/mcp.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts +20 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/mcpDiscovery.d.ts +33 -0
- package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/inventory/mcpPinning.d.ts +11 -0
- package/types/lib/inventory/mcpPinning.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +49 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -0
- package/types/lib/inventory/osinfo.d.ts +201 -0
- package/types/lib/inventory/osinfo.d.ts.map +1 -0
- package/types/lib/inventory/osqueryTransform.d.ts +84 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts +58 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -0
- package/types/lib/inventory/protobom.d.ts +71 -0
- package/types/lib/inventory/protobom.d.ts.map +1 -0
- package/types/lib/inventory/protobomLoader.d.ts +17 -0
- package/types/lib/inventory/protobomLoader.d.ts.map +1 -0
- package/types/lib/inventory/provenanceUtils.d.ts +98 -0
- package/types/lib/inventory/provenanceUtils.d.ts.map +1 -0
- package/types/lib/inventory/purl.d.ts +313 -0
- package/types/lib/inventory/purl.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +17 -0
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/sbomDocument.d.ts +59 -0
- package/types/lib/inventory/sbomDocument.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +163 -0
- package/types/lib/inventory/source.d.ts.map +1 -0
- package/types/lib/inventory/spdx.d.ts +66 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -0
- package/types/lib/inventory/spdxExpression.d.ts +58 -0
- package/types/lib/inventory/spdxExpression.d.ts.map +1 -0
- package/types/lib/inventory/spdxUtils.d.ts +12 -0
- package/types/lib/inventory/spdxUtils.d.ts.map +1 -0
- package/types/lib/inventory/table.d.ts +22 -0
- package/types/lib/inventory/table.d.ts.map +1 -0
- package/types/lib/inventory/traceRunner.d.ts +80 -0
- package/types/lib/inventory/traceRunner.d.ts.map +1 -0
- package/types/lib/inventory/unicodeScan.d.ts +46 -0
- package/types/lib/inventory/unicodeScan.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +147 -0
- package/types/lib/managers/binary.d.ts.map +1 -0
- package/types/lib/managers/containerutils.d.ts +30 -0
- package/types/lib/managers/containerutils.d.ts.map +1 -0
- package/types/lib/managers/docker.d.ts +157 -0
- package/types/lib/managers/docker.d.ts.map +1 -0
- package/types/lib/managers/dockerConnection.d.ts +42 -0
- package/types/lib/managers/dockerConnection.d.ts.map +1 -0
- package/types/lib/managers/oci.d.ts +21 -0
- package/types/lib/managers/oci.d.ts.map +1 -0
- package/types/lib/managers/piptree.d.ts +13 -0
- package/types/lib/managers/piptree.d.ts.map +1 -0
- package/types/lib/parsers/cmakeCache.d.ts +70 -0
- package/types/lib/parsers/cmakeCache.d.ts.map +1 -0
- package/types/lib/parsers/gguf.d.ts +39 -0
- package/types/lib/parsers/gguf.d.ts.map +1 -0
- package/types/lib/parsers/gitAiNotes.d.ts +15 -0
- package/types/lib/parsers/gitAiNotes.d.ts.map +1 -0
- package/types/lib/parsers/gitmodules.d.ts +88 -0
- package/types/lib/parsers/gitmodules.d.ts.map +1 -0
- package/types/lib/parsers/htmlExtract.d.ts +34 -0
- package/types/lib/parsers/htmlExtract.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts +153 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts +155 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -0
- package/types/lib/parsers/iri.d.ts +68 -0
- package/types/lib/parsers/iri.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +33 -0
- package/types/lib/parsers/npmrc.d.ts.map +1 -0
- package/types/lib/parsers/ollama.d.ts +22 -0
- package/types/lib/parsers/ollama.d.ts.map +1 -0
- package/types/lib/parsers/xml.d.ts +47 -0
- package/types/lib/parsers/xml.d.ts.map +1 -0
- package/types/lib/server/server.d.ts +51 -0
- package/types/lib/server/server.d.ts.map +1 -0
- package/types/lib/stages/postgen/annotator.d.ts +36 -0
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -0
- package/types/lib/stages/postgen/auditBom.d.ts +92 -0
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/postgen.d.ts +59 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
- package/types/lib/stages/postgen/sortBom.d.ts +34 -0
- package/types/lib/stages/postgen/sortBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts +71 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -0
- package/types/lib/stages/pregen/envAudit.d.ts +14 -0
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
- package/types/lib/stages/pregen/pregen.d.ts +59 -0
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts +47 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +9 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts +46 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/index.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts +14 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/link.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/node.d.ts +112 -0
- package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts +27 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts +36 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts +20 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +54 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts +13 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +6 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +35 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -0
- package/types/lib/validator/bomValidator.d.ts +40 -0
- package/types/lib/validator/bomValidator.d.ts.map +1 -0
- package/types/lib/validator/complianceEngine.d.ts +72 -0
- package/types/lib/validator/complianceEngine.d.ts.map +1 -0
- package/types/lib/validator/complianceRules.d.ts +61 -0
- package/types/lib/validator/complianceRules.d.ts.map +1 -0
- package/types/lib/validator/index.d.ts +101 -0
- package/types/lib/validator/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/annotations.d.ts +37 -0
- package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
- package/types/lib/validator/reporters/console.d.ts +34 -0
- package/types/lib/validator/reporters/console.d.ts.map +1 -0
- package/types/lib/validator/reporters/index.d.ts +30 -0
- package/types/lib/validator/reporters/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/json.d.ts +11 -0
- package/types/lib/validator/reporters/json.d.ts.map +1 -0
- package/types/lib/validator/reporters/sarif.d.ts +22 -0
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
- package/mod.d.ts +0 -7
- package/mod.js +0 -22
package/lib/core/ui.js
ADDED
|
@@ -0,0 +1,920 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live-region CLI UI controller.
|
|
3
|
+
*
|
|
4
|
+
* Layer 0: imports nothing outside `lib/core`. The mechanism is a single live
|
|
5
|
+
* region: a block of lines rewritten in place by rewinding only by the previous
|
|
6
|
+
* frame's height. The block never ends with a newline until `stop()`, so every
|
|
7
|
+
* update is a single `write` and a crashed process can never leave a torn frame
|
|
8
|
+
* on screen.
|
|
9
|
+
*
|
|
10
|
+
* The UX layer on top is the phase model: `ui.phase(label)` returns a handle
|
|
11
|
+
* whose `detail`/`progress`/`succeed`/`fail`/`skip` calls drive the region. In
|
|
12
|
+
* non-interactive mode the same calls emit at most one plain line per state
|
|
13
|
+
* transition, so callers never branch on `ui.interactive`.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import process from "node:process";
|
|
17
|
+
import { formatWithOptions, inspect } from "node:util";
|
|
18
|
+
|
|
19
|
+
import { readEnvironmentVariable } from "./activity.js";
|
|
20
|
+
import { diagnosticStream, TRACE_MODE, traceLog } from "./logger.js";
|
|
21
|
+
import { stringWidth, stripAnsi } from "./text.js";
|
|
22
|
+
|
|
23
|
+
// Frame interval, and the floor on how often detail/progress updates redraw.
|
|
24
|
+
// Updates arriving faster than this are coalesced by the refresh timer.
|
|
25
|
+
const REFRESH_MS = 80;
|
|
26
|
+
|
|
27
|
+
// Glyph sets. Unicode support is a separate capability from color: a redirected
|
|
28
|
+
// UTF-8 log file takes the glyphs happily, while a legacy Windows console
|
|
29
|
+
// renders them as boxes whether or not it does color.
|
|
30
|
+
const GLYPHS = {
|
|
31
|
+
unicode: {
|
|
32
|
+
frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
33
|
+
ellipsis: "…",
|
|
34
|
+
succeeded: "✔",
|
|
35
|
+
failed: "✖",
|
|
36
|
+
skipped: "→",
|
|
37
|
+
},
|
|
38
|
+
ascii: {
|
|
39
|
+
// The frames lib/audit/progress.js used before this module existed.
|
|
40
|
+
frames: ["-", "\\", "|", "/"],
|
|
41
|
+
ellipsis: "...",
|
|
42
|
+
succeeded: "+",
|
|
43
|
+
failed: "x",
|
|
44
|
+
skipped: "~",
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Semantic colors — only emitted when `color` is true.
|
|
49
|
+
const COLOR = {
|
|
50
|
+
dim: (s) => `\x1b[2m${s}\x1b[22m`,
|
|
51
|
+
green: (s) => `\x1b[32m${s}\x1b[39m`,
|
|
52
|
+
red: (s) => `\x1b[31m${s}\x1b[39m`,
|
|
53
|
+
yellow: (s) => `\x1b[33m${s}\x1b[39m`,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const HIDE_CURSOR = "\x1b[?25l";
|
|
57
|
+
const SHOW_CURSOR = "\x1b[?25h";
|
|
58
|
+
const CLEAR_LINE = "\r\x1b[2K";
|
|
59
|
+
const CURSOR_UP_CLEAR = "\x1b[1A\x1b[2K";
|
|
60
|
+
|
|
61
|
+
const LEVEL_SILENT = 0;
|
|
62
|
+
const LEVEL_NORMAL = 1;
|
|
63
|
+
const LEVEL_VERBOSE = 2;
|
|
64
|
+
const LEVEL_DEBUG = 3;
|
|
65
|
+
|
|
66
|
+
const LEVEL_NAMES = new Map([
|
|
67
|
+
["silent", LEVEL_SILENT],
|
|
68
|
+
["quiet", LEVEL_SILENT],
|
|
69
|
+
["error", LEVEL_SILENT],
|
|
70
|
+
["normal", LEVEL_NORMAL],
|
|
71
|
+
["info", LEVEL_NORMAL],
|
|
72
|
+
["warn", LEVEL_NORMAL],
|
|
73
|
+
["verbose", LEVEL_VERBOSE],
|
|
74
|
+
["debug", LEVEL_DEBUG],
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
// Phase status → the color and log level its committed line uses. The marker
|
|
78
|
+
// glyph comes from the resolved glyph set.
|
|
79
|
+
const PHASE_OUTCOMES = {
|
|
80
|
+
succeeded: { color: COLOR.green, level: "info" },
|
|
81
|
+
failed: { color: COLOR.red, level: "error" },
|
|
82
|
+
skipped: { color: COLOR.yellow, level: "warn" },
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Resolve a capability snapshot for the live region. Re-runs cleanly when given
|
|
87
|
+
* `overrides` (used by tests with a fake stream and a captive env object).
|
|
88
|
+
*
|
|
89
|
+
* `FORCE_COLOR` non-empty wins over `isatty()`; `TERM` in {dumb, unknown}
|
|
90
|
+
* forces non-interactive; `NO_COLOR` non-empty disables color but not the live
|
|
91
|
+
* region; `CDXGEN_NO_PROGRESS` and `CI=true` disable the live region. A worker
|
|
92
|
+
* thread needs no special case: its stdio is a pipe, so `isTTY` is undefined.
|
|
93
|
+
*
|
|
94
|
+
* @param {object} [overrides] Overrides for stream, env, and resolved flags
|
|
95
|
+
* @returns {{stream: object, interactive: boolean, color: boolean, unicode: boolean, glyphs: object, columns: () => number, rows: () => number}} Capability snapshot
|
|
96
|
+
*/
|
|
97
|
+
export function detectCapabilities(overrides = {}) {
|
|
98
|
+
// `CDXGEN_LOG_STREAM=stdout` is the documented escape hatch for callers that
|
|
99
|
+
// scraped v12's stdout. Resolving the destination here rather than pinning
|
|
100
|
+
// stderr is what makes it apply to the region, the banners and the tables
|
|
101
|
+
// instead of only to the thought and trace logs.
|
|
102
|
+
const stream = overrides.stream || diagnosticStream;
|
|
103
|
+
const env = overrides.env;
|
|
104
|
+
const read = (name) => (env ? env[name] : readEnvironmentVariable(name));
|
|
105
|
+
const isSet = (name) => {
|
|
106
|
+
const value = read(name);
|
|
107
|
+
return value !== undefined && value !== null && value !== "";
|
|
108
|
+
};
|
|
109
|
+
const term = `${read("TERM") || ""}`.toLowerCase();
|
|
110
|
+
const isDumbTerm = term === "dumb" || term === "unknown";
|
|
111
|
+
const ci = `${read("CI") || ""}`.toLowerCase() === "true";
|
|
112
|
+
const noProgressEnv = `${read("CDXGEN_NO_PROGRESS") || ""}`.toLowerCase();
|
|
113
|
+
const noProgress =
|
|
114
|
+
overrides.noProgress === true ||
|
|
115
|
+
noProgressEnv === "true" ||
|
|
116
|
+
noProgressEnv === "1";
|
|
117
|
+
const interactive =
|
|
118
|
+
overrides.interactive !== undefined
|
|
119
|
+
? !!overrides.interactive
|
|
120
|
+
: stream?.isTTY === true && !isDumbTerm && !ci && !noProgress;
|
|
121
|
+
const color =
|
|
122
|
+
overrides.color !== undefined
|
|
123
|
+
? !!overrides.color
|
|
124
|
+
: isSet("FORCE_COLOR") || (interactive && !isSet("NO_COLOR"));
|
|
125
|
+
// Legacy Windows consoles draw braille and box-drawing glyphs as boxes.
|
|
126
|
+
// Windows Terminal and VS Code advertise themselves, and every other platform
|
|
127
|
+
// is assumed UTF-8 capable. CDXGEN_UNICODE overrides the guess either way.
|
|
128
|
+
const unicodeEnv = `${read("CDXGEN_UNICODE") || ""}`.toLowerCase();
|
|
129
|
+
let unicode;
|
|
130
|
+
if (overrides.unicode !== undefined) {
|
|
131
|
+
unicode = !!overrides.unicode;
|
|
132
|
+
} else if (unicodeEnv === "true" || unicodeEnv === "1") {
|
|
133
|
+
unicode = true;
|
|
134
|
+
} else if (unicodeEnv === "false" || unicodeEnv === "0") {
|
|
135
|
+
unicode = false;
|
|
136
|
+
} else {
|
|
137
|
+
unicode =
|
|
138
|
+
process.platform !== "win32" ||
|
|
139
|
+
isSet("WT_SESSION") ||
|
|
140
|
+
read("TERM_PROGRAM") === "vscode";
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
stream,
|
|
144
|
+
interactive,
|
|
145
|
+
color,
|
|
146
|
+
unicode,
|
|
147
|
+
glyphs: unicode ? GLYPHS.unicode : GLYPHS.ascii,
|
|
148
|
+
// Read per frame so a terminal resize self-corrects on the next tick.
|
|
149
|
+
columns: () => (Number(stream?.columns) > 0 ? Number(stream.columns) : 80),
|
|
150
|
+
rows: () => (Number(stream?.rows) > 0 ? Number(stream.rows) : 25),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Resolve the verbosity level. Existing debug env vars win over the flag so no
|
|
156
|
+
* user's CI breaks.
|
|
157
|
+
*
|
|
158
|
+
* @param {number|string} [explicit] Flag-derived level
|
|
159
|
+
* @returns {number} Level in 0..3
|
|
160
|
+
*/
|
|
161
|
+
function resolveLevel(explicit) {
|
|
162
|
+
const named = LEVEL_NAMES.get(
|
|
163
|
+
`${readEnvironmentVariable("CDXGEN_LOG_LEVEL") || ""}`.toLowerCase(),
|
|
164
|
+
);
|
|
165
|
+
if (named !== undefined) {
|
|
166
|
+
return named;
|
|
167
|
+
}
|
|
168
|
+
if (
|
|
169
|
+
readEnvironmentVariable("CDXGEN_DEBUG_MODE") === "debug" ||
|
|
170
|
+
readEnvironmentVariable("SCAN_DEBUG_MODE") === "debug"
|
|
171
|
+
) {
|
|
172
|
+
return LEVEL_DEBUG;
|
|
173
|
+
}
|
|
174
|
+
if (explicit === undefined || explicit === null) {
|
|
175
|
+
return LEVEL_NORMAL;
|
|
176
|
+
}
|
|
177
|
+
const numeric = Number(explicit);
|
|
178
|
+
if (!Number.isFinite(numeric)) {
|
|
179
|
+
return LEVEL_NAMES.get(`${explicit}`.toLowerCase()) ?? LEVEL_NORMAL;
|
|
180
|
+
}
|
|
181
|
+
return Math.max(LEVEL_SILENT, Math.min(LEVEL_DEBUG, Math.round(numeric)));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Resolve the log serialization format. The env var wins over the flag.
|
|
186
|
+
*
|
|
187
|
+
* @param {string} [explicit] Flag-derived format
|
|
188
|
+
* @returns {("text"|"json")} Resolved format
|
|
189
|
+
*/
|
|
190
|
+
function resolveFormat(explicit) {
|
|
191
|
+
const fromEnv =
|
|
192
|
+
`${readEnvironmentVariable("CDXGEN_LOG_FORMAT") || ""}`.toLowerCase();
|
|
193
|
+
if (fromEnv === "json" || fromEnv === "text") {
|
|
194
|
+
return fromEnv;
|
|
195
|
+
}
|
|
196
|
+
return `${explicit || ""}`.toLowerCase() === "json" ? "json" : "text";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Select a spinner frame from elapsed wall-clock time, so the animation runs at
|
|
201
|
+
* the right rate however often refresh fires and re-rendering during a print
|
|
202
|
+
* never advances it.
|
|
203
|
+
*
|
|
204
|
+
* @param {number} startedAt Phase start timestamp
|
|
205
|
+
* @param {number} now Current timestamp
|
|
206
|
+
* @param {string[]} frames Frame set
|
|
207
|
+
* @returns {string} The frame for this instant
|
|
208
|
+
*/
|
|
209
|
+
function spinnerFrame(startedAt, now, frames) {
|
|
210
|
+
const elapsed = Math.max(0, now - startedAt);
|
|
211
|
+
return frames[Math.floor(elapsed / REFRESH_MS) % frames.length];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Render a determinate progress bar.
|
|
216
|
+
*
|
|
217
|
+
* @param {number} done Completed units
|
|
218
|
+
* @param {number} total Total units
|
|
219
|
+
* @param {number} width Total bar width including brackets
|
|
220
|
+
* @returns {string} Rendered bar, or "" when total is not positive
|
|
221
|
+
*/
|
|
222
|
+
function renderBar(done, total, width) {
|
|
223
|
+
const safeTotal = Number(total) > 0 ? Number(total) : 0;
|
|
224
|
+
if (safeTotal <= 0) {
|
|
225
|
+
return "";
|
|
226
|
+
}
|
|
227
|
+
const safeDone = Math.max(0, Math.min(safeTotal, Number(done) || 0));
|
|
228
|
+
const innerWidth = Math.max(4, width - 2);
|
|
229
|
+
const filled = Math.round((safeDone / safeTotal) * innerWidth);
|
|
230
|
+
return `[${"#".repeat(filled)}${"-".repeat(innerWidth - filled)}] ${safeDone}/${safeTotal}`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Truncate from the left, keeping the tail.
|
|
235
|
+
*
|
|
236
|
+
* Phase detail is usually a path, where the distinguishing part is the end. Two
|
|
237
|
+
* hundred files under one long temp directory all truncate to the same prefix,
|
|
238
|
+
* which tells the reader nothing about what is in flight.
|
|
239
|
+
*
|
|
240
|
+
* @param {string} text Input text
|
|
241
|
+
* @param {number} maxWidth Maximum display width
|
|
242
|
+
* @param {string} ellipsis Marker for the elided head
|
|
243
|
+
* @returns {string} Text fitting within maxWidth
|
|
244
|
+
*/
|
|
245
|
+
function truncateHead(text, maxWidth, ellipsis) {
|
|
246
|
+
if (stringWidth(text) <= maxWidth) {
|
|
247
|
+
return text;
|
|
248
|
+
}
|
|
249
|
+
const budget = maxWidth - stringWidth(ellipsis);
|
|
250
|
+
const chars = [...text];
|
|
251
|
+
let width = 0;
|
|
252
|
+
let start = chars.length;
|
|
253
|
+
while (start > 0) {
|
|
254
|
+
const charWidth = stringWidth(chars[start - 1]);
|
|
255
|
+
if (width + charWidth > budget) {
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
width += charWidth;
|
|
259
|
+
start -= 1;
|
|
260
|
+
}
|
|
261
|
+
return `${ellipsis}${chars.slice(start).join("")}`;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Format console-style arguments into a single line.
|
|
266
|
+
*
|
|
267
|
+
* @param {unknown[]} args Arguments
|
|
268
|
+
* @returns {string} Formatted line
|
|
269
|
+
*/
|
|
270
|
+
function formatArgs(args) {
|
|
271
|
+
if (args.length === 0) {
|
|
272
|
+
return "";
|
|
273
|
+
}
|
|
274
|
+
return args
|
|
275
|
+
.map((arg) =>
|
|
276
|
+
typeof arg === "string"
|
|
277
|
+
? arg
|
|
278
|
+
: inspect(arg, {
|
|
279
|
+
colors: false,
|
|
280
|
+
breakLength: Number.POSITIVE_INFINITY,
|
|
281
|
+
}),
|
|
282
|
+
)
|
|
283
|
+
.join(" ");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Create a live-region controller.
|
|
288
|
+
*
|
|
289
|
+
* @param {object} [options] Controller options
|
|
290
|
+
* @param {object} [options.stream] Writable stream (default: the diagnostic stream, stderr unless `CDXGEN_LOG_STREAM=stdout`)
|
|
291
|
+
* @param {number|string} [options.level] Verbosity ladder 0..3
|
|
292
|
+
* @param {("text"|"json")} [options.format] Log serialization format
|
|
293
|
+
* @param {boolean} [options.noProgress] Force-disable the live region
|
|
294
|
+
* @param {boolean} [options.color] Force color on or off
|
|
295
|
+
* @param {boolean} [options.interactive] Force the live region on or off
|
|
296
|
+
* @param {() => number} [options.now] Clock, injectable for tests
|
|
297
|
+
* @returns {object} Controller
|
|
298
|
+
*/
|
|
299
|
+
export function createUi(options = {}) {
|
|
300
|
+
let caps = detectCapabilities(options);
|
|
301
|
+
let level = resolveLevel(options.level);
|
|
302
|
+
let format = resolveFormat(options.format);
|
|
303
|
+
const now = typeof options.now === "function" ? options.now : Date.now;
|
|
304
|
+
|
|
305
|
+
// JSON log format disables the live region entirely: NDJSON to stderr only.
|
|
306
|
+
const isLive = () => caps.interactive && format !== "json";
|
|
307
|
+
|
|
308
|
+
/** @type {object[]} Phases currently running, in start order. */
|
|
309
|
+
const running = [];
|
|
310
|
+
let lastHeight = 0;
|
|
311
|
+
let lastRenderAt = 0;
|
|
312
|
+
let dirty = false;
|
|
313
|
+
let stopped = false;
|
|
314
|
+
let interval = null;
|
|
315
|
+
let cursorHidden = false;
|
|
316
|
+
let signalsInstalled = false;
|
|
317
|
+
|
|
318
|
+
function write(chunk) {
|
|
319
|
+
const stream = caps.stream;
|
|
320
|
+
if (!chunk || typeof stream?.write !== "function") {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
try {
|
|
324
|
+
stream.write(chunk);
|
|
325
|
+
} catch (err) {
|
|
326
|
+
// A consumer that closed the pipe (`| head`) must not produce a stack.
|
|
327
|
+
if (err?.code !== "EPIPE") {
|
|
328
|
+
throw err;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function rewind() {
|
|
334
|
+
if (lastHeight <= 0) {
|
|
335
|
+
return "";
|
|
336
|
+
}
|
|
337
|
+
// The cursor sits on the block's last line, so move up height-1 times.
|
|
338
|
+
return `${CLEAR_LINE}${CURSOR_UP_CLEAR.repeat(lastHeight - 1)}`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function renderPhaseRow(phase, at) {
|
|
342
|
+
const { frames, ellipsis } = caps.glyphs;
|
|
343
|
+
let row = `${spinnerFrame(phase.startedAt, at, frames)} ${phase.label}`;
|
|
344
|
+
if (phase.total > 0) {
|
|
345
|
+
const barWidth = Math.min(
|
|
346
|
+
20,
|
|
347
|
+
Math.max(6, caps.columns() - stringWidth(row) - 16),
|
|
348
|
+
);
|
|
349
|
+
row += ` ${renderBar(phase.done, phase.total, barWidth)}`;
|
|
350
|
+
}
|
|
351
|
+
if (phase.detailText) {
|
|
352
|
+
const separator = caps.unicode ? " — " : " - ";
|
|
353
|
+
const remaining = Math.max(
|
|
354
|
+
8,
|
|
355
|
+
caps.columns() - stringWidth(row) - stringWidth(separator),
|
|
356
|
+
);
|
|
357
|
+
row += `${separator}${truncateHead(phase.detailText, remaining, ellipsis)}`;
|
|
358
|
+
}
|
|
359
|
+
return row;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Build the current frame, clamped to the terminal height. Clamping is not
|
|
364
|
+
* cosmetic: a frame taller than the screen scrolls the terminal, after which
|
|
365
|
+
* the rewind count under-shoots and smears output for the rest of the run.
|
|
366
|
+
*
|
|
367
|
+
* @returns {{body: string, height: number}} Frame body and its line count
|
|
368
|
+
*/
|
|
369
|
+
function buildFrame() {
|
|
370
|
+
if (!isLive() || running.length === 0) {
|
|
371
|
+
return { body: "", height: 0 };
|
|
372
|
+
}
|
|
373
|
+
const at = now();
|
|
374
|
+
const lines = running.map((phase) => renderPhaseRow(phase, at));
|
|
375
|
+
const maxLines = Math.max(1, caps.rows() - 1);
|
|
376
|
+
if (lines.length <= maxLines) {
|
|
377
|
+
return { body: lines.join("\n"), height: lines.length };
|
|
378
|
+
}
|
|
379
|
+
const kept = lines.slice(0, Math.max(1, maxLines - 1));
|
|
380
|
+
kept.push(`${caps.glyphs.ellipsis} and ${lines.length - kept.length} more`);
|
|
381
|
+
return { body: kept.join("\n"), height: kept.length };
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function render() {
|
|
385
|
+
if (!isLive()) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
const { body, height } = buildFrame();
|
|
389
|
+
write(rewind() + body);
|
|
390
|
+
lastHeight = height;
|
|
391
|
+
lastRenderAt = now();
|
|
392
|
+
dirty = false;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Request a redraw. State transitions render at once; detail and progress
|
|
397
|
+
* updates are coalesced to one frame per REFRESH_MS, so a caller reporting
|
|
398
|
+
* per-file progress in a tight loop costs one write per frame, not per file.
|
|
399
|
+
*
|
|
400
|
+
* @param {boolean} [force] Render immediately regardless of the throttle
|
|
401
|
+
*/
|
|
402
|
+
function requestRender(force = false) {
|
|
403
|
+
if (!isLive()) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
dirty = true;
|
|
407
|
+
if (force || now() - lastRenderAt >= REFRESH_MS) {
|
|
408
|
+
render();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function tick() {
|
|
413
|
+
if (dirty || running.length > 0) {
|
|
414
|
+
render();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function startTimer() {
|
|
419
|
+
if (interval || stopped || !isLive()) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (!cursorHidden) {
|
|
423
|
+
write(HIDE_CURSOR);
|
|
424
|
+
cursorHidden = true;
|
|
425
|
+
}
|
|
426
|
+
// unref() so a forgotten stop() can never hold the process open.
|
|
427
|
+
interval = setInterval(tick, REFRESH_MS);
|
|
428
|
+
interval.unref?.();
|
|
429
|
+
installSignalHandlers();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function stopTimer() {
|
|
433
|
+
if (interval) {
|
|
434
|
+
clearInterval(interval);
|
|
435
|
+
interval = null;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function showCursor() {
|
|
440
|
+
if (cursorHidden) {
|
|
441
|
+
write(SHOW_CURSOR);
|
|
442
|
+
cursorHidden = false;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function onExit() {
|
|
447
|
+
stopTimer();
|
|
448
|
+
showCursor();
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Restore the terminal and then let the signal do what it would have done.
|
|
453
|
+
* Registering a listener suppresses Node's default terminate-on-SIGINT, so
|
|
454
|
+
* the signal has to be re-raised or Ctrl-C would stop killing long scans.
|
|
455
|
+
*
|
|
456
|
+
* @param {NodeJS.Signals} signal The received signal
|
|
457
|
+
*/
|
|
458
|
+
function onSignal(signal) {
|
|
459
|
+
removeSignalHandlers();
|
|
460
|
+
stopTimer();
|
|
461
|
+
showCursor();
|
|
462
|
+
process.kill(process.pid, signal);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function installSignalHandlers() {
|
|
466
|
+
if (signalsInstalled) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
signalsInstalled = true;
|
|
470
|
+
process.on("SIGINT", onSignal);
|
|
471
|
+
process.on("SIGTERM", onSignal);
|
|
472
|
+
process.on("exit", onExit);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function removeSignalHandlers() {
|
|
476
|
+
if (!signalsInstalled) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
signalsInstalled = false;
|
|
480
|
+
process.off("SIGINT", onSignal);
|
|
481
|
+
process.off("SIGTERM", onSignal);
|
|
482
|
+
process.off("exit", onExit);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Print a line above the live region. The line becomes permanent scrollback
|
|
487
|
+
* and the region is redrawn below it, in exactly one `write` so a frame is
|
|
488
|
+
* never left torn.
|
|
489
|
+
*
|
|
490
|
+
* @param {string} text Line to print, without a trailing newline
|
|
491
|
+
*/
|
|
492
|
+
function print(text) {
|
|
493
|
+
const line = `${text ?? ""}`;
|
|
494
|
+
if (!isLive()) {
|
|
495
|
+
write(`${line}\n`);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const { body, height } = buildFrame();
|
|
499
|
+
write(`${rewind()}${line}\n${body}`);
|
|
500
|
+
lastHeight = height;
|
|
501
|
+
lastRenderAt = now();
|
|
502
|
+
dirty = false;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Emit one leveled record: NDJSON when the json format is selected, otherwise
|
|
507
|
+
* a line through the live-region-aware print path.
|
|
508
|
+
*
|
|
509
|
+
* @param {string} levelName Record level
|
|
510
|
+
* @param {string} message Message text
|
|
511
|
+
*/
|
|
512
|
+
function writeLine(levelName, message) {
|
|
513
|
+
if (format === "json") {
|
|
514
|
+
write(
|
|
515
|
+
`${JSON.stringify({
|
|
516
|
+
ts: new Date().toISOString(),
|
|
517
|
+
level: levelName,
|
|
518
|
+
msg: message,
|
|
519
|
+
})}\n`,
|
|
520
|
+
);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
print(message);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Pause the live region, run `fn`, then redraw. Used when a spawned process
|
|
528
|
+
* must own the terminal.
|
|
529
|
+
*
|
|
530
|
+
* @param {() => any} fn Work to run with the region cleared
|
|
531
|
+
* @returns {any} Result of `fn`
|
|
532
|
+
*/
|
|
533
|
+
function pause(fn) {
|
|
534
|
+
if (!isLive()) {
|
|
535
|
+
return fn();
|
|
536
|
+
}
|
|
537
|
+
write(rewind());
|
|
538
|
+
lastHeight = 0;
|
|
539
|
+
try {
|
|
540
|
+
return fn();
|
|
541
|
+
} finally {
|
|
542
|
+
render();
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Mirror a phase transition onto the trace stream.
|
|
548
|
+
*
|
|
549
|
+
* The live region is a terminal affordance, so a piped consumer such as the
|
|
550
|
+
* cdxui terminal UI would otherwise have to scrape formatted lines to learn
|
|
551
|
+
* what cdxgen is doing. Emitting the phase model structurally lets it render
|
|
552
|
+
* its own progress. `progress` transitions are throttled to the frame
|
|
553
|
+
* interval so a per-file loop costs one event per frame, not one per file.
|
|
554
|
+
*
|
|
555
|
+
* @param {object} handle Phase handle
|
|
556
|
+
* @param {string} state One of started, progress, succeeded, failed, skipped
|
|
557
|
+
*/
|
|
558
|
+
function tracePhase(handle, state) {
|
|
559
|
+
if (!TRACE_MODE) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
const at = now();
|
|
563
|
+
if (state === "progress") {
|
|
564
|
+
if (at - (handle.tracedAt || 0) < REFRESH_MS) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
handle.tracedAt = at;
|
|
568
|
+
}
|
|
569
|
+
traceLog("phase", {
|
|
570
|
+
phase: handle.label,
|
|
571
|
+
state,
|
|
572
|
+
detail: handle.detailText ?? undefined,
|
|
573
|
+
note: handle.note ?? undefined,
|
|
574
|
+
done: handle.total > 0 ? handle.done : undefined,
|
|
575
|
+
total: handle.total > 0 ? handle.total : undefined,
|
|
576
|
+
elapsedMs: at - handle.startedAt,
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
function commitPhase(phase) {
|
|
581
|
+
const outcome = PHASE_OUTCOMES[phase.status] || PHASE_OUTCOMES.succeeded;
|
|
582
|
+
const glyph = caps.glyphs[phase.status] || caps.glyphs.succeeded;
|
|
583
|
+
const elapsed = `${((now() - phase.startedAt) / 1000).toFixed(1)}s`;
|
|
584
|
+
const parts = [
|
|
585
|
+
phase.label,
|
|
586
|
+
phase.note,
|
|
587
|
+
caps.color ? COLOR.dim(elapsed) : elapsed,
|
|
588
|
+
];
|
|
589
|
+
const marker = caps.color ? outcome.color(glyph) : glyph;
|
|
590
|
+
const message = `${marker} ${parts.filter(Boolean).join(" ")}`;
|
|
591
|
+
writeLine(outcome.level, caps.color ? message : stripAnsi(message));
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Begin a named phase.
|
|
596
|
+
*
|
|
597
|
+
* @param {string} label Phase label
|
|
598
|
+
* @returns {object} Phase handle
|
|
599
|
+
*/
|
|
600
|
+
function phase(label) {
|
|
601
|
+
const handle = {
|
|
602
|
+
label: label || "working",
|
|
603
|
+
detailText: null,
|
|
604
|
+
done: 0,
|
|
605
|
+
total: 0,
|
|
606
|
+
status: "running",
|
|
607
|
+
startedAt: now(),
|
|
608
|
+
note: null,
|
|
609
|
+
committed: false,
|
|
610
|
+
tracedAt: 0,
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Replace the trailing detail text on this phase's row.
|
|
614
|
+
*
|
|
615
|
+
* @param {string} text Detail text
|
|
616
|
+
* @returns {object} This handle
|
|
617
|
+
*/
|
|
618
|
+
detail(text) {
|
|
619
|
+
if (!this.committed) {
|
|
620
|
+
this.detailText = text ? `${text}` : null;
|
|
621
|
+
tracePhase(this, "progress");
|
|
622
|
+
requestRender();
|
|
623
|
+
}
|
|
624
|
+
return this;
|
|
625
|
+
},
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Switch this phase's row to a progress bar.
|
|
629
|
+
*
|
|
630
|
+
* @param {number} done Completed units
|
|
631
|
+
* @param {number} total Total units
|
|
632
|
+
* @returns {object} This handle
|
|
633
|
+
*/
|
|
634
|
+
progress(done, total) {
|
|
635
|
+
if (!this.committed) {
|
|
636
|
+
this.done = Number(done) || 0;
|
|
637
|
+
this.total = Number(total) || 0;
|
|
638
|
+
tracePhase(this, "progress");
|
|
639
|
+
requestRender();
|
|
640
|
+
}
|
|
641
|
+
return this;
|
|
642
|
+
},
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Commit this phase as succeeded.
|
|
646
|
+
*
|
|
647
|
+
* @param {string} [summary] One-line outcome summary
|
|
648
|
+
*/
|
|
649
|
+
succeed(summary) {
|
|
650
|
+
finish(this, "succeeded", summary);
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Commit this phase as failed.
|
|
655
|
+
*
|
|
656
|
+
* @param {Error|string} [err] Failure cause
|
|
657
|
+
*/
|
|
658
|
+
fail(err) {
|
|
659
|
+
finish(
|
|
660
|
+
this,
|
|
661
|
+
"failed",
|
|
662
|
+
err instanceof Error ? err.message : `${err ?? "failed"}`,
|
|
663
|
+
);
|
|
664
|
+
},
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Commit this phase as skipped.
|
|
668
|
+
*
|
|
669
|
+
* @param {string} [reason] Why the phase was skipped
|
|
670
|
+
*/
|
|
671
|
+
skip(reason) {
|
|
672
|
+
finish(this, "skipped", reason || "skipped");
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
running.push(handle);
|
|
676
|
+
tracePhase(handle, "started");
|
|
677
|
+
startTimer();
|
|
678
|
+
requestRender(true);
|
|
679
|
+
return handle;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function finish(handle, status, note) {
|
|
683
|
+
if (handle.committed) {
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
handle.committed = true;
|
|
687
|
+
handle.status = status;
|
|
688
|
+
handle.note = note ? `${note}` : null;
|
|
689
|
+
tracePhase(handle, status);
|
|
690
|
+
const index = running.indexOf(handle);
|
|
691
|
+
if (index >= 0) {
|
|
692
|
+
running.splice(index, 1);
|
|
693
|
+
}
|
|
694
|
+
if (running.length === 0 && isLive()) {
|
|
695
|
+
// Clear the region so the committed line is not drawn over a stale frame.
|
|
696
|
+
write(rewind());
|
|
697
|
+
lastHeight = 0;
|
|
698
|
+
}
|
|
699
|
+
if (level >= LEVEL_NORMAL || status === "failed") {
|
|
700
|
+
commitPhase(handle);
|
|
701
|
+
}
|
|
702
|
+
if (running.length === 0) {
|
|
703
|
+
stopTimer();
|
|
704
|
+
} else {
|
|
705
|
+
requestRender(true);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Stop the controller: halt the timer, commit the final frame, restore the
|
|
711
|
+
* cursor, and detach signal handlers. Safe to call more than once.
|
|
712
|
+
*/
|
|
713
|
+
function stop() {
|
|
714
|
+
if (stopped) {
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
stopped = true;
|
|
718
|
+
stopTimer();
|
|
719
|
+
if (isLive()) {
|
|
720
|
+
// The final frame is committed with the one newline the region owes.
|
|
721
|
+
const { body } = buildFrame();
|
|
722
|
+
write(body ? `${rewind()}${body}\n` : rewind());
|
|
723
|
+
lastHeight = 0;
|
|
724
|
+
}
|
|
725
|
+
showCursor();
|
|
726
|
+
removeSignalHandlers();
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Re-resolve capabilities, level, and format. Used by the CLI once flags are
|
|
731
|
+
* parsed, and by the server to force non-interactive NDJSON.
|
|
732
|
+
*
|
|
733
|
+
* @param {object} [next] Same shape as the constructor options
|
|
734
|
+
*/
|
|
735
|
+
function configure(next = {}) {
|
|
736
|
+
caps = detectCapabilities({ ...next, stream: next.stream || caps.stream });
|
|
737
|
+
if (next.level !== undefined) {
|
|
738
|
+
level = resolveLevel(next.level);
|
|
739
|
+
}
|
|
740
|
+
if (next.format !== undefined) {
|
|
741
|
+
format = resolveFormat(next.format);
|
|
742
|
+
}
|
|
743
|
+
if (!isLive()) {
|
|
744
|
+
stopTimer();
|
|
745
|
+
showCursor();
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
const logApi = {
|
|
750
|
+
/**
|
|
751
|
+
* Log an error. Always emitted, at every level.
|
|
752
|
+
*
|
|
753
|
+
* @param {...unknown} args Message parts
|
|
754
|
+
*/
|
|
755
|
+
error(...args) {
|
|
756
|
+
writeLine("error", formatArgs(args));
|
|
757
|
+
},
|
|
758
|
+
/**
|
|
759
|
+
* Log a warning.
|
|
760
|
+
*
|
|
761
|
+
* @param {...unknown} args Message parts
|
|
762
|
+
*/
|
|
763
|
+
warn(...args) {
|
|
764
|
+
if (level >= LEVEL_NORMAL) {
|
|
765
|
+
writeLine("warn", formatArgs(args));
|
|
766
|
+
}
|
|
767
|
+
},
|
|
768
|
+
/**
|
|
769
|
+
* Log an informational message.
|
|
770
|
+
*
|
|
771
|
+
* @param {...unknown} args Message parts
|
|
772
|
+
*/
|
|
773
|
+
info(...args) {
|
|
774
|
+
if (level >= LEVEL_NORMAL) {
|
|
775
|
+
writeLine("info", formatArgs(args));
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
/**
|
|
779
|
+
* Log a debug message. Shown from verbosity level 2.
|
|
780
|
+
*
|
|
781
|
+
* @param {...unknown} args Message parts
|
|
782
|
+
*/
|
|
783
|
+
debug(...args) {
|
|
784
|
+
if (level >= LEVEL_VERBOSE) {
|
|
785
|
+
writeLine("debug", formatArgs(args));
|
|
786
|
+
}
|
|
787
|
+
},
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
return {
|
|
791
|
+
print,
|
|
792
|
+
writeLine,
|
|
793
|
+
phase,
|
|
794
|
+
pause,
|
|
795
|
+
stop,
|
|
796
|
+
configure,
|
|
797
|
+
log: logApi,
|
|
798
|
+
get interactive() {
|
|
799
|
+
return isLive();
|
|
800
|
+
},
|
|
801
|
+
get color() {
|
|
802
|
+
return caps.color;
|
|
803
|
+
},
|
|
804
|
+
get level() {
|
|
805
|
+
return level;
|
|
806
|
+
},
|
|
807
|
+
get format() {
|
|
808
|
+
return format;
|
|
809
|
+
},
|
|
810
|
+
get stream() {
|
|
811
|
+
return caps.stream;
|
|
812
|
+
},
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Process-wide default live-region UI controller instance. Library code imports
|
|
818
|
+
* this directly; the CLI reconfigures it once flags are parsed.
|
|
819
|
+
*
|
|
820
|
+
* @type {Object}
|
|
821
|
+
*/
|
|
822
|
+
export const ui = createUi({});
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Convenience facade exposing leveled log methods (`error`, `warn`, `info`,
|
|
826
|
+
* `debug`) that delegate to the default controller instance.
|
|
827
|
+
*
|
|
828
|
+
* @type {Object}
|
|
829
|
+
*/
|
|
830
|
+
export const log = {
|
|
831
|
+
/**
|
|
832
|
+
* Log an error through the default controller.
|
|
833
|
+
*
|
|
834
|
+
* @param {...unknown} args Message parts
|
|
835
|
+
*/
|
|
836
|
+
error: (...args) => ui.log.error(...args),
|
|
837
|
+
/**
|
|
838
|
+
* Log a warning through the default controller.
|
|
839
|
+
*
|
|
840
|
+
* @param {...unknown} args Message parts
|
|
841
|
+
*/
|
|
842
|
+
warn: (...args) => ui.log.warn(...args),
|
|
843
|
+
/**
|
|
844
|
+
* Log an informational message through the default controller.
|
|
845
|
+
*
|
|
846
|
+
* @param {...unknown} args Message parts
|
|
847
|
+
*/
|
|
848
|
+
info: (...args) => ui.log.info(...args),
|
|
849
|
+
/**
|
|
850
|
+
* Log a debug message through the default controller.
|
|
851
|
+
*
|
|
852
|
+
* @param {...unknown} args Message parts
|
|
853
|
+
*/
|
|
854
|
+
debug: (...args) => ui.log.debug(...args),
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
// Minimum verbosity level for each shimmed console method.
|
|
858
|
+
const CONSOLE_ROUTES = {
|
|
859
|
+
log: { level: LEVEL_NORMAL, name: "info" },
|
|
860
|
+
info: { level: LEVEL_NORMAL, name: "info" },
|
|
861
|
+
warn: { level: LEVEL_NORMAL, name: "warn" },
|
|
862
|
+
error: { level: LEVEL_SILENT, name: "error" },
|
|
863
|
+
debug: { level: LEVEL_VERBOSE, name: "debug" },
|
|
864
|
+
trace: { level: LEVEL_DEBUG, name: "trace" },
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
let originalConsole = null;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Install a global `console` shim routing `log`/`info`/`warn`/`error`/`debug`/
|
|
871
|
+
* `trace` through the controller. This converts every existing `console.*` call
|
|
872
|
+
* site to land on the diagnostic stream above the live region without editing
|
|
873
|
+
* any of them. Unknown members delegate to the real console.
|
|
874
|
+
*
|
|
875
|
+
* @param {object} [uiInstance] Controller to route through
|
|
876
|
+
* @returns {() => void} Function that restores the original console
|
|
877
|
+
*/
|
|
878
|
+
export function installConsoleShim(uiInstance = ui) {
|
|
879
|
+
if (originalConsole !== null) {
|
|
880
|
+
return restoreConsole;
|
|
881
|
+
}
|
|
882
|
+
originalConsole = globalThis.console;
|
|
883
|
+
const overrides = {};
|
|
884
|
+
for (const [method, route] of Object.entries(CONSOLE_ROUTES)) {
|
|
885
|
+
overrides[method] = (...args) => {
|
|
886
|
+
if (uiInstance.level < route.level) {
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
const formatted = formatWithOptions(
|
|
890
|
+
{ colors: uiInstance.color },
|
|
891
|
+
...args,
|
|
892
|
+
);
|
|
893
|
+
// Streams without color (pipes, CI, NO_COLOR) stay free of escape bytes
|
|
894
|
+
// so the diagnostic stream is grep-safe.
|
|
895
|
+
uiInstance.writeLine(
|
|
896
|
+
route.name,
|
|
897
|
+
uiInstance.color ? formatted : stripAnsi(formatted),
|
|
898
|
+
);
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
globalThis.console = new Proxy(originalConsole, {
|
|
902
|
+
get(target, prop, receiver) {
|
|
903
|
+
return Object.hasOwn(overrides, prop)
|
|
904
|
+
? overrides[prop]
|
|
905
|
+
: Reflect.get(target, prop, receiver);
|
|
906
|
+
},
|
|
907
|
+
});
|
|
908
|
+
return restoreConsole;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Restore the console captured by {@link installConsoleShim}. Safe to call when
|
|
913
|
+
* no shim is installed.
|
|
914
|
+
*/
|
|
915
|
+
export function restoreConsole() {
|
|
916
|
+
if (originalConsole !== null) {
|
|
917
|
+
globalThis.console = originalConsole;
|
|
918
|
+
originalConsole = null;
|
|
919
|
+
}
|
|
920
|
+
}
|