Skip to content

feat(add): --unscoped flag to alias packages by their unscoped name - #36319

Merged
bartlomieju merged 1 commit into
denoland:mainfrom
dsherret:feat/add-unscoped-flag
Jul 30, 2026
Merged

feat(add): --unscoped flag to alias packages by their unscoped name#36319
bartlomieju merged 1 commit into
denoland:mainfrom
dsherret:feat/add-unscoped-flag

Conversation

@dsherret

@dsherret dsherret commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

deno add --unscoped jsr:@david/jsonc-morph adds the package to the import map as "jsonc-morph" instead of "@david/jsonc-morph", which is the same result as spelling out jsonc-morph@jsr:@david/jsonc-morph.

jsonc-morph@jsr:@david/jsonc-morph is a mouthful, so --unscoped is nicer to write and doesn't have any duplication.

The reason I want this, is so I can recommend:

npm install jsonc-morph
deno install --unscoped jsr:@david/jsonc-morph

Then the users all import from the same "jsonc-morph" bare specifier.

Also supported on deno install <pkg>. Applies to package.json too, where a differing alias is written using npm's alias syntax ("esm-basic": "npm:@denotest/esm-basic@^1.0.0").

An alias the user provided always wins, and unscoped package names are unaffected. Because two scopes can share a name, adding packages that would collapse to the same alias is an error rather than letting one silently overwrite the other.

This PR was created and iterated on with AI.

`deno add --unscoped jsr:@david/jsonc-morph` adds the package to the
import map as "jsonc-morph" instead of "@david/jsonc-morph", which is
the same result as spelling out `jsonc-morph@jsr:@david/jsonc-morph`.

Also supported on `deno install <pkg>`. Applies to package.json too,
where a differing alias is written using npm's alias syntax
("esm-basic": "npm:@denotest/esm-basic@^1.0.0").

An alias the user provided always wins, and unscoped package names are
unaffected. Because two scopes can share a name, adding packages that
would collapse to the same alias is an error rather than letting one
silently overwrite the other.
@bartlomieju

Copy link
Copy Markdown
Member

The within-command collision guard is a nice touch, but it only compares against the other packages in the same deno add invocation — it won't catch a collision with an alias that's already in deno.json/package.json from an earlier run.

deno add --unscoped jsr:@david/flag     # writes "flag": "jsr:@david/flag@..."
deno add --unscoped jsr:@other/flag     # silently overwrites "flag"

The second command replaces the first "flag" import without any error — the same "silently overwrite each other" outcome the batch guard is there to prevent, just split across two invocations.

This matches how deno add already handles conflicting explicit aliases across runs, so it may be intentional and out of scope for this PR. If so, could you note that the guard is best-effort (single-command only) in the PR description or a code comment? Otherwise, worth considering checking the resolved alias against the existing config imports before writing.

@dsherret

Copy link
Copy Markdown
Contributor Author

This matches how deno add already handles conflicting explicit aliases across runs, so it may be intentional and out of scope for this PR.

Yes, I noticed this and kept the current behaviour.

@bartlomieju
bartlomieju merged commit 39f402e into denoland:main Jul 30, 2026
137 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants