1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([["26780"],{57580(e,n,a){a.r(n),a.d(n,{metadata:()=>s,default:()=>g,frontMatter:()=>r,contentTitle:()=>i,toc:()=>p,assets:()=>d});var s=JSON.parse('{"id":"catalogs","title":"Catalogs","description":"\\"Catalogs\\" are a workspace feature for defining dependency version ranges as reusable constants. Constants defined in catalogs can later be referenced in package.json files.","source":"@site/versioned_docs/version-11.x/catalogs.md","sourceDirName":".","slug":"/catalogs","permalink":"/11.x/catalogs","draft":false,"unlisted":false,"editUrl":"https://github.com/pnpm/pnpm.io/edit/main/versioned_docs/version-11.x/catalogs.md","tags":[],"version":"11.x","lastUpdatedBy":"Zoltan Kochan","lastUpdatedAt":1789071248000,"frontMatter":{"id":"catalogs","title":"Catalogs"},"sidebar":"docs","previous":{"title":"Workspace task orchestration","permalink":"/11.x/workspace-task-orchestration"},"next":{"title":"Config Dependencies","permalink":"/11.x/config-dependencies"}}'),c=a(91987),l=a(67008),o=a(46285),t=a(15850);let r={id:"catalogs",title:"Catalogs"},i,d={},p=[{value:"The Catalog Protocol (<code>catalog:</code>)",id:"the-catalog-protocol-catalog",level:2},{value:"Advantages",id:"advantages",level:2},{value:"Defining Catalogs",id:"defining-catalogs",level:2},{value:"Default Catalog",id:"default-catalog",level:3},{value:"Named Catalogs",id:"named-catalogs",level:3},{value:"Workspace dependencies in a catalog",id:"workspace-dependencies-in-a-catalog",level:3},{value:"Publishing",id:"publishing",level:2},{value:"Settings",id:"settings",level:2},...o.RM,...t.RM];function h(e){let n={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(n.p,{children:['"',(0,c.jsx)(n.em,{children:"Catalogs"}),'" are a ',(0,c.jsx)(n.a,{href:"/11.x/workspaces",children:"workspace feature"})," for defining dependency version ranges as reusable constants. Constants defined in catalogs can later be referenced in ",(0,c.jsx)(n.code,{children:"package.json"})," files."]}),"\n",(0,c.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube-nocookie.com/embed/PuRUk4mV2jc",title:"pnpm Catalogs \u2014 A New Tool to Manage Dependencies in monorepos",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen"}),"\n",(0,c.jsxs)(n.h2,{id:"the-catalog-protocol-catalog",children:["The Catalog Protocol (",(0,c.jsx)(n.code,{children:"catalog:"}),")"]}),"\n",(0,c.jsxs)(n.p,{children:["Once a catalog is defined in ",(0,c.jsx)(n.code,{children:"pnpm-workspace.yaml"}),","]}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-yaml",metastring:'title="pnpm-workspace.yaml"',children:"packages:\n - packages/*\n\n# Define a catalog of version ranges.\ncatalog:\n react: ^18.3.1\n redux: ^5.0.1\n"})}),"\n",(0,c.jsxs)(n.p,{children:["The ",(0,c.jsx)(n.code,{children:"catalog:"})," protocol can be used instead of the version range itself."]}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-json",metastring:'title="packages/example-app/package.json"',children:'{\n "name": "@example/app",\n "dependencies": {\n "react": "catalog:",\n "redux": "catalog:"\n }\n}\n'})}),"\n",(0,c.jsxs)(n.p,{children:["This is equivalent to writing a version range (e.g. ",(0,c.jsx)(n.code,{children:"^18.3.1"}),") directly."]}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-json",metastring:'title="packages/example-app/package.json"',children:'{\n "name": "@example/app",\n "dependencies": {\n "react": "^18.3.1",\n "redux": "^5.0.1"\n }\n}\n'})}),"\n",(0,c.jsxs)(n.p,{children:["You may use the ",(0,c.jsx)(n.code,{children:"catalog:"})," protocol in the next fields:"]}),"\n",(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsxs)(n.li,{children:[(0,c.jsx)(n.code,{children:"package.json"}),":","\n",(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.code,{children:"dependencies"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.code,{children:"devDependencies"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.code,{children:"peerDepen
1dencies"})}),"\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.code,{children:"optionalDependencies"})}),"\n"]}),"\n"]}),"\n",(0,c.jsxs)(n.li,{children:[(0,c.jsx)(n.code,{children:"pnpm-workspace.yaml"}),"\n",(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsx)(n.li,{children:(0,c.jsx)(n.code,{children:"overrides"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,c.jsxs)(n.p,{children:["The ",(0,c.jsx)(n.code,{children:"catalog:"})," protocol allows an optional name after the colon (ex: ",(0,c.jsx)(n.code,{children:"catalog:name"}),") to specify which catalog should be used. When a name is omitted, the default catalog is used."]}),"\n",(0,c.jsxs)(n.p,{children:["Depending on the scenario, the ",(0,c.jsx)(n.code,{children:"catalog:"})," protocol offers a few ",(0,c.jsx)(n.a,{href:"#advantages",children:"advantages"})," compared to writing version ranges directly that are detailed next."]}),"\n",(0,c.jsx)(n.h2,{id:"advantages",children:"Advantages"}),"\n",(0,c.jsxs)(n.p,{children:["In a workspace (i.e. monorepo or multi-package repo) it's common for the same dependency to be used by many packages. Catalogs reduce duplication when authoring ",(0,c.jsx)(n.code,{children:"package.json"})," files and provide a few benefits in doing so:"]}),"\n",(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsxs)(n.li,{children:[(0,c.jsx)(n.strong,{children:"Maintain unique versions"})," \u2014 It's usually desirable to have only one version of a dependency in a workspace. Catalogs make this easier to maintain. Duplicated dependencies can conflict at runtime and cause bugs. Duplicates also increase size when using a bundler."]}),"\n",(0,c.jsxs)(n.li,{children:[(0,c.jsx)(n.strong,{children:"Easier upgrades"})," \u2014 When upgrading a dependency, only the catalog entry in ",(0,c.jsx)(n.code,{children:"pnpm-workspace.yaml"})," needs to be edited rather than all ",(0,c.jsx)(n.code,{children:"package.json"})," files using that dependency. This saves time \u2014 only one line needs to be changed instead of many."]}),"\n",(0,c.jsxs)(n.li,{children:[(0,c.jsx)(n.strong,{children:"Fewer merge conflicts"})," \u2014 Since ",(0,c.jsx)(n.code,{children:"package.json"})," files do not need to be edited when upgrading a dependency, git merge conflicts no longer happen in these files."]}),"\n"]}),"\n",(0,c.jsx)(n.h2,{id:"defining-catalogs",children:"Defining Catalogs"}),"\n",(0,c.jsxs)(n.p,{children:["Catalogs are defined in the ",(0,c.jsx)(n.code,{children:"pnpm-workspace.yaml"})," file. There are two ways to define catalogs."]}),"\n",(0,c.jsxs)(n.ol,{children:["\n",(0,c.jsxs)(n.li,{children:["Using the (singular) ",(0,c.jsx)(n.code,{children:"catalog"})," field to create a catalog named ",(0,c.jsx)(n.code,{children:"default"}),"."]}),"\n",(0,c.jsxs)(n.li,{children:["Using the (plural) ",(0,c.jsx)(n.code,{children:"catalogs"})," field to create arbitrarily named catalogs."]}),"\n"]}),"\n",(0,c.jsxs)(n.admonition,{type:"tip",children:[(0,c.jsxs)(n.p,{children:["If you have an existing workspace that you want to migrate to using catalogs, you can use the following ",(0,c.jsx)(n.a,{href:"https://go.codemod.com/pnpm-catalog",children:"codemod"}),":"]}),(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{children:"pnpx codemod pnpm/catalog\n"})})]}),"\n",(0,c.jsx)(n.h3,{id:"default-catalog",children:"Default Catalog"}),"\n",(0,c.jsxs)(n.p,{children:["The top-level ",(0,c.jsx)(n.code,{children:"catalog"})," field allows users to define a catalog named ",(0,c.jsx)(n.code,{children:"default"}),"."]}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-yaml",metastring:'title="pnpm-workspace.yaml"',children:"catalog:\n react: ^18.2.0\n react-dom: ^18.2.0\n"})}),"\n",(0,c.jsxs)(n.p,{children:["These version ranges can be referenced through ",(0,c.jsx)(n.code,{children:"catalog:default"}),". For the default catalog only, a special ",(0,c.jsx)(n.code,{children:"catalog:"})," shorthand can also be used. Think of ",(0,c.jsx)(n.code,{children:"catalog:"})," as a shorthand that expands to ",(0,c.jsx)(n.code,{children:"catalog:default"}),"."]}),"\n",(0,c.jsx)(n.h3,{id:"named-catalogs",children:"Named Catalogs"}),"\n",(0,c.jsxs)(n.p,{children:["Multiple catalogs with arbitrarily chosen names can be configured under the ",(0,c.jsx)(n.code,{children:"catalogs"})," key."]}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-yaml",metastring:'title="pnpm-workspace.yaml"',children:'catalogs:\n # Can be referenced through "catalog:react17"\n react17:\n react: ^17.0.2\n react-dom: ^17.0.2\n\n # Can be referenced through "catalog:react18"\n react18:\n react: ^18.2.0\n react-dom: ^18.2.0\n'})}),"\n",(0,c.jsx)(n.p,{children:"A default catalog can be defined alongside multiple named catalogs. This might be useful in a large multi-package repo that's migrating to a newer version of a dependency piecemeal."}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-yaml",metastring:'title="pnpm-workspace.yaml"',children:'catalog:\n react: ^16.14.0\n react-dom: ^16.14.0\n\ncatalogs:\n # Can be referenced through "catalog:react17"\n react17:\n react: ^17.0.2\n react-dom: ^17.0.2\n\n # Can be referenced through "catalog:react18"\n react18:\n react: ^18.2.0\n react-dom: ^18.2.0\n'})}),"\n",(0,c.jsx)(n.h3,{id:"workspace-dependencies-in-a-catalog",children:"Worksp
1ace dependencies in a catalog"}),"\n",(0,c.jsx)(n.p,{children:"Added in: v11.26.0"}),"\n",(0,c.jsxs)(n.p,{children:["A catalog entry may hold a ",(0,c.jsxs)(n.a,{href:"/11.x/workspaces#workspace-protocol-workspace",children:[(0,c.jsx)(n.code,{children:"workspace:"})," range"]}),", so the version a workspace dependency is linked by is written once too:"]}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-yaml",metastring:'title="pnpm-workspace.yaml"',children:"catalog:\n '@example/utils': workspace:^\n"})}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-json",metastring:'title="packages/example-app/package.json"',children:'{\n "name": "@example/app",\n "dependencies": {\n "@example/utils": "catalog:"\n }\n}\n'})}),"\n",(0,c.jsxs)(n.p,{children:["pnpm expands the ",(0,c.jsx)(n.code,{children:"catalog:"})," reference to ",(0,c.jsx)(n.code,{children:"workspace:^"})," and then links the workspace project, exactly as if the ",(0,c.jsx)(n.code,{children:"package.json"})," had declared ",(0,c.jsx)(n.code,{children:"workspace:^"})," itself. On publish both protocols are replaced, so the example above ships as ",(0,c.jsx)(n.code,{children:'"^1.4.0"'})," when ",(0,c.jsx)(n.code,{children:"@example/utils"})," is at 1.4.0."]}),"\n",(0,c.jsx)(n.h2,{id:"publishing",children:"Publishing"}),"\n",(0,c.jsxs)(n.p,{children:["The ",(0,c.jsx)(n.code,{children:"catalog:"})," protocol is removed when running ",(0,c.jsx)(n.code,{children:"pnpm publish"})," or ",(0,c.jsx)(n.code,{children:"pnpm pack"}),". This is similar to the ",(0,c.jsxs)(n.a,{href:"/11.x/workspaces#workspace-protocol-workspace",children:[(0,c.jsx)(n.code,{children:"workspace:"})," protocol"]}),", which is ",(0,c.jsx)(n.a,{href:"/11.x/workspaces#publishing-workspace-packages",children:"also replaced on publish"}),"."]}),"\n",(0,c.jsx)(n.p,{children:"For example,"}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-json",metastring:'title="packages/example-components/package.json"',children:'{\n "name": "@example/components",\n "dependencies": {\n "react": "catalog:react18",\n }\n}\n'})}),"\n",(0,c.jsx)(n.p,{children:"Will become the following on publish."}),"\n",(0,c.jsx)(n.pre,{children:(0,c.jsx)(n.code,{className:"language-json",metastring:'title="packages/example-components/package.json"',children:'{\n "name": "@example/components",\n "dependencies": {\n "react": "^18.3.1",\n }\n}\n'})}),"\n",(0,c.jsxs)(n.p,{children:["The ",(0,c.jsx)(n.code,{children:"catalog:"})," protocol replacement process allows the ",(0,c.jsx)(n.code,{children:"@example/components"})," package to be used by other workspaces or package managers."]}),"\n",(0,c.jsx)(n.h2,{id:"settings",children:"Settings"}),"\n","\n",(0,c.jsx)(o.Ay,{}),"\n","\n",(0,c.jsx)(t.Ay,{})]})}function g(e={}){let{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,c.jsx)(n,{...e,children:(0,c.jsx)(h,{...e})}):h(e)}},46285(e,n,a){a.d(n,{Ay:()=>t,RM:()=>l});var s=a(91987),c=a(67008);let l=[{value:"catalogMode",id:"catalogmode",level:3}];function o(e){let n={code:"code",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,c.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h3,{id:"catalogmode",children:"catalogMode"}),"\n",(0,s.jsx)(n.p,{children:"Added in: v10.12.1"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Default: ",(0,s.jsx)(n.strong,{children:"manual"})]}),"\n",(0,s.jsxs)(n.li,{children:["Type: ",(0,s.jsx)(n.strong,{children:"manual"}),", ",(0,s.jsx)(n.strong,{children:"strict"}),", ",(0,s.jsx)(n.strong,{children:"prefer"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Controls if and how dependencies are added to the default catalog, when running ",(0,s.jsx)(n.code,{children:"pnpm add"}),". There are three modes:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"strict"})," - only allows dependency versions from the catalog. Adding a dependency outside the catalog's version range will cause an error."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"prefer"})," - prefers catalog versions, but will fall back to direct dependencies if no compatible version is found."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"manual"}
1)," (default) - does not automatically add dependencies to the catalog."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Since v11.26.0, a specifier that names a location rather than a version is never moved into a catalog: local paths, local tarballs, tarball URLs, and ",(0,s.jsx)(n.code,{children:"workspace:<path>"})," ranges stay in the ",(0,s.jsx)(n.code,{children:"package.json"})," that declares them. Such a specifier is resolved relative to its own project, so one catalog entry could not mean the same directory for every project that references it."]})]})}function t(e={}){let{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(o,{...e})}):o(e)}},15850(e,n,a){a.d(n,{Ay:()=>t,RM:()=>l});var s=a(91987),c=a(67008);let l=[{value:"catalogPrune",id:"catalogprune",level:3}];function o(e){let n={code:"code",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,c.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("a",{id:"cleanupunusedcatalogs"}),"\n",(0,s.jsx)(n.h3,{id:"catalogprune",children:"catalogPrune"}),"\n",(0,s.jsxs)(n.p,{children:["Added in: v11.22.0 (as ",(0,s.jsx)(n.code,{children:"cleanupUnusedCatalogs"})," since v10.15.0)"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Default: ",(0,s.jsx)(n.strong,{children:"false"})]}),"\n",(0,s.jsxs)(n.li,{children:["Type: ",(0,s.jsx)(n.strong,{children:"Boolean"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["When set to ",(0,s.jsx)(n.code,{children:"true"}),", pnpm will remove unused catalog entries during installation."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"cleanupUnusedCatalogs"})," is the deprecated spelling of this setting and continues to work; when both are set, ",(0,s.jsx)(n.code,{children:"catalogPrune"})," wins."]})]})}function t(e={}){let{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(o,{...e})}):o(e)}},67008(e,n,a){a.d(n,{R:()=>o,x:()=>t});var s=a(71763);let c={},l=s.createContext(c);function o(e){let n=s.useContext(l);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:o(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.