Package and workspace model
Flog reads workspace membership from the root package.json workspaces
array. The object form with a packages array is accepted for compatibility.
Workspace paths are normalized to slash-separated paths and sorted before they
enter the project model.
Supported workspace patterns use path-segment globs:
*,?, and character classes match within one segment.**matches zero or more complete segments.- absolute paths, parent traversal, root selection, overlapping matches, and paths resolving outside the workspace through a symlink are rejected.
Discovery derives bounded traversal roots from the fixed prefix of each glob
and prunes a directory as soon as no workspace pattern can match below it. A
shallow declaration such as packages/* therefore inspects package directories
but never generated descendants such as packages/core/lib. Recursive **
patterns continue to discover nested packages. .git, .rp, node_modules,
and directory symlinks are never traversed.
An entry that vanishes while expanding a wildcard is revalidated and skipped
before it becomes a workspace candidate. Once a candidate is confirmed, or when
an exact workspace importer is declared, disappearance and missing or invalid
package.json files remain errors rather than silently changing membership.
Workspace package names must be unique. Flog also accepts hierarchical local
identifiers such as @primate/app/ts for application filtering, while registry
dependency names retain normal npm scoped-name validation.
When the workspace root is itself public, its package name must also differ
from every workspace child. A private configuration root may share a name with
a public child because it has no publication identity.
Dependency specifiers#
The shared model recognizes:
- complete versions and npm-style SemVer ranges
- npm dist-tags such as
latestandnext npm:aliases, including scoped aliases and tagged aliasesworkspace:*,workspace:^, andworkspace:~- explicit workspace ranges such as
workspace:^1.2.0
SemVer ranges support wildcards and partial versions, comparators, hyphen
ranges, tilde ranges, caret ranges, AND by whitespace, and OR with ||.
Prereleases follow npm's opt-in rule: a prerelease only matches a comparator set
that includes a prerelease comparator with the same major, minor, and patch.
Dist-tags are resolved through the registry's dist-tags map and pinned to the
resulting exact version. Peer constraints must remain SemVer ranges because a
peer provider is validated locally rather than selected from a registry tag.
Every workspace: dependency must name a discovered local package. Explicit
ranges must match the local package version. The graph records dependency,
development, optional, and peer edges and provides deterministic
dependency-first traversal with field-aware cycle errors.