Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions aube.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ cmd add help="Add a dependency" {
flag --no-save help="Install without persisting the dependency to `package.json`" {
long_help "Install without persisting the dependency to `package.json`.\n\nSnapshots `package.json` and the lockfile, links the named packages into `node_modules`, and then restores both files — so the dependency is usable for the current process but the project's committed state is untouched.\n\nHandy for one-off experiments and for scripts that install a tool transiently. Mirrors `pnpm add --no-save`. Conflicts with `-g`/`--global`, which has to persist the install to its global manifest."
}
flag --no-save-workspace-protocol help="Inverse of `--save-workspace-protocol`" {
long_help "Inverse of `--save-workspace-protocol`.\n\nForces the manifest specifier into a registry-style spec (`^<version>`) for this invocation, even when `linkWorkspacePackages` matched a local sibling. The install pipeline still prefers the local workspace copy at resolve time — this flag only controls what's written to `package.json`. Mirrors `pnpm add --no-save-workspace-protocol`."
}
flag --save-catalog help="Save the new dependency into the workspace's default catalog" {
long_help "Save the new dependency into the workspace's default catalog.\n\nWrites `catalog:` into `package.json` and seeds/upserts the resolved range under `catalog:` in the workspace yaml. Mirrors `pnpm add --save-catalog`.\n\nWorkspace and aliased specs (`workspace:*`, `npm:`, `jsr:`) are never catalogized — the manifest gets the original spec and the catalog yaml is left alone. If the package is already in the target catalog, the existing entry is preserved (never overwritten); the manifest then gets `catalog:` only when the existing entry is compatible with the user's range.\n\nConflicts with `--no-save`: catalog mutations write to the workspace yaml, which the `--no-save` restore path doesn't snapshot — combining the two would silently leave an orphaned catalog entry behind."
}
Expand All @@ -93,6 +96,9 @@ cmd add help="Add a dependency" {
flag --save-peer help="Add as a peer dependency (written to `peerDependencies` in package.json)" {
long_help "Add as a peer dependency (written to `peerDependencies` in package.json).\n\nBy convention you usually pair this with `--save-dev` so the peer is also installed for local development; that's what pnpm does."
}
flag --save-workspace-protocol help="Force the manifest specifier into `workspace:` form for this invocation, overriding `saveWorkspaceProtocol` from the workspace yaml / `.npmrc` / env" {
long_help "Force the manifest specifier into `workspace:` form for this invocation, overriding `saveWorkspaceProtocol` from the workspace yaml / `.npmrc` / env.\n\nOnly meaningful when `linkWorkspacePackages` (or a workspace sibling already exists for the named package). With this flag the entry written to `package.json` is `workspace:^` (rolling) or `workspace:^<version>` (pinned), depending on the resolved `saveWorkspaceProtocol` value."
}
flag "-w --workspace" help="Add the dependency to the workspace root's `package.json`" {
long_help "Add the dependency to the workspace root's `package.json`.\n\nApplies regardless of the current working directory: walks up from cwd looking for `aube-workspace.yaml`, `pnpm-workspace.yaml`, or a `package.json` with a `workspaces` field and runs the add against that directory."
}
Expand Down
17 changes: 17 additions & 0 deletions crates/aube-manifest/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,23 @@ pub struct WorkspaceConfig {
#[serde(default)]
pub cleanup_unused_catalogs: Option<bool>,

// -- Workspace-protocol settings --
/// Resolve `aube add <name>` against local workspace siblings
/// before falling back to the registry. Wired through
/// `aube_settings::resolved::link_workspace_packages`; the typed
/// field exists so `meta::workspace_yaml_keys_...` sees the key
/// as a real field and doesn't fall through to `extra`.
#[serde(default)]
pub link_workspace_packages: Option<bool>,
Comment thread
greptile-apps[bot] marked this conversation as resolved.

/// Spec form written to `package.json` when `aube add` matches a
/// workspace sibling. The yaml value can be the booleans `true` /
/// `false` or the string `"rolling"`, so the typed field lands at
/// `yaml_serde::Value` and the resolver normalizes via
/// `aube_settings::resolved::SaveWorkspaceProtocol::from_str_normalized`.
#[serde(default)]
pub save_workspace_protocol: Option<yaml_serde::Value>,

// -- Peer Dependency Settings --
/// Whether to auto-install peer dependencies (default: true).
#[serde(default)]
Expand Down
63 changes: 63 additions & 0 deletions crates/aube-settings/settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1985,6 +1985,69 @@ sources.env = ["npm_config_save_prefix", "NPM_CONFIG_SAVE_PREFIX", "AUBE_SAVE_PR
sources.npmrc = ["save-prefix", "savePrefix"]
examples = []

[linkWorkspacePackages]
description = "Resolve `aube add <name>` against local workspace siblings before falling back to the registry."
type = "bool"
default = "false"
docs = """
When `true`, `aube add <name>` checks the workspace for a package
whose `name` matches the spec before falling back to the registry.
A match wires the dep up as a workspace link; the manifest specifier
written to `package.json` is controlled by `saveWorkspaceProtocol`.

If the user typed an explicit range (`aube add pkg@^1.2.0`), the
sibling's version must satisfy it — otherwise the spec falls through
to the registry path so an incompatible local copy isn't silently
linked.

Off by default to match pnpm 8+ — opt in via `pnpm-workspace.yaml`
when you want every `aube add` to prefer the local copy of a sibling.
Aube's resolver already prefers workspace siblings on bare semver
ranges at install time, so this setting only controls `aube add`'s
manifest-write path; pnpm's `"deep"` value (which extends the
preference to transitive deps) is therefore not implemented and
treating the value as a plain bool is intentional.
"""
sources.cli = []
sources.env = [
"npm_config_link_workspace_packages",
"NPM_CONFIG_LINK_WORKSPACE_PACKAGES",
"AUBE_LINK_WORKSPACE_PACKAGES",
]
sources.npmrc = ["link-workspace-packages", "linkWorkspacePackages"]
sources.workspaceYaml = ["linkWorkspacePackages"]
examples = []

[saveWorkspaceProtocol]
description = "Spec form written to `package.json` when `aube add` resolves against a workspace sibling."
type = '"true" | "false" | "rolling"'
default = "\"rolling\""
docs = """
- `"true"` writes a version-pinned workspace spec (`workspace:^1.0.0`,
honoring `savePrefix`). The exact lockfile entry never moves
without an explicit `aube update`.
- `"rolling"` (default) writes the rolling form `workspace:^`
(or `workspace:~` / `workspace:*` per `savePrefix`). Sibling
version bumps flow into dependents on the next install without
re-running `aube add`.
- `"false"` writes a plain registry-style spec (`^1.0.0`). The dep
is still linked locally on install (controlled by
`linkWorkspacePackages`), but the manifest looks identical to a
registry dep.

The `--save-workspace-protocol` / `--no-save-workspace-protocol` CLI
flags on `aube add` override this setting per-invocation.
"""
sources.cli = []
sources.env = [
"npm_config_save_workspace_protocol",
"NPM_CONFIG_SAVE_WORKSPACE_PROTOCOL",
"AUBE_SAVE_WORKSPACE_PROTOCOL",
]
sources.npmrc = ["save-workspace-protocol", "saveWorkspaceProtocol"]
sources.workspaceYaml = ["saveWorkspaceProtocol"]
examples = []

[tag]
description = "Default dist-tag used by `aube add` without a version."
type = "string"
Expand Down
Loading
Loading