1"use strict";(self.webpackChunkbackstage_microsite=self.webpackChunkbackstage_microsite||[]).push([["13404"],{472262(e,n,t){t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>d,default:()=>h,frontMatter:()=>c,metadata:()=>s,toc:()=>a});var s=t(398746),i=t(474848),r=t(28453);let c={id:"naming-patterns",title:"Backend System Naming Patterns",sidebar_label:"Naming Patterns",description:"Naming patterns in the backend system"},d,l={},a=[{value:"Plugins",id:"plugins",level:3},{value:"Modules",id:"modules",level:3},{value:"Extensions",id:"extensions",level:3},{value:"Services",id:"services",level:3}];function o(e){let n={code:"code",h3:"h3",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"These are the naming patterns to adhere to within the backend system. They help us keep exports consistent across packages and make it easier to understand the usage and intent of exports."}),"\n",(0,i.jsx)(n.p,{children:"As a rule, all names should be camel case, with the exceptions of plugin and module IDs, which should be kebab case."}),"\n",(0,i.jsx)(n.h3,{id:"plugins",children:"Plugins"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Description"}),(0,i.jsx)(n.th,{children:"Pattern"}),(0,i.jsx)(n.th,{children:"Examples"}),(0,i.jsx)(n.th,{children:"Notes"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"export"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<camelId>Plugin"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"catalogPlugin"}),", ",(0,i.jsx)(n.code,{children:"userSettingsPlugin"})]}),(0,i.jsx)(n.td,{})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ID"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"'<kebab-id>'"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"'catalog'"}),", ",(0,i.jsx)(n.code,{children:"'user-settings'"})]}),(0,i.jsx)(n.td,{children:"letters, digits, and dashes, starting with a letter"})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"export const userSettingsPlugin = createBackendPlugin({\n pluginId: 'user-settings',\n ...\n})\n"})}),"\n",(0,i.jsx)(n.h3,{id:"modules",children:"Modules"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Description"}),(0,i.jsx)(n.th,{children:"Pattern"}),(0,i.jsx)(n.th,{children:"Examples"}),(0,i.jsx)(n.th,{children:"Notes"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"export"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<pluginId>Module<ModuleId>"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"catalogModuleGithubEntityProvider"})}),(0,i.jsx)(n.td,{})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ID"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"'<module-id>'"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"'github-entity-provider'"})}),(0,i.jsx)(n.td,{children:"letters, digits, and dashes, starting with a letter"})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"export const catalogModuleGithubEntityProvider = createBackendModule({\n pluginId: 'catalog',\n moduleId: 'github-entity-provider',\n ...\n})\n"})}),"\n",(0,i.jsx)(n.h3,{id:"extensions",children:"Extensions"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Description"}),(0,i.jsx)(n.th,{children:"Pattern"}),(0,i.jsx)(n.th,{children:"Examples"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Interface"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<PluginId><Name>ExtensionPoint"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"CatalogProcessingExtensionPoint"})})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Reference"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<pluginId><Name>ExtensionPoint"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"catalogProcessingExtensionPoint"})})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ID"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"'<pluginId>.<name>'"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"'catalog.processing'"}),", ",(0,i.jsx)(n.code,{children:"'foo.barBaz'"})]})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"export interface CatalogProcessingExtensionPoint {\n ...\n}\n\nexport const catalogProcessingExtensionPoint = createExtensionPoint<CatalogProcessingExtensionPoint>({\n id: 'catalog.processing',\n ...\n})\n"})}),"\n",(0,i.jsx)(n.h3,{id:"services",children:"Services"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Description"}),(0,i.jsx)(n.th,{children:"Pattern"}),(0,i.jsx)(n.th,{children:"Examples"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Interface"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<Name>Service"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"LoggerService"}),", ",(0,i.jsx)(n.code,{children:"DatabaseService"})]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Reference"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<name>ServiceRef"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"loggerServiceRef"}),", ",(0,i.jsx)(n.code,{children:"databaseServiceRef"})]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ID"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<pluginId>.<name>"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"'core.rootHttpRouter'"}),", ",(0,i.jsx)(n.code,{children:"'catalog.catalogClient'"})]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Factory"}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"<name>ServiceFactory"})}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"loggerServiceFactory"}),", ",(0,i.jsx)(n.code,{children:"databaseServiceFactory"})]})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-ts",children:"export interface CatalogClientService {\n ...\n}\n\nexport const catalogClientServiceRef = createServiceRef<CatalogClientService>({\n id: 'catalog.catalogClient',\n ...\n})\n\nexport const catalogClientServiceFactory = createServiceFactory({\n service: catalogClientServiceRef,\n ...\n})\n"})}),"\n",(0,i.jsxs)(n.p,{children:["An exception to the above service reference naming pattern has been made for all of the core services in the core API. The ",(0,i.jsx)(n.code,{children:"@backstage/backend-plugin-api"})," makes all core service references available via a single ",(0,i.jsx)(n.code,{children:"coreServices"})," collection. Likewise, the ",(0,i.jsx)(n.code,{children:"@backstage/backend-test-utils"})," exports all mock service implementations via a single ",(0,i.jsx)(n.code,{children:"mockServices"})," collection. This means that the table above is slightly misleading, since ",(0,i.jsx)(n.code,{children:"loggerServiceRef"})," and ",(0,i.jsx)(n.code,{children:"databaseServiceRef"})," are instead available as ",(0,i.jsx)(n.code,{children:"coreServices.logger"})," and ",(0,i.jsx)(n.code,{children:"coreService.database"}),". We recommend that plugins avoid this patterns unless they have a very large number of services that they need to export."]}
1),"\n",(0,i.jsxs)(n.p,{children:["While it is often preferred to prefix root scoped services with ",(0,i.jsx)(n.code,{children:"Root"}),", it is not required. For example, ",(0,i.jsx)(n.code,{children:"RootHttpRouterService"})," and ",(0,i.jsx)(n.code,{children:"RootLifecycleService"})," follow this pattern, but ",(0,i.jsx)(n.code,{children:"ConfigService"})," doesn't and it is a root scoped service."]})]})}function h(e={}){let{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},28453(e,n,t){t.d(n,{R:()=>c,x:()=>d});var s=t(296540);let i={},r=s.createContext(i);function c(e){let n=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:n},e.children)}},398746(e){e.exports=JSON.parse('{"id":"backend-system/architecture/naming-patterns","title":"Backend System Naming Patterns","description":"Naming patterns in the backend system","source":"@site/versioned_docs/version-stable/backend-system/architecture/08-naming-patterns.md","sourceDirName":"backend-system/architecture","slug":"/backend-system/architecture/naming-patterns","permalink":"/docs/backend-system/architecture/naming-patterns","draft":false,"unlisted":false,"editUrl":"https://github.com/backstage/backstage/edit/master/docs/backend-system/architecture/08-naming-patterns.md","tags":[],"version":"stable","sidebarPosition":8,"frontMatter":{"id":"naming-patterns","title":"Backend System Naming Patterns","
1sidebar_label":"Naming Patterns","description":"Naming patterns in the backend system"},"sidebar":"docs","previous":{"title":"Feature Loaders","permalink":"/docs/backend-system/architecture/feature-loaders"},"next":{"title":"Building Backends","permalink":"/docs/building-backends/generated-index"}}')}}]);
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.