)
pnpm registry-access.commands 实战指南用 pnpm 管理 registry 包deprecate / undeprecate 及全套权限命令【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm本指南以 pnpm 11 仓库中的 pnpm/registry-access.commands 模块 为核心系统讲解 pnpm 面向 npm registry 的整套包管理命令弃用与取消弃用deprecate / undeprecate、访问权限access、发布标签dist-tag、协作者与团队owner / team、取消发布unpublish、收藏star以及连通性/身份类命令ping / whoami / search。读完本文你将掌握每条命令的完整 CLI 用法、可选项与默认值并理解其底层如何通过 registry REST API、认证头与 OTP 流程实现读写操作。模块定位pnpm 的 registry 管理命令集在 pnpm 11 的模块化架构中pnpm/registry-access.commands是一个职责单一的 workspace 包专门承载对 registry 上包进行管理操作的命令实现。它的定义在 package.json 中清晰可见包名pnpm/registry-access.commands当前版本1101.0.4描述Commands for managing packages on the registrydeprecate、undeprecate 等运行环境node 22.13type: module编译产物入口为lib/index.js许可协议MIT依赖了 pnpm 工作区内的pnpm/registry-access.client、pnpm/network.fetch、pnpm/network.auth-header、pnpm/network.web-auth、pnpm/config.pick-registry-for-package、pnpm/config.reader等基础设施包以及pnpm/npm-package-argnpa、semver、render-help、chalk、ramda等通用库该模块的公开 API 由 src/index.ts 统一导出共暴露 13 个命令命名空间导出命名空间命令名源码位置deprecatedeprecatesrc/deprecation/deprecate.tsundeprecateundeprecatesrc/deprecation/undeprecate.tsaccessaccesssrc/access.tsdistTagdist-tag/dist-tagssrc/distTag.tsownerowner/ownerssrc/owner.tsteamteamsrc/team.tsunpublishunpublishsrc/unpublish.tsstar/unstar/starsstar/unstar/starssrc/star/whoamiwhoamisrc/whoami.tspingpingsrc/ping.tssearchsearch/s/se/findsrc/search.ts安装模块 README 给出的标准安装方式为pnpm add pnpm/registry-access.commands在 pnpm 仓库内部它作为 workspace 包被引用用户侧通常无需直接安装——这些命令最终由 pnpm CLI 的pnpm help command聚合展示每个命令文件都通过render-help生成帮助文本。若要在自己的 Node 工具链中以编程方式调用可像仓库的测试代码那样导入对应命名空间并调用handler(opts, params)。通用基础设施所有命令共享的底层能力在深入各命令之前有必要先了解 src/common.ts 提供的共享工具它们是理解全部命令实现的关键。包名解析parsePackageSpec几乎所有命令都通过parsePackageSpec解析包名参数其内部使用pnpm/npm-package-argnpaexport function parsePackageSpec (spec: string): { name: string, escapedName: string, versionRange: string | undefined } { const parsed npa(spec) ... const versionRange parsed.rawSpec || undefined return { name: parsed.name, escapedName: parsed.escapedName, versionRange } }它返回三个字段name规范包名、escapedNameURL 编码后的名字用于拼接 REST 路径如scope/pkg会编码为scope%2fpkg、versionRange之后的裸版本说明符可为 semver 区间。解析失败时抛出INVALID_PACKAGE_SPEC错误。registry 选择与认证头rcOptionsTypes()从pnpm/config.reader的完整配置类型中选取registry一项确保所有命令都支持--registry url选项pickRegistryForPackage来自pnpm/config.pick-registry-for-package按 scope 选择 registry默认 registry 为源码中反复出现的常量https://registry.npmjs.org/createGetAuthHeaderByURI来自pnpm/network.auth-header基于configByUri生成认证头。configByUri以//host/为键支持按 scope 细分的 token例如测试代码中的写法const CONFIG_BY_URI { [//localhost:${REGISTRY_MOCK_PORT}/]: { : { authToken: getRegistryMockToken() }, }, }test/dist-tag.ts 中的dist-tag ls: should use package-scoped auth用例验证了这一点当configByUri同时提供默认 token 与scope专属 token 时请求会携带Bearer scoped-token。安全的错误体读取readErrorBodyregistry 的响应体是不可信的readErrorBody采用限量读取策略最多读取64 * 1024字节ERROR_BODY_LIMIT超出部分截断并追加(response body truncated)标记避免将不可信的大响应体整体缓冲进内存。OTP 上下文createOtpContext对于需要二次验证的写操作createOtpContext组装了 web 认证所需的运行环境readline、inquirer/prompts的input、日志器、fetch等并特意让内部 fetch 继承命令的代理/TLS/configByUri配置保证在自定义网络环境下 OTP 轮询不会因配置丢失而失败。这一点在 src/common.ts 的注释中有明确说明。核心命令一deprecate 与 undeprecate弃用/取消弃用这是模块描述中点名的两个命令也是 pnpm 发布生态中最常用的维护操作。deprecatepnpm deprecate package[version] message可用选项选项说明--registry url指定 npm registry 基础地址--otp code提供一次性密码适用于开启双因素认证的账号命令执行流程deprecate.ts → deprecation/common.ts参数校验缺包名抛DEPRECATE_REQUIRED缺消息抛DEPRECATE_MESSAGE_REQUIRED提示取消弃用请用undeprecate命令读取完整 packumentGET registry/{escapedName}请求头带fullMetadata: true得到包的全部版本元数据PackageMeta版本筛选若给了version用semver.satisfies(version, range)筛选匹配版本未给则作用于所有版本。无匹配版本抛NO_MATCHING_VERSIONS回写为每个匹配版本设置pkg.versions[ver].deprecated message然后PUT整个 packument 回 registry带content-type: application/json如有--otp则附加npm-otp头成功返回Successfully deprecated N version(s) of package。值得注意的细节由于deprecated字段是按版本存储的所以给包加弃用消息本质上是对某个版本区间元数据的批量修改。401/403 分别映射为UNAUTHORIZED、FORBIDDEN并附带 registry 返回的错误体。undeprecatepnpm undeprecate package[version]与deprecate共用updateDeprecation只是传入deprecated: undefined从而把匹配版本的deprecated字段清空不接受消息参数多传一个参数会抛UNDEPRECATE_NO_MESSAGE仅对已处于弃用状态的版本生效若匹配范围内没有任何已弃用版本抛NOT_DEPRECATED。实测验证test/deprecate.ts 展示了完整闭环先用publish.handler在本地 mock registry 上发布包再调用deprecate.handler最后通过pnpm view pkg deprecated --json断言弃用消息写入了 registry。用例覆盖了弃用整个包与弃用特定版本pkg0.0.1两种场景。核心命令二access包访问权限与可见性access是子命令最多的命令之一access.ts帮助文本给出的完整用法pnpm access list packages [user|scope|scope:team] pnpm access list collaborators [package [user]] pnpm access get status [package] pnpm access set statuspublic|private [package] pnpm access set mfanone|publish|automation [package] pnpm access grant read-only|read-write scope:team [package] pnpm access revoke scope:team [package]通用选项--registry url、--jsonJSON 输出、--otp。list packages列出某个用户、组织scope或团队scope:team可访问的包不带参数时列出当前登录用户自己的包。实体类型由参数形态推断含:视为团队、以开头视为组织、否则视为用户。对应 registry 端点自己/-/package?formatcli团队/-/team/{scope}/{team}/package?formatcli组织/-/org/{scope}/package?formatcli用户/-/user/{user}/package?formatcli默认输出为排序后的pkg: access行仅包名无权限字段时只输出包名--json则输出原始 JSON。list collaborators / get status / set statuslist collaborators请求/-/package/{name}/collaborators?formatcli[user...]输出user email: permissionsget status请求/-/package/{name}/accessGET输出package: xxx与access: public|restricted无access字段时视为 publicset statusPOST /-/package/{name}/accessbody 为{ access: public | restricted }。注意源码中的两个约束值仅接受public/private/restricted其中private与restricted都会被归一化为restricted其他值抛ACCESS_SET_STATUS_INVALID只能作用于 scoped 包scope/name无 scope 的包恒为 public强行设置会抛ACCESS_SET_STATUS_UNSCOPED。另外access public pkg与access restricted pkg作为 npm 时代的废弃形态仍被兼容内部转换为statuspublic/statusrestricted。set mfapnpm access set mfanone|publish|automation package通过POST /-/package/{name}/access写入{ publish_requires_tfa: boolean }none对应falsepublish与automation对应true二者在 registry API 层面的差异由服务端解析。非法值抛ACCESS_SET_MFA_INVALID。grant / revokegrantPUT /-/team/{scope}/{team}/packagebody 为{ package, permissions }permissions仅接受read-only或read-write团队格式必须为scope:teamrevokeDELETE同一端点body 为{ package }。对应输出分别为scope:team (read-only): pkg与-scope:team: pkg。核心命令三dist-tag发布标签管理pnpm dist-tag ls [package] pnpm dist-tag add packageversion [tag] pnpm dist-tag rm package tagdistTag.ts 的实现要点默认子命令为ls不写子命令时直接把全部参数当作ls处理list是ls的别名lsGET /-/package/{name}/dist-tags按键名排序输出tag: versionadd目标版本必须是精确 semver 版本semver.valid校验否则抛DIST_TAG_ADD_INVALID_VERSION标签默认值为latest。写操作通过pnpm/registry-access.client的 setDistTag 完成PUT /-/package/{name}/dist-tags/{tag}请求头携带npm-auth-type与可选的npm-otprmDELETE /-/package/{name}/dist-tags/{tag}删除前先GET确认标签存在不存在抛DIST_TAG_NOT_FOUND且禁止删除latest标签抛DIST_TAG_RM_LATEST——这是防止破坏默认安装版本语义的保护机制。OTP 双模式web 与 legacydist-tag是模块中 OTP 流程的代表默认authType web走pnpm/network.web-auth的 web 认证挑战自动轮询完成 OTP一旦用户显式传入--otp则切为legacy模式直接发送经典 6 位验证码。withOtpHandling负责捕获401中的 OTP 挑战并重试。核心命令四owner 与 team协作者与团队管理ownerpnpm owner ls package pnpm owner add package user pnpm owner rm package userowner.ts 中ls为默认子命令请求GET /-/package/{name}/owners输出username email列表add/rm分别对/-/package/{name}/owners/{user}执行PUT/DELETE返回user: pkg/-user: pkg。teampnpm team create scope:team [--otp code] pnpm team destroy scope:team [--otp code] pnpm team add scope:team user [--otp code] pnpm team rm scope:team user [--otp code] pnpm team ls scope|scope:teamteam.ts 的额外选项为--parseable逐行纯文本输出与--jsonJSON 输出。实现细节团队规格解析parseScopeTeam要求以开头格式为scope列出团队或scope:team列出成员否则抛TEAM_INVALID_SCOPE认证为组织挑选 registry 时以伪包名scope/__pnpm_team__作为 key 调用pickRegistryForPackage保证按 scope 解析到正确的 registry 与 token缺认证抛TEAM_MISSING_AUTH端点创建PUT /-/org/{scope}/teambody{ name }、销毁DELETE /-/team/{scope}/{team}、成员增删PUT|DELETE /-/team/{scope}/{team}/userbody{ user }列出团队与成员在无数据时有友好提示scope has no teams/scope:team has no members404 分别映射为ORG_NOT_FOUND/TEAM_NOT_FOUND未提供子命令时若首参数以或:开头则默认执行ls与 npm 行为一致否则抛TEAM_SUBCOMMAND_REQUIRED。核心命令五unpublish取消发布pnpm unpublish [package[version]]选项--registry、--otp、--force。unpublish是模块中最重的一条写操作命令unpublish.ts其执行逻辑分层清晰读取 packumentfullMetadata: true无版本抛NO_VERSIONS按版本范围筛选version支持 semver 区间semver.satisfies无匹配抛NO_MATCHING_VERSIONS若匹配到的版本恰好等于全部版本则自动转为全部取消发布流程部分取消发布unpublishVersions先收集待删版本的 tarball URL再从versions中剔除同步维护dist-tags指向已删版本的标签一并删除若latest被删自动用剩余最高版本semver.compareLoose排序回填latest清理_revisions、_attachments等内部元数据后PUT {packageUrl}/-rev/{_rev}回写 packument随后逐版本DELETEtarball{origin}/{tarballPath}/-rev/{_rev}并特意将 404 视为成功——部分 registry 会在 packument 更新时自动清理 tarball全部取消发布unpublishAll默认拒绝——不带--force会抛出UNPUBLISH_CONFIRM列出全部版本并给出保护性说明提示可用pnpm unpublish pkgversion删单个版本带--force后执行DELETE {packageUrl}/-rev/{_rev}删除整个包若 registry 返回 405 则抛UNPUBLISH_FORBIDDEN提示改用 deprecate 或联系平台支持。所有写请求经由otpSession.run统一处理401若为 OTP 挑战则自动应答并重试web 流或经典输入非 OTP 的401视为普通认证失败——同一运行内多个版本共享一次 OTP 会话避免重复认证。其余命令速览star / unstar / stars / whoami / ping / searchstar 与 unstarpnpm star package pnpm unstar package pnpm stars [user]star/common.ts 中performStarAction实现了三级降级策略首选现代端点PUT|DELETE /-/user/v1/starbody{ name, package }失败后尝试替代端点/-/user/package/{escapedName}/star再失败400/404/405/500则进入legacy 流程先whoami获取用户名读取完整 packument在users字段中增删当前用户pkgData.users[username] true/delete随后PUT回写带-rev版本号。未登录时抛STAR_UNAUTHORIZED。starsstars.ts列出指定用户的收藏包不带用户时要求登录先whoami得到当前用户再查询/-/user/{user}/stars备选/-/util/user/{user}/stars输出包名列表。whoami / ping / searchwhoamiGET ./-/whoami返回当前登录用户名无认证头直接抛WHOAMI_UNAUTHORIZEDpingGET ./-/ping?writetrue关闭重试retry: { retries: 0 }输出PING url/PONG 耗时msregistry 返回的 JSON 详情会一并展示不可达或非 2xx 抛PING_ERRORsearchGET ./-/v1/search?textquerysizen--search-limit控制结果数默认 20--json输出结构化结果支持s/se/find别名。错误处理与安全边界所有命令统一使用PnpmError(code, message)错误体系错误码按命令与场景命名便于上层精准处理。常见的跨命令错误码包括错误码触发场景UNAUTHORIZED/WHOAMI_UNAUTHORIZED/STAR_UNAUTHORIZED/TEAM_MISSING_AUTH未登录或缺少认证头FORBIDDEN已登录但无操作权限PACKAGE_NOT_FOUND/ORG_NOT_FOUND/TEAM_NOT_FOUND/USER_NOT_FOUND目标资源不存在404NO_VERSIONS/NO_MATCHING_VERSIONS/NOT_DEPRECATED版本元数据相关ACCESS_SET_STATUS_UNSCOPED/DIST_TAG_RM_LATEST/UNPUBLISH_CONFIRM语义保护性拒绝ACCESS_VALIDATION_ERRORregistry 返回 422 校验失败REGISTRY_ERROR/PING_ERROR/SEARCH_FAILED网络或服务端异常安全层面有两处值得注意一是readErrorBody对 registry 错误响应体的 64KB 限量读取与截断标记二是多个命令在拼接错误信息前对响应文本做sanitize/sanitizeInline过滤剔除控制字符防止不可信响应内容污染终端或日志。测试验证如何确认命令行为模块自带的 test/ 目录以 Jestpreset 为pnpm/jest-config/with-registry覆盖了全部命令测试思路可归纳为三类端到端闭环如 deprecate.ts先在本地 mock registryhttp://localhost:{REGISTRY_MOCK_PORT}token 由pnpm/testing.registry-mock提供发布包再执行目标命令最后用pnpm view断言 registry 状态HTTP 级断言如 dist-tag.ts 的 scoped-auth 用例用pnpm/testing.mock-agent拦截请求直接校验请求路径、authorization头如Bearer scoped-token与响应体命令默认行为如dist-tag ls不带子命令、owner ls默认列出协作者等验证无子命令时的兼容逻辑。总结pnpm/registry-access.commands是 pnpm 11 中registry 运维能力的集中载体它以 13 个命令覆盖了从弃用、权限、标签、协作者/团队到取消发布、收藏、连通性检测的完整操作面。从源码可以看出几条贯穿始终的设计原则统一复用所有命令共享parsePackageSpec、normalizeRegistryUrl、认证头生成与受限错误体读取等基础设施兼容 npm 语义命令形态与默认行为对齐 npm CLI如dist-tag ls默认、team ls兜底同时保留access public/restricted等废弃形态的兼容转换安全优先unpublish --force保护、latest标签保护、scoped 包权限约束、不可信响应体限量读取均为写操作设定了明确边界双模认证web OTP 自动挑战与--otplegacy 模式按需切换兼顾易用性与传统环境。如需进一步深入可从 模块入口 出发按命令逐一阅读 src/ 下的实现并以 test/ 中的用例作为行为规格快速建立对 pnpm registry 协议层的完整认知。【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考