From 8557c7c08943856e0792a2af96d1dfe53d0af76a Mon Sep 17 00:00:00 2001 From: Alexander Wondwossen Date: Sat, 28 Mar 2026 09:46:08 -0400 Subject: [PATCH] feat: add package access/collaborators page Gives /package//access its own dedicated page instead of just being buried in the sidebar. Shows the existing AccessControls component when the npm connector is running, or a connect prompt otherwise. - New page at /package/[[org]]/[name]/access.vue - Access tab added to the package navigation header - i18n keys for the page title, subtitle, and connect prompt - README updated, removed /access from "Not yet supported" URL list --- README.md | 5 +- app/components/Package/Header.vue | 22 ++++- app/pages/package/[[org]]/[name]/access.vue | 93 +++++++++++++++++++++ i18n/locales/en.json | 7 +- i18n/schema.json | 15 ++++ 5 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 app/pages/package/[[org]]/[name]/access.vue diff --git a/README.md b/README.md index 05efb54876..5a7d56bb8f 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ What npmx offers: - **Version range resolution** – dependency ranges (e.g., `^1.0.0`) resolve to actual installed versions - **Claim new packages** – register new package names directly from search results (via local connector) - **Clickable version tags** – navigate directly to any version from the versions list +- **Package access management** – view and manage team/collaborator access for scoped packages (via local connector) ### User & org pages @@ -91,7 +92,7 @@ What npmx offers: | Multi-provider repo support | ❌ | ✅ | | Version range resolution | ❌ | ✅ | | Dependents list | ✅ | 🚧 | -| Package admin (access/owners) | ✅ | 🚧 | +| Package admin (access/owners) | ✅ | ✅ | | Org/team management | ✅ | 🚧 | | 2FA/account settings | ✅ | ❌ | | Claim new package names | ✅ | ✅ | @@ -118,8 +119,6 @@ npmx.dev supports npm permalinks – just replace `npmjs.com` with `npmx.dev #### Not yet supported -- `/package//access` – package access settings -- `/package//dependents` – dependent packages list - `/settings/*` – account settings pages ### Simpler URLs diff --git a/app/components/Package/Header.vue b/app/components/Package/Header.vue index 7cf6b4c8bc..19ed77a565 100644 --- a/app/components/Package/Header.vue +++ b/app/components/Package/Header.vue @@ -10,7 +10,7 @@ const props = defineProps<{ latestVersion?: SlimVersion | null provenanceData?: ProvenanceDetails | null provenanceStatus?: string | null - page: 'main' | 'docs' | 'code' | 'diff' + page: 'main' | 'docs' | 'code' | 'diff' | 'access' versionUrlPattern: string }>() @@ -108,6 +108,18 @@ const mainLink = computed((): RouteLocationRaw | null => { return packageRoute(props.pkg.name, props.resolvedVersion) }) +const accessLink = computed((): RouteLocationRaw | null => { + if (props.pkg == null) return null + const split = props.pkg.name.split('/') + return { + name: 'package-access', + params: { + org: split.length === 2 ? split[0] : undefined, + name: split.length === 2 ? split[1]! : split[0]!, + }, + } +}) + const diffLink = computed((): RouteLocationRaw | null => { if ( props.pkg == null || @@ -343,6 +355,14 @@ const fundingUrl = computed(() => { > {{ $t('compare.compare_versions') }} + + {{ $t('package.links.access') }} + diff --git a/app/pages/package/[[org]]/[name]/access.vue b/app/pages/package/[[org]]/[name]/access.vue new file mode 100644 index 0000000000..8fc76d0a48 --- /dev/null +++ b/app/pages/package/[[org]]/[name]/access.vue @@ -0,0 +1,93 @@ + + + diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 02c1af000f..224adf8ecf 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -318,7 +318,8 @@ "docs": "docs", "fund": "fund", "compare": "compare", - "compare_this_package": "compare this package" + "compare_this_package": "compare this package", + "access": "access" }, "likes": { "like": "Like this package", @@ -587,6 +588,10 @@ "show_all": "show {count} deprecated package | show all {count} deprecated packages" }, "access": { + "page_title": "Access & Collaborators", + "page_subtitle": "Manage team and collaborator access for {name}", + "connect_required": "Connect your npm CLI to manage access", + "connect_hint": "Use the local connector to view and manage package collaborators and team access.", "title": "Team Access", "refresh": "Refresh team access", "list_label": "Team access list", diff --git a/i18n/schema.json b/i18n/schema.json index 885bd6eb5e..d071d65a38 100644 --- a/i18n/schema.json +++ b/i18n/schema.json @@ -960,6 +960,9 @@ }, "compare_this_package": { "type": "string" + }, + "access": { + "type": "string" } }, "additionalProperties": false @@ -1765,6 +1768,18 @@ "access": { "type": "object", "properties": { + "page_title": { + "type": "string" + }, + "page_subtitle": { + "type": "string" + }, + "connect_required": { + "type": "string" + }, + "connect_hint": { + "type": "string" + }, "title": { "type": "string" },