Skip to content

Guardrails / Collectors

Node.js build ​

The Node.js project in the project directory: its manifest, the Node version and package manager it asks for, every workspace it declares, the dependencies each manifest names and which of them are pinned, and the lock files committed beside them.

Facts keynodejs
Versionv1
Scriptnodejs.py
Timeout30 seconds

Inputs ​

InputDescriptionDefaultEnvironment
projectDirDirectory holding the project, relative to the directory the CLI runs in..GUARDRAIL_INPUT_PROJECTDIR
maxWorkspacesMaximum number of workspace packages to describe. A larger monorepo carries the ones its globs resolve first.200GUARDRAIL_INPUT_MAXWORKSPACES

When a guardrail declares an input with the same name, it passes its value through. That means you set these values in the guardrail's configuration in buildnote.json.

A guardrail asks for these facts by name and reads them back by the same name:

json
{
  "collect": ["nodejs"]
}
python
nodejs = guardrail.facts("nodejs")

Facts ​

These are the fields of the document nodejs collects. In a path, [] means each entry of the list before it, and [path] means a key of the object before it.

FactMeaning
directoryThe project directory set by the guardrail's projectDir input, relative to the directory the CLI runs in. Every other path this collector reports is also relative to the directory the CLI runs in, so it resolves from where you invoked the CLI, not from wherever the collector happened to run.
existsWhether that directory exists. When it doesn't, nothing else is collected.
manifestPath of the primary manifest, from the directory the CLI runs in, always package.json.
sourcesEvery manifest that was read and understood, in the order they were read. A manifest the reader could not handle is in unparsed instead.
declaredThe Node version the project asks for, or null when it asks for none. .nvmrc wins over engines.node, because it is what a developer's shell reads.
declared.versionConstraint exactly as written, such as >=20 or 20.11.1.
declared.sourceFile declaring it, from the directory the CLI runs in.
declared.pinnedWhether the constraint names one exact version rather than a range. A >=, a ^, a ~, an x or an * is not pinned.
packageManagerThe packageManager field, such as pnpm@9.1.0, which is what Corepack installs. null when the manifest names none and whatever the runner has is used.
projectsEvery package in the build: the root, followed by every workspace its workspaces globs resolve to.
projects[].pathDirectory of the package, from the directory the CLI runs in; directory itself for the project directory.
projects[].manifestThat package's package.json, from the directory the CLI runs in.
projects[].nameName the manifest declares, or null when it declares none.
dependenciesWhat the manifests declare, split by whether the project asks for it itself.
dependencies.directEvery dependency any manifest declares, in manifest order.
dependencies.direct[].namePackage name, such as react or @company/widget.
dependencies.direct[].versionConstraint exactly as written, such as ^18.3.0, a workspace:* protocol or a git URL.
dependencies.direct[].scopesWhich of dependencies, devDependencies, peerDependencies and optionalDependencies declare it. A package in two carries both.
dependencies.direct[].sourceManifest declaring it, from the directory the CLI runs in.
dependencies.direct[].pinnedWhether the constraint names one exact version. A ^, a ~, a range, a tag, a URL or a workspace: protocol is not pinned.
dependencies.transitiveAlways empty. What a lock file resolves is not read: lockfiles says whether one is committed, and reading a package-lock.json graph is the scanner's job rather than this collector's.
scriptsNames of the scripts the root manifest declares. Names only, because a script body can carry a token.
lockfilesEvery lock file committed, from the directory the CLI runs in. More than one means two package managers each believe they own the tree.
droppedWorkspace packages left out because maxWorkspaces was reached. Above zero, projects and dependencies describe only part of the build.
unparsedEvery manifest the reader could not handle, so a guardrail can tell a project that declares nothing apart from one that could not be read.
unparsed[].pathPath of that manifest, from the directory the CLI runs in.
unparsed[].reasonWhy the reader could not handle it.

If a collector can't finish, it prints what it gathered so far along with an incomplete key that says why. Facts after the point where it stopped are missing, so a check that depends on them should read incomplete first.

Example facts ​

Here are the facts the nodejs collector gathers from an example project:

json
{
  "directory": ".",
  "exists": true,
  "manifest": "package.json",
  "sources": [
    "package.json",
    "packages/core/package.json"
  ],
  "declared": {
    "version": "20.11.1",
    "source": ".nvmrc",
    "pinned": true
  },
  "packageManager": "pnpm@9.1.0",
  "projects": [
    {
      "path": ".",
      "manifest": "package.json",
      "name": "@company/widget"
    },
    {
      "path": "packages/core",
      "manifest": "packages/core/package.json",
      "name": "@company/core"
    }
  ],
  "dependencies": {
    "direct": [
      {
        "name": "react",
        "version": "^18.3.1",
        "scopes": [
          "dependencies"
        ],
        "source": "package.json",
        "pinned": false
      },
      {
        "name": "zod",
        "version": "3.23.8",
        "scopes": [
          "dependencies"
        ],
        "source": "package.json",
        "pinned": true
      },
      {
        "name": "typescript",
        "version": "~5.4.5",
        "scopes": [
          "devDependencies"
        ],
        "source": "package.json",
        "pinned": false
      },
      {
        "name": "vitest",
        "version": "^1.6.0",
        "scopes": [
          "devDependencies"
        ],
        "source": "package.json",
        "pinned": false
      },
      {
        "name": "zod",
        "version": "3.23.8",
        "scopes": [
          "dependencies"
        ],
        "source": "packages/core/package.json",
        "pinned": true
      }
    ],
    "transitive": []
  },
  "scripts": [
    "build",
    "test"
  ],
  "lockfiles": [
    "pnpm-lock.yaml"
  ],
  "dropped": 0,
  "unparsed": []
}

Collected for ​

GuardrailCategoryInputs
nodejs/lockfile-committednodejsprojectDir
nodejs/package-manager-pinnednodejsprojectDir
nodejs/single-package-managernodejsprojectDir
nodejs/version-declarednodejsprojectDir

All collectors

Buildnote Limited
Registered in England and Wales, Reg: 16140412