- Primary Language: JavaScript (ES modules,
"type": "module"in package.json) - TypeScript: Configuration present but code is primarily JavaScript with JSDoc
- Node.js: Requires Node >= 20.0.0, npm >= 11.5.1
- CLI:
yargsfor command-line argument parsing - Parsing Libraries:
fast-xml-parser,fast-toml,smol-toml,web-tree-sitterwith grammar packages (tree-sitter-requirements,tree-sitter-gomod,tree-sitter-containerfile) - Prefer proper parsers over regex: When parsing structured file formats (e.g., go.mod, requirements.txt, Dockerfile), use tree-sitter grammars rather than hand-written regex. Tree-sitter grammars already exist for several formats and provide a well-defined AST that handles edge cases. Follow the existing pattern: add the grammar package, create a
*_parser.jsmodule undersrc/providers/, copy the.wasmfile inpretest/postcompilescripts, and use queries to extract data from the syntax tree.
- Linter: ESLint with recommended config + editorconfig + import plugins
- Indentation: Tabs (4 spaces for YAML/Markdown)
- Line endings: LF
- Max line length: 100 (120 for Markdown)
- Charset: UTF-8, final newline, trim trailing whitespace
- Import ordering (ESLint enforced): builtin, external, internal, parent, sibling, index — alphabetical within groups
- Strict equality:
eqeqeq: ["warn", "always", {"null": "never"}] - Curly braces: Required (
curly: "warn") - No throw literals:
no-throw-literal: "warn" - No Prettier — ESLint + EditorConfig handle formatting
- Classes: PascalCase with underscore-separated language names (
Java_maven,Base_java,Javascript_npm) - Files: snake_case for providers (
base_java.js,javascript_npm.js,python_pip.js) - Test files:
*.test.jssuffix (analysis.test.js,provider.test.js) - Functions/Methods: camelCase (
provideComponent(),provideStack(),validateLockFile()) - Variables: camelCase (
manifestPath,backendUrl) - Constants: UPPER_SNAKE_CASE (
ecosystem_maven,DEFAULT_WORKSPACE_DISCOVERY_IGNORE) - Private class fields:
#prefix (#manifest,#cmd,#ecosystem) - Protected methods:
_prefix (_lockFileName(),_cmdName(),_listCmdArgs())
src/
├── index.js # Main export
├── cli.js # CLI entry point
├── analysis.js # API request handling
├── provider.js # Provider matching logic
├── workspace.js # Workspace discovery
├── tools.js # Utilities
├── sbom.js # SBOM handling
├── cyclone_dx_sbom.js # CycloneDX SBOM generation
├── providers/ # Ecosystem providers
│ ├── base_java.js
│ ├── base_javascript.js
│ ├── java_maven.js
│ ├── javascript_npm.js
│ ├── python_pip.js
│ ├── rust_cargo.js
│ └── processors/ # Specialized processors
├── license/ # License detection
└── oci_image/ # OCI image analysis
test/
├── analysis.test.js
├── provider.test.js
├── tools.test.js
└── providers/ # Provider-specific tests
- Throw Error objects:
throw new Error("message"),throw new TypeError("message") - No custom error classes — uses built-in
ErrorandTypeError - HTTP errors: Check
resp.status, throw with status code and response text - Async errors: Bubble up naturally via async/await (no blanket try-catch)
- Validation errors: Thrown early with descriptive context (manifest type, lock file)
- Framework: Mocha with TDD UI (
suite()/test()) - Assertions: Chai with
expect()syntax - Mocking: Sinon for stubs; MSW (Mock Service Worker) for HTTP mocking
- Module mocking:
esmockwith experimental loader - Coverage: C8 with 82% line coverage requirement
- Test patterns:
expect(res).to.deep.equal(...),expect(() => ...).to.throw('message') - Higher-order setup: Functions like
interceptAndRun()for test setup/teardown - Prefer real tool invocations over env var overrides: Tests should call the actual ecosystem tools (pip, uv, poetry, mvn, npm, etc.) rather than injecting pre-recorded output via
TRUSTIFY_DA_*environment variables. The CI environment has these tools available. Env var overrides (TRUSTIFY_DA_PIP_REPORT,TRUSTIFY_DA_UV_EXPORT, etc.) exist for users who lack the tool locally, but tests should exercise the real tool path to catch integration issues. - Golden SBOM files for every test fixture: Every provider test fixture directory must include
expected_stack_sbom.jsonandexpected_component_sbom.jsongolden files. Tests must use theSBOM_CASESpattern to do a fulldeep.equalcomparison of the provider output against these golden files. Manual partial assertions (e.g. checking a single component name) are not a substitute — they may be added as supplementary tests but never as the only verification for a fixture.
- Likely Conventional Commits format
- DCO (Developer Certificate of Origin) required
- Semantic versioning (
0.3.0in package.json)
- Dependabot suppression: Test fixture directories contain intentionally pinned (sometimes vulnerable) dependencies. When adding a new test fixture directory with a manifest file, review
.github/dependabot.ymlto ensure the new path is covered. Non-npm ecosystems are suppressed via root-levelignore: [{dependency-name: "*"}]entries. npm fixtures use per-directory entries with/**globs; add the parent directory if a new npm/pnpm/yarn fixture tree is introduced.
- Package manager: npm with
package-lock.json - Module system: ES modules with explicit
.jsextensions in relative imports - Import convention:
import fs from 'node:fs'(node: protocol for built-ins) - Environment variables: Prefixed with
TRUSTIFY_DA_(e.g.,TRUSTIFY_DA_MVN_PATH,TRUSTIFY_DA_TOKEN,TRUSTIFY_DA_DEBUG) - Multi-ecosystem support: npm, pnpm, yarn, Maven, Gradle, pip, cargo, Go modules, Docker/Podman