How observe reads an Nx workspace
The Nx detector of @putnami/observe finds the projects of an Nx repository,
the directory each one owns and the projects each one depends on. The change
analysis uses them to map each changed file to its project and to list the
projects that depend on it. The detector reads files only: it never runs nx
or a package manager.
The graph export comes first
When the CI ran nx graph --file=graph.json before putnami observe, the
export is the authority. It holds every edge Nx knows, including the ones it
computes from source imports, which no static read can see.
npx nx graph --file=graph.json
putnami observeThe detector reads graph.json at the repository root; putnami observe has
no flag to name another file:
- each node of
graph.nodesis a project at itsdata.root; - each entry of
graph.dependenciesbetween two project nodes is an edge, whether Nx marks itstatic,dynamicorimplicit; - a dependency on an external node, such as
npm:react, is not an edge.
A missing file is not a finding. A file that is not an Nx graph export, or
whose nodes name no root, gets the observe.nx_graph_unreadable warning when
the caller named it or the repository holds nx.json, and the detector reads
the configuration instead. A node without a root, or with the root of another
node, gets the same warning and is skipped.
Without an export: the Nx configuration
A repository whose root holds nx.json is an Nx workspace. Its projects are:
- every directory that holds a
project.json; - every directory whose
package.jsonthe package manager workspace lists:workspacesin the rootpackage.json,packagesinpnpm-workspace.yamlandpackagesinlerna.json, together. A!pattern removes directories.
The package.json beside a project.json belongs to that project, listed or
not.
The detector does not enter node_modules, dist and hidden directories.
| Fact | Read from |
|---|---|
| Name | project.json name, else package.json nx.name, else package.json name, else the directory's last segment |
| Edges | implicitDependencies of project.json and of package.json nx: names, * patterns (* alone selects every project), tag:<tag> selectors, and ! exclusions, which also remove a package dependency edge; and the dependencies, devDependencies, peerDependencies and optionalDependencies that name another project's package |
| Type | projectType |
An edge that only a source import carries is missing from this read. Write the graph export in the CI to get it.
A project.json or package.json that is not valid JSON gets the
observe.nx_manifest_unreadable warning, and its directory is skipped.
What each project tells the change analysis
| Member | Meaning |
|---|---|
name |
The Nx project name. |
source |
orchestrator when it comes from the graph export, workspace when it comes from the configuration. |
testOutputs |
The repository-relative outputs of the project's test targets, where its test and coverage reports land. |
lockfile |
The root lockfile: pnpm-lock.yaml, yarn.lock, package-lock.json, bun.lock or bun.lockb, the first one found. |
A test target is named test, test-*, test:*, *-test or e2e, or its
executor ends in :test or runs Jest, Vitest, Playwright or Cypress. Its
outputs come from the target, else from the nx.json targetDefaults of its
name, else of its executor. The detector resolves {projectRoot},
{workspaceRoot}, {projectName} and {options.<name>}, cuts a glob to the
directory before it, and drops an exclusion, an absolute path and an output
it cannot resolve.
The probe answer
The detector answers in the shape of a workspace probe result, the contract an extension uses to tell Putnami about the projects of a directory: each project by its repository-relative path, the manifest its name was read from, its dependencies as project paths, and the members above as its metadata. The detector can therefore move to an extension of its own once Putnami can run a probe outside a workspace.