PageSourceSearch

https://postgraphile.org/assets/js/d31fae99.f33f2444.js

js postgraphile.org collected 2026-10-03 19:03:42 UTC 7,140 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunk_localrepo_postgraphile_website=globalThis.webpackChunk_localrepo_postgraphile_website||[]).push([[2909],{27420(e,n,t){t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"smart-tags-file","title":"The postgraphile.tags.json5 file","description":"You can load TagsFilePlugin as part of your configuration to have","source":"@site/versioned_docs/version-5/smart-tags-file.md","sourceDirName":".","slug":"/smart-tags-file","permalink":"/postgraphile/5/smart-tags-file","draft":false,"unlisted":false,"editUrl":"https://github.com/graphile/crystal/tree/main/postgraphile/website/postgraphile/smart-tags-file.md","tags":[],"version":"5","lastUpdatedAt":1761669037000,"frontMatter":{"title":"The postgraphile.tags.json5 file"},"sidebar":"docs","previous":{"title":"Smart Tags","permalink":"/postgraphile/5/smart-tags"},"next":{"title":"Smart Comments","permalink":"/postgraphile/5/smart-comments"}}');var i=t(31085),a=t(71184);const r={title:"The postgraphile.tags.json5 file"},o=void 0,l={},d=[{value:"Merging/Overriding",id:"mergingoverriding",level:3},{value:"File format",id:"file-format",level:3},{value:"Reading from an alternative path",id:"reading-from-an-alternative-path",level:2},{value:"Going further",id:"going-further",level:3}];function g(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["You can load ",(0,i.jsx)(n.code,{children:"TagsFilePlugin"})," as part of your configuration to have\nPostGraphile read a ",(0,i.jsx)(n.code,{children:"postgraphile.tags.json5"})," file from the current directory\nand process the tags and descriptions therein."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",metastring:'title="graphile.config.mjs"',children:'import { TagsFilePlugin } from "postgraphile/utils";\n\nexport default {\n  // ...\n  plugins: [TagsFilePlugin],\n};\n'})}),"\n",(0,i.jsx)(n.h3,{id:"mergingoverriding",children:"Merging/Overriding"}),"\n",(0,i.jsxs)(n.p,{children:["If you provide a description for an entity in ",(0,i.jsx)(n.code,{children:"postgraphile.tags.json5"})," then\nthat description will override any previous descriptions."]}),"\n",(0,i.jsxs)(n.p,{children:["If you provide tags for an entity in ",(0,i.jsx)(n.code,{children:"postgraphile.tags.json5"}),", those tags will\nbe ",(0,i.jsx)(n.em,{children:"merged"})," with previous tags overriding tags with the same names but retaining\nother tags."]}),"\n",(0,i.jsx)(n.h3,{id:"file-format",children:"File format"}),"\n",(0,i.jsxs)(n.p,{children:["The file is in JSON5 (you can just use regular JSON if you prefer, but the\nextension must be ",(0,i.jsx)(n.code,{children:".json5"}),") and is formatted like this:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json5",children:'{\n  version: 1,\n  config: {\n    /*\n     * There can be entries here for:\n     *\n     * - `class`: for tables, composite types, views and materialized views\n     * - `attribute`: for columns/attributes (of any \'class\' type)\n     * - `constraint`: for table constraints\n     * - `procedure`: for functions/procedures\n     */\n    class: {\n      /*\n       * The next level describes the named type. We\'ve just used the table\n       * name `"post"` but it could be `"my_schema.post"` if you have multiple\n       * tables with the same name and you don\'t want this rule to apply to\n       * all of them.\n       */\n      post: {\n        /*\n         * This will override the description sourced from the PostgreSQL COMMENT.\n         */\n        description: "A post within our forum.",\n\n        /*\n         * Add tags specific to the \'post\' table here. You can omit this if you\n         * don\'t want to add any tags.\n         */\n        tags: {\n          foreignKey: [\n            "(default_user_id) references user (id)|@fieldName defaultUser",\n            "(organization_id) references organization (id)|@fieldName organization",\n          ],\n        },\n\n        /*\n         * We\'ve added a shortcut to class-types so you can tag/describe\n         * columns at the same time of the class.\n         */\n        attribute: {\n          /*\n           * Assuming `body` is one of the columns in the \'post\' table.\n           */\n          body: {\n            /*\n             * Optional description, if provided overrides the PostgreSQL\n             * `COMMENT ON COLUMN post.body`.\n             */\n            description: "The body of the post",\n            tags: {\n              /*\n               * Here we indicate that the \'body\' field will not be available\n               * in the update mutation.\n               */\n              omit: "update",\n            },\n          },\n        },\n      },\n    },\n  },\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"reading-from-an-alternative-path",children:"Reading from an alternative path"}),"\n",(0,i.jsxs)(n.p,{children:["If you want to store your tags in a different file (e.g.\n",(0,i.jsx)(n.code,{children:"postgraphile.tags.json"}
1)," to support a wider range of parsers) then you can use\na custom plugin instead:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",metastring:'title="graphile.config.mjs"',children:'import { pgSmartTagsFromFile } from "postgraphile/utils";\n\nexport default {\n  // ...\n  plugins: [\n    pgSmartTagsFromFile(\n      // JSON and JSONC are also JSON5 compatible, so you can use these extensions if you prefer:\n      "/path/to/my/tags.file.json",\n    ),\n  ],\n};\n'})}),"\n",(0,i.jsxs)(n.p,{children:["If you're trying to avoid the ",(0,i.jsx)(n.code,{children:"fs"})," module (e.g. because you're using webpack)\nthen building and loading a basic smart tags plugin that doesn't read from the\nfile system might look something like this:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",metastring:'title="graphile.config.mjs"',children:'import { jsonPgSmartTags } from "postgraphile/utils";\n\nconst MySmartTagsPlugin = jsonPgSmartTags({\n  version: 1,\n  config: {\n    class: {\n      post: {\n        tags: {\n          omit: "update",\n        },\n      },\n    },\n  },\n});\n\nexport default {\n  // ...\n  plugins: [MySmartTagsPlugin],\n};\n'})}),"\n",(0,i.jsx)(n.h3,{id:"going-further",children:"Going further"}),"\n",(0,i.jsxs)(n.p,{children:["For greater flexibility, you might choose to check out\n",(0,i.jsx)(n.a,{href:"./pg-smart-tags",children:"pgSmartTags"}),"."]})]})}function c(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(g,{...e})}):g(e)}},71184(e,n,t){t.d(n,{R:()=>r,x:()=>o});var s=t(14041);const i={},a=s.createContext(i);function r(e){const n=s.useContext(a);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(a.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.