Page Not Found
We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000000..e69de29bb2d diff --git a/404.html b/404.html new file mode 100644 index 00000000000..9f9ba54c757 --- /dev/null +++ b/404.html @@ -0,0 +1,17 @@ + + +
+ + +We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
[ENTITY]Saved
",id:"entitysaved",level:2},{value:"[ENTITY]Deleted
",id:"entitydeleted",level:2}],p={toc:c},u="wrapper";function d(e){let{components:t,...n}=e;return(0,i.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"subscription"},"Subscription"),(0,i.kt)("p",null,"When the GraphQL plugin is loaded, some subscriptions are automatically adding to\nthe GraphQL schema if the ",(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/sql-events")," plugin has been previously registered."),(0,i.kt)("p",null,"It's possible to avoid creating the subscriptions for a given entity by adding the ",(0,i.kt)("inlineCode",{parentName:"p"},"subscriptionIgnore")," config,\nlike so: ",(0,i.kt)("inlineCode",{parentName:"p"},"subscriptionIgnore: ['page']"),"."),(0,i.kt)("h2",{id:"entitysaved"},(0,i.kt)("inlineCode",{parentName:"h2"},"[ENTITY]Saved")),(0,i.kt)("p",null,"Published whenever an entity is saved, e.g. when the mutation ",(0,i.kt)("inlineCode",{parentName:"p"},"insert[ENTITY]")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"save[ENTITY]")," are called."),(0,i.kt)("h2",{id:"entitydeleted"},(0,i.kt)("inlineCode",{parentName:"h2"},"[ENTITY]Deleted")),(0,i.kt)("p",null,"Published whenever an entity is deleted, e.g. when the mutation ",(0,i.kt)("inlineCode",{parentName:"p"},"delete[ENTITY]")," is called.."))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/071c8372.695446df.js b/assets/js/071c8372.695446df.js
new file mode 100644
index 00000000000..2053337f5d3
--- /dev/null
+++ b/assets/js/071c8372.695446df.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[97306],{3905:(t,e,a)=>{a.d(e,{Zo:()=>u,kt:()=>f});var n=a(67294);function r(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function l(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function i(t){for(var e=1;eserver
",id:"server",level:3},{value:"metrics
",id:"metrics",level:3},{value:"plugins
",id:"plugins",level:3},{value:"watch
",id:"watch",level:3},{value:"composer
",id:"composer",level:3},{value:"openapi
",id:"openapi",level:4},{value:"openapi-configuration
",id:"openapi-configuration",level:5},{value:"telemetry
",id:"telemetry",level:3},{value:"Environment variable placeholders",id:"environment-variable-placeholders",level:2},{value:"Example",id:"example",level:3},{value:"Setting environment variables",id:"setting-environment-variables",level:3},{value:"Allowed placeholder names",id:"allowed-placeholder-names",level:3}],m={toc:s},c="wrapper";function d(e){let{components:t,...n}=e;return(0,i.kt)(c,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"configuration"},"Configuration"),(0,i.kt)("p",null,"Platformatic Composer configured with a configuration file. It supports the use\nof environment variables as setting values with ",(0,i.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,i.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,i.kt)("p",null,"If the Platformatic CLI finds a file in the current working directory matching\none of these filenames, it will automatically load it:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.json")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.json5")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.yml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.yaml")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.tml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.toml"))),(0,i.kt)("p",null,"Alternatively, a ",(0,i.kt)("a",{parentName:"p",href:"/docs/0.42.0/reference/cli#composer"},(0,i.kt)("inlineCode",{parentName:"a"},"--config")," option")," with a configuration\nfilepath can be passed to most ",(0,i.kt)("inlineCode",{parentName:"p"},"platformatic composer")," CLI commands."),(0,i.kt)("p",null,"The configuration examples in this reference use JSON."),(0,i.kt)("h3",{id:"supported-formats"},"Supported formats"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"left"},"Format"),(0,i.kt)("th",{parentName:"tr",align:"left"},"Extensions"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"JSON"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".json"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"JSON5"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".json5"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"YAML"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".yml"),", ",(0,i.kt)("inlineCode",{parentName:"td"},".yaml"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"TOML"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".tml"))))),(0,i.kt)("p",null,"Comments are supported by the JSON5, YAML and TOML file formats."),(0,i.kt)("h2",{id:"settings"},"Settings"),(0,i.kt)("p",null,"Configuration settings are organised into the following groups:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#server"},(0,i.kt)("inlineCode",{parentName:"a"},"server"))," ",(0,i.kt)("strong",{parentName:"li"},"(required)")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#composer"},(0,i.kt)("inlineCode",{parentName:"a"},"composer"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#metrics"},(0,i.kt)("inlineCode",{parentName:"a"},"metrics"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#plugins"},(0,i.kt)("inlineCode",{parentName:"a"},"plugins"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#telemetry"},(0,i.kt)("inlineCode",{parentName:"a"},"telemetry")))),(0,i.kt)("p",null,"Sensitive configuration settings containing sensitive data should be set using ",(0,i.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,i.kt)("h3",{id:"server"},(0,i.kt)("inlineCode",{parentName:"h3"},"server")),(0,i.kt)("p",null,"A ",(0,i.kt)("strong",{parentName:"p"},"required")," object with the following settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"hostname"))," (",(0,i.kt)("strong",{parentName:"p"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") \u2014 Hostname where Platformatic Composer server will listen for connections.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"port"))," (",(0,i.kt)("strong",{parentName:"p"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"number"),") \u2014 Port where Platformatic Composer server will listen for connections.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"healthCheck"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Enables the health check endpoint."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Powered by ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/under-pressure"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/under-pressure")),"."),(0,i.kt)("li",{parentName:"ul"},"The value can be an object, used to specify the interval between checks in milliseconds (default: ",(0,i.kt)("inlineCode",{parentName:"li"},"5000"),")")),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "server": {\n ...\n "healthCheck": {\n "interval": 2000\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"cors"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Configuration for Cross-Origin Resource Sharing (CORS) headers."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"All options will be passed to the ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-cors"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/cors"))," plugin. In order to specify a ",(0,i.kt)("inlineCode",{parentName:"li"},"RegExp")," object, you can pass ",(0,i.kt)("inlineCode",{parentName:"li"},"{ regexp: 'yourregexp' }"),",\nit will be automatically converted."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"logger"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") -- the ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server/#logger"},"logger configuration"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"pluginTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the number of milliseconds to wait for a Fastify plugin to load, see the ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server/#plugintimeout"},"fastify docs")," for more details.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"https"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") - Configuration for HTTPS supporting the following options."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"key")," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),", or ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),") - If ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," is a string, it specifies the private key to be used. If ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," is an object, it must have a ",(0,i.kt)("inlineCode",{parentName:"li"},"path")," property specifying the private key file. Multiple keys are supported by passing an array of keys."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"cert")," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),", or ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),") - If ",(0,i.kt)("inlineCode",{parentName:"li"},"cert")," is a string, it specifies the certificate to be used. If ",(0,i.kt)("inlineCode",{parentName:"li"},"cert")," is an object, it must have a ",(0,i.kt)("inlineCode",{parentName:"li"},"path")," property specifying the certificate file. Multiple certificates are supported by passing an array of keys.")))),(0,i.kt)("h3",{id:"metrics"},(0,i.kt)("inlineCode",{parentName:"h3"},"metrics")),(0,i.kt)("p",null,"Configuration for a ",(0,i.kt)("a",{parentName:"p",href:"https://prometheus.io/"},"Prometheus")," server that will export monitoring metrics\nfor the current server instance. It uses ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/SkeLLLa/fastify-metrics"},(0,i.kt)("inlineCode",{parentName:"a"},"fastify-metrics")),"\nunder the hood."),(0,i.kt)("p",null,"This setting can be a ",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or an ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),". If set to ",(0,i.kt)("inlineCode",{parentName:"p"},"true")," the Prometheus server will listen on ",(0,i.kt)("inlineCode",{parentName:"p"},"http://0.0.0.0:9090"),"."),(0,i.kt)("p",null,"Supported object properties:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"hostname"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 The hostname where Prometheus server will listen for connections."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"port"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"number"),") \u2014 The port where Prometheus server will listen for connections."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"auth"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") \u2014 Basic Auth configuration. ",(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"username"))," and ",(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"password"))," are required here\n(use ",(0,i.kt)("a",{parentName:"li",href:"#environment-variables"},"environment variables"),").")),(0,i.kt)("h3",{id:"plugins"},(0,i.kt)("inlineCode",{parentName:"h3"},"plugins")),(0,i.kt)("p",null,"An optional object that defines the plugins loaded by Platformatic Composer."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"paths"))," (",(0,i.kt)("strong",{parentName:"p"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"array"),"): an array of paths (",(0,i.kt)("inlineCode",{parentName:"p"},"string"),")\nor an array of objects composed as follows,"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"path")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): Relative path to plugin's entry point."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"options")," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): Optional plugin options."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"encapsulate")," (",(0,i.kt)("inlineCode",{parentName:"li"},"boolean"),"): if the path is a folder, it instruct Platformatic to not encapsulate those plugins."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"maxDepth")," (",(0,i.kt)("inlineCode",{parentName:"li"},"integer"),"): if the path is a folder, it limits the depth to load the content from."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"typescript"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),"): enable typescript compilation. A ",(0,i.kt)("inlineCode",{parentName:"p"},"tsconfig.json")," file is required in the same folder."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "plugins": {\n "paths": [{\n "path": "./my-plugin.js",\n "options": {\n "foo": "bar"\n }\n }]\n }\n}\n')))),(0,i.kt)("h3",{id:"watch"},(0,i.kt)("inlineCode",{parentName:"h3"},"watch")),(0,i.kt)("p",null,"Disable watching for file changes if set to ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),". It can also be customized with the following options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string[]"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"null"),"): List of glob patterns to ignore when watching for changes. If ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," or not specified, ignore rule is not applied. Ignore option doesn't work for typescript files.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"allow"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string[]"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['*.js', '**/*.js']"),"): List of glob patterns to allow when watching for changes. If ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," or not specified, allow rule is not applied. Allow option doesn't work for typescript files."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "watch": {\n "ignore": ["*.mjs", "**/*.mjs"],\n "allow": ["my-plugin.js", "plugins/*.js"]\n }\n}\n')))),(0,i.kt)("h3",{id:"composer"},(0,i.kt)("inlineCode",{parentName:"h3"},"composer")),(0,i.kt)("p",null,"Configure ",(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/composer")," specific settings such as ",(0,i.kt)("inlineCode",{parentName:"p"},"services")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"refreshTimeout"),":"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"services"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"array"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),") \u2014 is an array of objects that defines\nthe services managed by the composer. Each service object supports the following settings:"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"id"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A unique identifier for the service."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"origin"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A service origin. Skip this option if the service is executing inside of Platformatic Runtime. In this case, service id will be used instead of origin."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"openapi"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") - The configuration file used to compose OpenAPI specification. See the ",(0,i.kt)("a",{parentName:"li",href:"#openapi"},"openapi")," for details."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"proxy"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"false"),") - Service proxy configuration. If ",(0,i.kt)("inlineCode",{parentName:"li"},"false"),", the service proxy is disabled.",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"prefix")," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - Service proxy prefix. All service routes will be prefixed with this value."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"refreshTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"number"),") - The number of milliseconds to wait for check for changes in the service OpenAPI specification. If not specified, the default value is ",(0,i.kt)("inlineCode",{parentName:"li"},"1000"),".")))),(0,i.kt)("h4",{id:"openapi"},(0,i.kt)("inlineCode",{parentName:"h4"},"openapi")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"url"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A path of the route that exposes the OpenAPI specification. If a service is a Platformatic Service or Platformatic DB, use ",(0,i.kt)("inlineCode",{parentName:"li"},"/documentation/json")," as a value. Use this or ",(0,i.kt)("inlineCode",{parentName:"li"},"file")," option to specify the OpenAPI specification."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"file"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A path to the OpenAPI specification file. Use this or ",(0,i.kt)("inlineCode",{parentName:"li"},"url")," option to specify the OpenAPI specification."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"prefix"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A prefix for the OpenAPI specification. All service routes will be prefixed with this value."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"config"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A path to the OpenAPI configuration file. This file is used to customize the OpenAPI specification. See the ",(0,i.kt)("a",{parentName:"li",href:"#openapi-configuration"},"openapi-configuration")," for details.")),(0,i.kt)("h5",{id:"openapi-configuration"},(0,i.kt)("inlineCode",{parentName:"h5"},"openapi-configuration")),(0,i.kt)("p",null,"The OpenAPI configuration file is a JSON file that is used to customize the OpenAPI specification. It supports the following options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") - If ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the route will be ignored by the composer.\nIf you want to ignore a specific method, use the ",(0,i.kt)("inlineCode",{parentName:"p"},"ignore")," option in the nested method object."),(0,i.kt)("p",{parentName:"li"}," ",(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "paths": {\n "/users": {\n "ignore": true\n },\n "/users/{id}": {\n "get": { "ignore": true },\n "put": { "ignore": true }\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"alias")," (",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") - Use it create an alias for the route path. Original route path will be ignored."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "paths": {\n "/users": {\n "alias": "/customers"\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"rename"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") - Use it to rename composed route response fields.\nUse json schema format to describe the response structure. For now it works only for ",(0,i.kt)("inlineCode",{parentName:"p"},"200")," response."),(0,i.kt)("p",{parentName:"li"}," ",(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "paths": {\n "/users": {\n "responses": {\n "200": {\n "type": "array",\n "items": {\n "type": "object",\n "properties": {\n "id": { "rename": "user_id" },\n "name": { "rename": "first_name" }\n }\n }\n }\n }\n }\n }\n}\n')))),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("p",null," Composition of two remote services:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "composer": {\n "services": [\n {\n "id": "auth-service",\n "origin": "https://auth-service.com",\n "openapi": {\n "url": "/documentation/json",\n "prefix": "auth"\n }\n },\n {\n "id": "payment-service",\n "origin": "https://payment-service.com",\n "openapi": {\n "file": "./schemas/payment-service.json"\n }\n }\n ],\n "refreshTimeout": 1000\n }\n}\n')),(0,i.kt)("p",null," Composition of two local services inside of Platformatic Runtime:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "composer": {\n "services": [\n {\n "id": "auth-service",\n "openapi": {\n "url": "/documentation/json",\n "prefix": "auth"\n }\n },\n {\n "id": "payment-service",\n "openapi": {\n "file": "./schemas/payment-service.json"\n }\n }\n ],\n "refreshTimeout": 1000\n }\n}\n')),(0,i.kt)("h3",{id:"telemetry"},(0,i.kt)("inlineCode",{parentName:"h3"},"telemetry")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://opentelemetry.io/"},"Open Telemetry")," is optionally supported with these settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"serviceName"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 Name of the service as will be reported in open telemetry."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"version"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 Optional version (free form)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"skip"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"array"),"). Optional list of operations to skip when exporting telemetry defined ",(0,i.kt)("inlineCode",{parentName:"li"},"object")," with properties: ",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"method"),": GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"path"),". e.g.: ",(0,i.kt)("inlineCode",{parentName:"li"},"/documentation/json")," "))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"exporter"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),") \u2014 Exporter configuration. If not defined, the exporter defaults to ",(0,i.kt)("inlineCode",{parentName:"li"},"console"),". If an array of objects is configured, every object must be a valid exporter object. The exporter object has the following properties:",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"type"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 Exporter type. Supported values are ",(0,i.kt)("inlineCode",{parentName:"li"},"console"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"otlp"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"zipkin")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," (default: ",(0,i.kt)("inlineCode",{parentName:"li"},"console"),"). ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," is only supported for testing purposes. "),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"options"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") \u2014 These options are supported:",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"url"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 The URL to send the telemetry to. Required for ",(0,i.kt)("inlineCode",{parentName:"li"},"otlp")," exporter. This has no effect on ",(0,i.kt)("inlineCode",{parentName:"li"},"console")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," exporters."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"headers"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") \u2014 Optional headers to send with the telemetry. This has no effect on ",(0,i.kt)("inlineCode",{parentName:"li"},"console")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," exporters.")))))),(0,i.kt)("p",null,"Note that OTLP traces can be consumed by different solutions, like ",(0,i.kt)("a",{parentName:"p",href:"https://www.jaegertracing.io/"},"Jaeger"),". ",(0,i.kt)("a",{parentName:"p",href:"https://opentelemetry.io/ecosystem/vendors/"},"Here")," the full list."),(0,i.kt)("p",null," ",(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "telemetry": {\n "serviceName": "test-service",\n "exporter": {\n "type": "otlp",\n "options": {\n "url": "http://localhost:4318/v1/traces"\n }\n }\n }\n}\n')),(0,i.kt)("h2",{id:"environment-variable-placeholders"},"Environment variable placeholders"),(0,i.kt)("p",null,"The value for any configuration setting can be replaced with an environment variable\nby adding a placeholder in the configuration file, for example ",(0,i.kt)("inlineCode",{parentName:"p"},"{PLT_SERVER_LOGGER_LEVEL}"),"."),(0,i.kt)("p",null,"All placeholders in a configuration must be available as an environment variable\nand must meet the ",(0,i.kt)("a",{parentName:"p",href:"#allowed-placeholder-names"},"allowed placeholder name")," rules."),(0,i.kt)("h3",{id:"example"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="platformatic.service.json"',title:'"platformatic.service.json"'},'{\n "server": {\n "port": "{PORT}"\n }\n}\n')),(0,i.kt)("p",null,"Platformatic will replace the placeholders in this example with the environment\nvariables of the same name."),(0,i.kt)("h3",{id:"setting-environment-variables"},"Setting environment variables"),(0,i.kt)("p",null,"If a ",(0,i.kt)("inlineCode",{parentName:"p"},".env")," file exists it will automatically be loaded by Platformatic using\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/motdotla/dotenv"},(0,i.kt)("inlineCode",{parentName:"a"},"dotenv")),". For example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-plaintext",metastring:'title=".env"',title:'".env"'},"PLT_SERVER_LOGGER_LEVEL=info\nPORT=8080\n")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},".env")," file must be located in the same folder as the Platformatic configuration\nfile or in the current working directory."),(0,i.kt)("p",null,"Environment variables can also be set directly on the commmand line, for example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"PLT_SERVER_LOGGER_LEVEL=debug npx platformatic composer\n")),(0,i.kt)("h3",{id:"allowed-placeholder-names"},"Allowed placeholder names"),(0,i.kt)("p",null,"Only placeholder names prefixed with ",(0,i.kt)("inlineCode",{parentName:"p"},"PLT_"),", or that are in this allow list, will be\ndynamically replaced in the configuration file:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"PORT"))),(0,i.kt)("p",null,"This restriction is to avoid accidentally exposing system environment variables.\nAn error will be raised by Platformatic if it finds a configuration placeholder\nthat isn't allowed."),(0,i.kt)("p",null,"The default allow list can be extended by passing a ",(0,i.kt)("inlineCode",{parentName:"p"},"--allow-env")," CLI option with a\ncomma separated list of strings, for example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"npx platformatic composer --allow-env=HOST,SERVER_LOGGER_LEVEL\n")),(0,i.kt)("p",null,"If ",(0,i.kt)("inlineCode",{parentName:"p"},"--allow-env")," is passed as an option to the CLI, it will be merged with the\ndefault allow list."))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/09705aa7.58bc86ae.js b/assets/js/09705aa7.58bc86ae.js
new file mode 100644
index 00000000000..980e33b61c9
--- /dev/null
+++ b/assets/js/09705aa7.58bc86ae.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[19730],{61677:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>m,default:()=>f,frontMatter:()=>p,metadata:()=>c,toc:()=>d});var n=a(87462),l=(a(67294),a(3905)),i=a(74866),o=a(85162),r=a(3901);const p={toc_max_heading_level:4},m="Platformatic CLI",c={unversionedId:"reference/cli",id:"version-0.41.2/reference/cli",title:"Platformatic CLI",description:"Installation and usage",source:"@site/versioned_docs/version-0.41.2/reference/cli.md",sourceDirName:"reference",slug:"/reference/cli",permalink:"/docs/0.41.2/reference/cli",draft:!1,editUrl:"https://github.com/platformatic/oss/edit/main/versioned_docs/version-0.41.2/reference/cli.md",tags:[],version:"0.41.2",frontMatter:{toc_max_heading_level:4},sidebar:"docs",previous:{title:"Reference",permalink:"/docs/0.41.2/category/reference"},next:{title:"Platformatic Composer",permalink:"/docs/0.41.2/reference/composer/introduction"}},s={},d=[{value:"Installation and usage",id:"installation-and-usage",level:2},{value:"Commands",id:"commands",level:2},{value:"help",id:"help",level:3},{value:"compile",id:"compile",level:4},{value:"deploy",id:"deploy",level:4},{value:"gh",id:"gh",level:4},{value:"start",id:"start",level:4},{value:"upgrade",id:"upgrade",level:4},{value:"client",id:"client",level:3},{value:"help",id:"help-1",level:4},{value:"composer",id:"composer",level:3},{value:"help",id:"help-2",level:4},{value:"openapi schemas fetch",id:"openapi-schemas-fetch",level:4},{value:"start",id:"start-1",level:4},{value:"db",id:"db",level:3},{value:"compile",id:"compile-1",level:4},{value:"help",id:"help-3",level:4},{value:"migrations apply",id:"migrations-apply",level:4},{value:"migrations create",id:"migrations-create",level:4},{value:"migrations",id:"migrations",level:4},{value:"schema",id:"schema",level:4},{value:"seed",id:"seed",level:4},{value:"start",id:"start-2",level:4},{value:"types",id:"types",level:4},{value:"service",id:"service",level:3},{value:"compile",id:"compile-2",level:4},{value:"help",id:"help-4",level:4},{value:"schema",id:"schema-1",level:4},{value:"start",id:"start-3",level:4},{value:"frontend",id:"frontend",level:3},{value:"runtime",id:"runtime",level:3},{value:"compile",id:"compile-3",level:4},{value:"help",id:"help-5",level:4},{value:"start",id:"start-4",level:4},{value:"start",id:"start-5",level:3}],u={toc:d},k="wrapper";function f(e){let{components:t,...a}=e;return(0,l.kt)(k,(0,n.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"platformatic-cli"},"Platformatic CLI"),(0,l.kt)("h2",{id:"installation-and-usage"},"Installation and usage"),(0,l.kt)("p",null,"Install the Platformatic CLI as a dependency for your project:"),(0,l.kt)(i.Z,{groupId:"package-manager",mdxType:"Tabs"},(0,l.kt)(o.Z,{value:"npm",label:"npm",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"npm install platformatic\n"))),(0,l.kt)(o.Z,{value:"yarn",label:"Yarn",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"yarn add platformatic\n"))),(0,l.kt)(o.Z,{value:"pnpm",label:"pnpm",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"pnpm add platformatic\n")))),(0,l.kt)("p",null,"Once it's installed you can run it with:"),(0,l.kt)(i.Z,{groupId:"package-manager",mdxType:"Tabs"},(0,l.kt)(o.Z,{value:"npm",label:"npm",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"npx platformatic\n"))),(0,l.kt)(o.Z,{value:"yarn",label:"Yarn",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"yarn platformatic\n"))),(0,l.kt)(o.Z,{value:"pnpm",label:"pnpm",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"pnpm platformatic\n")))),(0,l.kt)("admonition",{type:"info"},(0,l.kt)("p",{parentName:"admonition"},"The ",(0,l.kt)("inlineCode",{parentName:"p"},"platformatic")," package can be installed globally, but installing it as a\nproject dependency ensures that everyone working on the project is using the\nsame version of the Platformatic CLI.")),(0,l.kt)("h2",{id:"commands"},"Commands"),(0,l.kt)("p",null,"The Platformatic CLI provides the following commands:"),(0,l.kt)(r.Z,{toc:d,minHeadingLevel:3,maxHeadingLevel:4,mdxType:"TOCInline"}),(0,l.kt)("h3",{id:"help"},"help"),(0,l.kt)("p",null,"Welcome to Platformatic. Available commands are:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"help")," - display this message."),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"help db
",id:"db",level:3},{value:"metrics
",id:"metrics",level:3},{value:"migrations
",id:"migrations",level:3},{value:"plugins
",id:"plugins",level:3},{value:"typescript
compilation options",id:"typescript-compilation-options",level:4},{value:"watch
",id:"watch",level:3},{value:"server
",id:"server",level:3},{value:"authorization
",id:"authorization",level:3},{value:"Example",id:"example",level:4},{value:"telemetry
",id:"telemetry",level:3},{value:"Environment variable placeholders",id:"environment-variable-placeholders",level:2},{value:"Example",id:"example-1",level:3},{value:"Setting environment variables",id:"setting-environment-variables",level:3},{value:"Allowed placeholder names",id:"allowed-placeholder-names",level:3},{value:"Sample Configuration",id:"sample-configuration",level:2}],m={toc:s},d="wrapper";function k(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"configuration"},"Configuration"),(0,i.kt)("p",null,"Platformatic DB is configured with a configuration file. It supports the use\nof environment variables as setting values with ",(0,i.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,i.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,i.kt)("p",null,"If the Platformatic CLI finds a file in the current working directory matching\none of these filenames, it will automatically load it:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.db.json")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.db.json5")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.db.yml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.db.yaml")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.db.tml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.db.toml"))),(0,i.kt)("p",null,"Alternatively, a ",(0,i.kt)("a",{parentName:"p",href:"/docs/reference/cli#db"},(0,i.kt)("inlineCode",{parentName:"a"},"--config")," option")," with a configuration\nfilepath can be passed to most ",(0,i.kt)("inlineCode",{parentName:"p"},"platformatic db")," CLI commands."),(0,i.kt)("p",null,"The configuration examples in this reference use JSON."),(0,i.kt)("h3",{id:"supported-formats"},"Supported formats"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"left"},"Format"),(0,i.kt)("th",{parentName:"tr",align:"left"},"Extensions"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"JSON"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".json"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"JSON5"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".json5"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"YAML"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".yml"),", ",(0,i.kt)("inlineCode",{parentName:"td"},".yaml"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"TOML"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".tml"))))),(0,i.kt)("p",null,"Comments are supported by the JSON5, YAML and TOML file formats."),(0,i.kt)("h2",{id:"settings"},"Settings"),(0,i.kt)("p",null,"Configuration settings are organised into the following groups:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#db"},(0,i.kt)("inlineCode",{parentName:"a"},"db"))," ",(0,i.kt)("strong",{parentName:"li"},"(required)")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#metrics"},(0,i.kt)("inlineCode",{parentName:"a"},"metrics"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#migrations"},(0,i.kt)("inlineCode",{parentName:"a"},"migrations"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#plugins"},(0,i.kt)("inlineCode",{parentName:"a"},"plugins"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#server"},(0,i.kt)("inlineCode",{parentName:"a"},"server"))," ",(0,i.kt)("strong",{parentName:"li"},"(required)")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#authorization"},(0,i.kt)("inlineCode",{parentName:"a"},"authorization"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#telemetry"},(0,i.kt)("inlineCode",{parentName:"a"},"telemetry")))),(0,i.kt)("p",null,"Sensitive configuration settings, such as a database connection URL that contains\na password, should be set using ",(0,i.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,i.kt)("h3",{id:"db"},(0,i.kt)("inlineCode",{parentName:"h3"},"db")),(0,i.kt)("p",null,"A ",(0,i.kt)("strong",{parentName:"p"},"required")," object with the following settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"connectionString"))," (",(0,i.kt)("strong",{parentName:"p"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") \u2014 Database connection URL."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Example: ",(0,i.kt)("inlineCode",{parentName:"li"},"postgres://user:password@my-database:5432/db-name")))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"}," ",(0,i.kt)("inlineCode",{parentName:"strong"},"schema"))," (array of ",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") - Currently supported only for postgres, schemas used tolook for entities. If not provided, the default ",(0,i.kt)("inlineCode",{parentName:"p"},"public")," schema is used."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Examples")))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},' "db": {\n "connectionString": "(...)",\n "schema": [\n "schema1", "schema2"\n ],\n ...\n\n },\n\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Platformatic DB supports MySQL, MariaDB, PostgreSQL and SQLite.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"graphql"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Controls the GraphQL API interface, with optional GraphiQL UI."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("p",{parentName:"li"},"Enables GraphQL support"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": true\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"Enables GraphQL support with GraphiQL"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "graphiql": true\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"It's possible to selectively ignore entites:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "ignore": {\n "categories": true\n }\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"It's possible to selectively ignore fields:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "ignore": {\n "categories": {\n "name": true\n }\n }\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"It's possible to add a custom GraphQL schema during the startup:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "schemaPath": "path/to/schema.graphql"\n }\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"openapi"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Enables OpenAPI REST support."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"If value is an object, all ",(0,i.kt)("a",{parentName:"li",href:"https://swagger.io/specification/"},"OpenAPI v3")," allowed properties can be passed. Also a ",(0,i.kt)("inlineCode",{parentName:"li"},"prefix")," property can be passed to set the OpenAPI prefix."),(0,i.kt)("li",{parentName:"ul"},"Platformatic DB uses ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-swagger"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/swagger"))," under the hood to manage this configuration.")),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("p",{parentName:"li"},"Enables OpenAPI"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": true\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"Enables OpenAPI with prefix"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "prefix": "/api"\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"Enables OpenAPI with options"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "info": {\n "title": "Platformatic DB",\n "description": "Exposing a SQL database as REST"\n }\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"You can for example add the ",(0,i.kt)("inlineCode",{parentName:"p"},"security")," section, so that Swagger will allow you to add the authentication header to your requests.\nIn the following code snippet, we're adding a Bearer token in the form of a ",(0,i.kt)("a",{parentName:"p",href:"/docs/reference/db/authorization/strategies#json-web-token-jwt"},"JWT"),":"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n ...\n "security": [{ "bearerAuth": [] }],\n "components": {\n "securitySchemes": {\n "bearerAuth": {\n "type": "http",\n "scheme": "bearer",\n "bearerFormat": "JWT"\n }\n }\n }\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"It's possible to selectively ignore entites:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "ignore": {\n "categories": true\n }\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"It's possible to selectively ignore fields:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "ignore": {\n "categories": {\n "name": true\n }\n }\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Key/value object that defines which database tables should not be mapped as API entities."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "ignore": {\n "versions": true // "versions" table will be not mapped with GraphQL/REST APIs\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"events"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Controls the support for events published by the SQL mapping layer.\nIf enabled, this option add support for GraphQL Subscription over WebSocket. By default it uses an in-process message broker.\nIt's possible to configure it to use Redis instead."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "events": {\n "connectionString": "redis://:password@redishost.com:6380/"\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"schemalock"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),") \u2014 Controls the caching of the database schema on disk.\nIf set to ",(0,i.kt)("inlineCode",{parentName:"p"},"true")," the database schema metadata is stored inside a ",(0,i.kt)("inlineCode",{parentName:"p"},"schema.lock")," file.\nIt's also possible to configure the location of that file by specifying a path, like so:"),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "schemalock": {\n "path": "./dbmetadata"\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"li"},"Starting Platformatic DB or running a migration will automatically create the schemalock file."))),(0,i.kt)("h3",{id:"metrics"},(0,i.kt)("inlineCode",{parentName:"h3"},"metrics")),(0,i.kt)("p",null,"Configuration for a ",(0,i.kt)("a",{parentName:"p",href:"https://prometheus.io/"},"Prometheus")," server that will export monitoring metrics\nfor the current server instance. It uses ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/SkeLLLa/fastify-metrics"},(0,i.kt)("inlineCode",{parentName:"a"},"fastify-metrics")),"\nunder the hood."),(0,i.kt)("p",null,"This setting can be a ",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or an ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),". If set to ",(0,i.kt)("inlineCode",{parentName:"p"},"true")," the Prometheus server will listen on ",(0,i.kt)("inlineCode",{parentName:"p"},"http://0.0.0.0:9090"),"."),(0,i.kt)("p",null,"Supported object properties:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"hostname"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 The hostname where Prometheus server will listen for connections."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"port"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"number"),") \u2014 The port where Prometheus server will listen for connections."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"auth"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") \u2014 Basic Auth configuration. ",(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"username"))," and ",(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"password"))," are required here\n(use ",(0,i.kt)("a",{parentName:"li",href:"#environment-variables"},"environment variables"),").")),(0,i.kt)("h3",{id:"migrations"},(0,i.kt)("inlineCode",{parentName:"h3"},"migrations")),(0,i.kt)("p",null,"Configures ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rickbergfalk/postgrator"},"Postgrator")," to run migrations against the database."),(0,i.kt)("p",null,"An optional object with the following settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"dir"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): Relative path to the migrations directory."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"autoApply"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"boolean"),", default: ",(0,i.kt)("inlineCode",{parentName:"li"},"false"),"): Automatically apply migrations when Platformatic DB server starts.")),(0,i.kt)("h3",{id:"plugins"},(0,i.kt)("inlineCode",{parentName:"h3"},"plugins")),(0,i.kt)("p",null,"An optional object that defines the plugins loaded by Platformatic DB."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"paths"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),"): an array of paths (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),")\nor an array of objects composed as follows,",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"path")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): Relative path to plugin's entry point."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"options")," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): Optional plugin options."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"encapsulate")," (",(0,i.kt)("inlineCode",{parentName:"li"},"boolean"),"): if the path is a folder, it instruct Platformatic to not\n",(0,i.kt)("a",{parentName:"li",href:"https://www.fastify.io/docs/latest/Reference/Encapsulation/"},"encapsulate")," those plugins,\nallowing decorators and hooks to be shared across all routes."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"maxDepth")," (",(0,i.kt)("inlineCode",{parentName:"li"},"integer"),"): if the path is a folder, it limits the depth to load the content from."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"typescript"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): enable TypeScript compilation. A ",(0,i.kt)("inlineCode",{parentName:"li"},"tsconfig.json")," file is required in the same folder.")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "plugins": {\n "paths": [{\n "path": "./my-plugin.js",\n "options": {\n "foo": "bar"\n }\n }]\n }\n}\n')),(0,i.kt)("h4",{id:"typescript-compilation-options"},(0,i.kt)("inlineCode",{parentName:"h4"},"typescript")," compilation options"),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"typescript")," option can also be an object to customize the compilation. Here are the supported options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"enabled")," (",(0,i.kt)("inlineCode",{parentName:"li"},"boolean"),"): enables compilation"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"tsConfig")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): path to the ",(0,i.kt)("inlineCode",{parentName:"li"},"tsconfig.json")," file relative to the configuration"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"outDir")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): the output directory of ",(0,i.kt)("inlineCode",{parentName:"li"},"tsconfig.json"),", in case ",(0,i.kt)("inlineCode",{parentName:"li"},"tsconfig.json")," is not available\nand and ",(0,i.kt)("inlineCode",{parentName:"li"},"enabled")," is set to ",(0,i.kt)("inlineCode",{parentName:"li"},"false")," (procution build)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"flags")," (array of ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): flags to be passed to ",(0,i.kt)("inlineCode",{parentName:"li"},"tsc"),". Overrides ",(0,i.kt)("inlineCode",{parentName:"li"},"tsConfig"),".\n")),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "plugins": {\n "paths": [{\n "path": "./my-plugin.js",\n "options": {\n "foo": "bar"\n }\n }],\n "typescript": {\n "enabled": false,\n "tsConfig": "./path/to/tsconfig.json",\n "outDir": "dist"\n }\n }\n}\n')),(0,i.kt)("h3",{id:"watch"},(0,i.kt)("inlineCode",{parentName:"h3"},"watch")),(0,i.kt)("p",null,"Disable watching for file changes if set to ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),". It can also be customized with the following options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string[]"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"null"),"): List of glob patterns to ignore when watching for changes. If ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," or not specified, ignore rule is not applied. Ignore option doesn't work for typescript files.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"allow"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string[]"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"['*.js', '**/*.js']"),"): List of glob patterns to allow when watching for changes. If ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," or not specified, allow rule is not applied. Allow option doesn't work for typescript files."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "watch": {\n "ignore": ["*.mjs", "**/*.mjs"],\n "allow": ["my-plugin.js", "plugins/*.js"]\n }\n}\n')))),(0,i.kt)("h3",{id:"server"},(0,i.kt)("inlineCode",{parentName:"h3"},"server")),(0,i.kt)("p",null,"A ",(0,i.kt)("strong",{parentName:"p"},"required")," object with the following settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"hostname"))," (",(0,i.kt)("strong",{parentName:"p"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") \u2014 Hostname where Platformatic DB server will listen for connections.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"port"))," (",(0,i.kt)("strong",{parentName:"p"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"number"),") \u2014 Port where Platformatic DB server will listen for connections.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"healthCheck"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Enables the health check endpoint."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Powered by ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/under-pressure"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/under-pressure")),"."),(0,i.kt)("li",{parentName:"ul"},"The value can be an object, used to specify the interval between checks in milliseconds (default: ",(0,i.kt)("inlineCode",{parentName:"li"},"5000"),")")),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "server": {\n ...\n "healthCheck": {\n "interval": 2000\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"cors"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Configuration for Cross-Origin Resource Sharing (CORS) headers."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"All options will be passed to the ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-cors"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/cors"))," plugin. In order to specify a ",(0,i.kt)("inlineCode",{parentName:"li"},"RegExp")," object, you can pass ",(0,i.kt)("inlineCode",{parentName:"li"},"{ regexp: 'yourregexp' }"),",\nit will be automatically converted"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"https"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") - Configuration for HTTPS supporting the following options."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"key")," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),", or ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),") - If ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," is a string, it specifies the private key to be used. If ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," is an object, it must have a ",(0,i.kt)("inlineCode",{parentName:"li"},"path")," property specifying the private key file. Multiple keys are supported by passing an array of keys."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"cert")," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),", or ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),") - If ",(0,i.kt)("inlineCode",{parentName:"li"},"cert")," is a string, it specifies the certificate to be used. If ",(0,i.kt)("inlineCode",{parentName:"li"},"cert")," is an object, it must have a ",(0,i.kt)("inlineCode",{parentName:"li"},"path")," property specifying the certificate file. Multiple certificates are supported by passing an array of keys."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"logger"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") -- the ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server/#logger"},"logger configuration"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"pluginTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the number of milliseconds to wait for a Fastify plugin to load")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"bodyLimit"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the maximum request body size in bytes")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"maxParamLength"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the maximum length of a request parameter")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"caseSensitive"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") -- if ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the router will be case sensitive")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignoreTrailingSlash"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") -- if ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the router will ignore the trailing slash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignoreTrailingSlash"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") -- if ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the router will ignore the trailing slash")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"connectionTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the milliseconds to wait for a new HTTP request")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"keepAliveTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the milliseconds to wait for a keep-alive HTTP request")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"maxRequestsPerSocket"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the maximum number of requests per socket")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"forceCloseConnections"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},'"idle"'),") -- if ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the server will close all connections when it is closed")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"requestTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"integer"),") -- the milliseconds to wait for a request to be completed")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"disableRequestLogging"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") -- if ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the request logger will be disabled")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"exposeHeadRoutes"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") -- if ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the router will expose HEAD routes")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"serializerOpts"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") -- the ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server/#serializeropts"},"serializer options"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"requestIdHeader"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"false"),") -- the name of the header that will contain the request id")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"requestIdLogLabel"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") -- Defines the label used for the request identifier when logging the request. default: ",(0,i.kt)("inlineCode",{parentName:"p"},"'reqId'"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"jsonShorthand"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") -- default: ",(0,i.kt)("inlineCode",{parentName:"p"},"true")," -- visit ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server/#jsonshorthand"},"fastify docs")," for more details")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"trustProxy"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"integer")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"string")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"String[]"),") -- default: ",(0,i.kt)("inlineCode",{parentName:"p"},"false")," -- visit ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server/#trustproxy"},"fastify docs")," for more details"))),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"See the ",(0,i.kt)("a",{parentName:"p",href:"https://www.fastify.io/docs/latest/Reference/Server"},"fastify docs")," for more details.")),(0,i.kt)("h3",{id:"authorization"},(0,i.kt)("inlineCode",{parentName:"h3"},"authorization")),(0,i.kt)("p",null,"An optional object with the following settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"adminSecret")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): A secret that should be sent in an\n",(0,i.kt)("inlineCode",{parentName:"li"},"x-platformatic-admin-secret")," HTTP header when performing GraphQL/REST API\ncalls. Use an ",(0,i.kt)("a",{parentName:"li",href:"#environment-variable-placeholders"},"environment variable placeholder"),"\nto securely provide the value for this setting."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"roleKey")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),", default: ",(0,i.kt)("inlineCode",{parentName:"li"},"X-PLATFORMATIC-ROLE"),"): The name of the key in user\nmetadata that is used to store the user's roles. See ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/user-roles-metadata#role-configuration"},"Role configuration"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"anonymousRole")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),", default: ",(0,i.kt)("inlineCode",{parentName:"li"},"anonymous"),"): The name of the anonymous role. See ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/user-roles-metadata#role-configuration"},"Role configuration"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"jwt")," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): Configuration for the ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#json-web-token-jwt"},"JWT authorization strategy"),".\nAny option accepted by ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-jwt"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/jwt")),"\ncan be passed in this object.",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"secret")," (required, ",(0,i.kt)("inlineCode",{parentName:"li"},"string")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): The secret key that the JWT was signed with.\nSee the ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-jwt#secret-required"},(0,i.kt)("inlineCode",{parentName:"a"},"@fastify/jwt")," documentation"),"\nfor accepted string and object values. Use an ",(0,i.kt)("a",{parentName:"li",href:"#environment-variable-placeholders"},"environment variable placeholder"),"\nto securely provide the value for this setting."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"jwks")," (",(0,i.kt)("inlineCode",{parentName:"li"},"boolean")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): Configure authorization with JSON Web Key Sets (JWKS). See the ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#json-web-key-sets-jwks"},"JWKS documentation"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"namespace")," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): Configure a ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#jwt-custom-claim-namespace"},"JWT Custom Claim Namespace"),"\nto avoid name collisions."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"webhook")," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),"): Configuration for the ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#webhook"},"Webhook authorization strategy"),".",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"url")," (required, ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),"): Webhook URL that Platformatic DB will make a\nPOST request to."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"rules")," (",(0,i.kt)("inlineCode",{parentName:"li"},"array"),"): Authorization rules that describe the CRUD actions that\nusers are allowed to perform against entities. See ",(0,i.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/rules"},"Rules"),"\ndocumentation.")),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("p",{parentName:"admonition"},"If an ",(0,i.kt)("inlineCode",{parentName:"p"},"authorization")," object is present, but no rules are specified, no CRUD\noperations are allowed unless ",(0,i.kt)("inlineCode",{parentName:"p"},"adminSecret")," is passed.")),(0,i.kt)("h4",{id:"example"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="platformatic.db.json"',title:'"platformatic.db.json"'},'{\n "authorization": {\n "jwt": {\n "secret": "{PLT_AUTHORIZATION_JWT_SECRET}"\n },\n "rules": [\n ...\n ]\n }\n}\n')),(0,i.kt)("h3",{id:"telemetry"},(0,i.kt)("inlineCode",{parentName:"h3"},"telemetry")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://opentelemetry.io/"},"Open Telemetry")," is optionally supported with these settings:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"serviceName"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 Name of the service as will be reported in open telemetry."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"version"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 Optional version (free form)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"skip"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"array"),"). Optional list of operations to skip when exporting telemetry defined ",(0,i.kt)("inlineCode",{parentName:"li"},"object")," with properties: ",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"method"),": GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"path"),". e.g.: ",(0,i.kt)("inlineCode",{parentName:"li"},"/documentation/json")," "))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"exporter"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"array"),") \u2014 Exporter configuration. If not defined, the exporter defaults to ",(0,i.kt)("inlineCode",{parentName:"li"},"console"),". If an array of objects is configured, every object must be a valid exporter object. The exporter object has the following properties:",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"type"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 Exporter type. Supported values are ",(0,i.kt)("inlineCode",{parentName:"li"},"console"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"otlp"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"zipkin")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," (default: ",(0,i.kt)("inlineCode",{parentName:"li"},"console"),"). ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," is only supported for testing purposes. "),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"options"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") \u2014 These options are supported:",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"url"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \u2014 The URL to send the telemetry to. Required for ",(0,i.kt)("inlineCode",{parentName:"li"},"otlp")," exporter. This has no effect on ",(0,i.kt)("inlineCode",{parentName:"li"},"console")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," exporters."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"headers"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") \u2014 Optional headers to send with the telemetry. This has no effect on ",(0,i.kt)("inlineCode",{parentName:"li"},"console")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"memory")," exporters.")))))),(0,i.kt)("p",null,"Note that OTLP traces can be consumed by different solutions, like ",(0,i.kt)("a",{parentName:"p",href:"https://www.jaegertracing.io/"},"Jaeger"),". ",(0,i.kt)("a",{parentName:"p",href:"https://opentelemetry.io/ecosystem/vendors/"},"Here")," the full list."),(0,i.kt)("p",null," ",(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "telemetry": {\n "serviceName": "test-service",\n "exporter": {\n "type": "otlp",\n "options": {\n "url": "http://localhost:4318/v1/traces"\n }\n }\n }\n}\n')),(0,i.kt)("h2",{id:"environment-variable-placeholders"},"Environment variable placeholders"),(0,i.kt)("p",null,"The value for any configuration setting can be replaced with an environment variable\nby adding a placeholder in the configuration file, for example ",(0,i.kt)("inlineCode",{parentName:"p"},"{PLT_SERVER_LOGGER_LEVEL}"),"."),(0,i.kt)("p",null,"All placeholders in a configuration must be available as an environment variable\nand must meet the ",(0,i.kt)("a",{parentName:"p",href:"#allowed-placeholder-names"},"allowed placeholder name")," rules."),(0,i.kt)("h3",{id:"example-1"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="platformatic.db.json"',title:'"platformatic.db.json"'},'{\n "db": {\n "connectionString": "{DATABASE_URL}"\n },\n "server": {\n "logger": {\n "level": "{PLT_SERVER_LOGGER_LEVEL}"\n },\n "port": "{PORT}"\n }\n}\n')),(0,i.kt)("p",null,"Platformatic will replace the placeholders in this example with the environment\nvariables of the same name."),(0,i.kt)("h3",{id:"setting-environment-variables"},"Setting environment variables"),(0,i.kt)("p",null,"If a ",(0,i.kt)("inlineCode",{parentName:"p"},".env")," file exists it will automatically be loaded by Platformatic using\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/motdotla/dotenv"},(0,i.kt)("inlineCode",{parentName:"a"},"dotenv")),". For example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-plaintext",metastring:'title=".env"',title:'".env"'},"PLT_SERVER_LOGGER_LEVEL=info\nPORT=8080\n")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},".env")," file must be located in the same folder as the Platformatic configuration\nfile or in the current working directory."),(0,i.kt)("p",null,"Environment variables can also be set directly on the commmand line, for example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"PLT_SERVER_LOGGER_LEVEL=debug npx platformatic db\n")),(0,i.kt)("h3",{id:"allowed-placeholder-names"},"Allowed placeholder names"),(0,i.kt)("p",null,"Only placeholder names prefixed with ",(0,i.kt)("inlineCode",{parentName:"p"},"PLT_"),", or that are in this allow list, will be\ndynamically replaced in the configuration file:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"PORT")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DATABASE_URL"))),(0,i.kt)("p",null,"This restriction is to avoid accidentally exposing system environment variables.\nAn error will be raised by Platformatic if it finds a configuration placeholder\nthat isn't allowed."),(0,i.kt)("p",null,"The default allow list can be extended by passing a ",(0,i.kt)("inlineCode",{parentName:"p"},"--allow-env")," CLI option with a\ncomma separated list of strings, for example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"npx platformatic db start --allow-env=HOST,SERVER_LOGGER_LEVEL\n# OR\nnpx platformatic start --allow-env=HOST,SERVER_LOGGER_LEVEL\n")),(0,i.kt)("p",null,"If ",(0,i.kt)("inlineCode",{parentName:"p"},"--allow-env")," is passed as an option to the CLI, it will be merged with the\ndefault allow list."),(0,i.kt)("h2",{id:"sample-configuration"},"Sample Configuration"),(0,i.kt)("p",null,"This is a bare minimum configuration for Platformatic DB. Uses a local ",(0,i.kt)("inlineCode",{parentName:"p"},"./db.sqlite")," SQLite database, with OpenAPI and GraphQL support."),(0,i.kt)("p",null,"Server will listen to ",(0,i.kt)("inlineCode",{parentName:"p"},"http://127.0.0.1:3042")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "server": {\n "hostname": "127.0.0.1",\n "port": "3042"\n },\n "db": {\n "connectionString": "sqlite://./db.sqlite",\n "graphiql": true,\n "openapi": true,\n "graphql": true\n }\n}\n')))}k.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/0f99474f.3897e1da.js b/assets/js/0f99474f.3897e1da.js
new file mode 100644
index 00000000000..1fe39950cb6
--- /dev/null
+++ b/assets/js/0f99474f.3897e1da.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[27494],{3905:(e,t,r)=>{r.d(t,{Zo:()=>l,kt:()=>m});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;tsave[ENTITY]
",id:"saveentity",level:2},{value:"Example",id:"example",level:3},{value:"insert[ENTITY]
",id:"insertentity",level:2},{value:"Example",id:"example-1",level:3},{value:"delete[ENTITIES]
",id:"deleteentities",level:2},{value:"Example",id:"example-2",level:3}],c={toc:p},u="wrapper";function m(e){let{components:n,...t}=e;return(0,a.kt)(u,(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"mutations"},"Mutations"),(0,a.kt)("p",null,"When the GraphQL plugin is loaded, some mutations are automatically adding to\nthe GraphQL schema."),(0,a.kt)("h2",{id:"saveentity"},(0,a.kt)("inlineCode",{parentName:"h2"},"save[ENTITY]")),(0,a.kt)("p",null,"Saves a new entity to the database or updates an existing entity.\nThis actually behaves as an ",(0,a.kt)("inlineCode",{parentName:"p"},"upsert"),", allowing both behaviours depending on the presence of the primary key field."),(0,a.kt)("h3",{id:"example"},"Example"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-js"},"'use strict'\n\nconst Fastify = require('fastify')\nconst graphqlPlugin = require('@platformatic/sql-graphql')\nconst sqlMapper = require('@platformatic/sql-mapper')\n\nasync function main() {\n const app = Fastify({\n logger: {\n level: 'info'\n }\n })\n app.register(sqlMapper, {\n connectionString: 'postgres://postgres:postgres@127.0.0.1/postgres',\n log: logger,\n })\n app.register(graphqlPlugin, {\n graphiql: true\n })\n const res = await app.inject({\n method: 'POST',\n url: '/graphql',\n body: {\n query: `\n mutation {\n savePage(input: { id: 3 title: \"Platformatic is cool!\" }) {\n id\n title\n }\n }\n `\n }\n })\n const result = await res.json()\n console.log(result.data) // { savePage: { id: '3', title: 'Platformatic is cool!' } }\n await app.close()\n}\n\nmain()\n")),(0,a.kt)("h2",{id:"insertentity"},(0,a.kt)("inlineCode",{parentName:"h2"},"insert[ENTITY]")),(0,a.kt)("p",null,"Inserts a new entity in the database."),(0,a.kt)("h3",{id:"example-1"},"Example"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-js"},"'use strict'\n\nconst Fastify = require('fastify')\nconst graphqlPlugin = require('@platformatic/sql-graphql')\nconst sqlMapper = require('@platformatic/sql-mapper')\n\nasync function main() {\n const app = Fastify({\n logger: {\n level: 'info'\n }\n })\n app.register(sqlMapper, {\n connectionString: 'postgres://postgres:postgres@127.0.0.1/postgres',\n log: logger,\n })\n app.register(graphqlPlugin, {\n graphiql: true\n })\n const res = await app.inject({\n method: 'POST',\n url: '/graphql',\n body: {\n query: `\n mutation {\n savePage(input: { title: \"Platformatic is cool!\" }) {\n id\n title\n }\n }\n `\n }\n })\n const result = await res.json()\n console.log(result.data) // { savePage: { id: '4', title: 'Platformatic is cool!' } }\n await app.close()\n}\n\nmain()\n")),(0,a.kt)("h2",{id:"deleteentities"},(0,a.kt)("inlineCode",{parentName:"h2"},"delete[ENTITIES]")),(0,a.kt)("p",null,"Deletes one or more entities from the database, based on the ",(0,a.kt)("inlineCode",{parentName:"p"},"where")," clause\npassed as an input to the mutation."),(0,a.kt)("h3",{id:"example-2"},"Example"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-js"},"'use strict'\n\nconst Fastify = require('fastify')\nconst graphqlPlugin = require('@platformatic/sql-graphql')\nconst sqlMapper = require('@platformatic/sql-mapper')\n\nasync function main() {\n const app = Fastify({\n logger: {\n level: 'info'\n }\n })\n app.register(sqlMapper, {\n connectionString: 'postgres://postgres:postgres@127.0.0.1/postgres',\n log: logger,\n })\n app.register(graphqlPlugin, {\n graphiql: true\n })\n const res = await app.inject({\n method: 'POST',\n url: '/graphql',\n body: {\n query: `\n mutation {\n deletePages(where: { id: { eq: \"3\" } }) {\n id\n title\n }\n }\n `\n }\n })\n const result = await res.json()\n console.log(result.data) // { deletePages: [ { id: '3', title: 'Platformatic is cool!' } ] }\n await app.close()\n}\n\nmain()\n")))}m.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/10e966f5.541d7376.js b/assets/js/10e966f5.541d7376.js
new file mode 100644
index 00000000000..a087bdadbeb
--- /dev/null
+++ b/assets/js/10e966f5.541d7376.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[25512],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t[ENTITY]Saved
",id:"entitysaved",level:2},{value:"[ENTITY]Deleted
",id:"entitydeleted",level:2}],p={toc:c},u="wrapper";function d(e){let{components:t,...n}=e;return(0,i.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"subscription"},"Subscription"),(0,i.kt)("p",null,"When the GraphQL plugin is loaded, some subscriptions are automatically adding to\nthe GraphQL schema if the ",(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/sql-events")," plugin has been previously registered."),(0,i.kt)("p",null,"It's possible to avoid creating the subscriptions for a given entity by adding the ",(0,i.kt)("inlineCode",{parentName:"p"},"subscriptionIgnore")," config,\nlike so: ",(0,i.kt)("inlineCode",{parentName:"p"},"subscriptionIgnore: ['page']"),"."),(0,i.kt)("h2",{id:"entitysaved"},(0,i.kt)("inlineCode",{parentName:"h2"},"[ENTITY]Saved")),(0,i.kt)("p",null,"Published whenever an entity is saved, e.g. when the mutation ",(0,i.kt)("inlineCode",{parentName:"p"},"insert[ENTITY]")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"save[ENTITY]")," are called."),(0,i.kt)("h2",{id:"entitydeleted"},(0,i.kt)("inlineCode",{parentName:"h2"},"[ENTITY]Deleted")),(0,i.kt)("p",null,"Published whenever an entity is deleted, e.g. when the mutation ",(0,i.kt)("inlineCode",{parentName:"p"},"delete[ENTITY]")," is called.."))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/10f0d52a.e3a82e0b.js b/assets/js/10f0d52a.e3a82e0b.js
new file mode 100644
index 00000000000..01b8b9be009
--- /dev/null
+++ b/assets/js/10f0d52a.e3a82e0b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[71931],{3905:(e,n,r)=>{r.d(n,{Zo:()=>c,kt:()=>m});var t=r(67294);function i(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function o(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function a(e){for(var n=1;nentity mapper
for plugins",id:"access-validation-on-entity-mapper-for-plugins",level:2},{value:"Skip authorization rules",id:"skip-authorization-rules",level:2},{value:"Avoid repetition of the same rule multiple times",id:"avoid-repetition-of-the-same-rule-multiple-times",level:2}],u={toc:p},c="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"rules"},"Rules"),(0,r.kt)("h2",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,"Authorization rules can be defined to control what operations users are\nable to execute via the REST or GraphQL APIs that are exposed by a Platformatic\nDB app."),(0,r.kt)("p",null,"Every rule must specify:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"role")," (required) \u2014 A role name. It's a string and must match with the role(s) set by an external authentication service."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"entity")," (optional) \u2014 The Platformatic DB entity to apply this rule to."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"entities")," (optional) \u2014 The Platformatic DB entities to apply this rule to."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"defaults")," (optional) \u2014 Configure entity fields that will be\n",(0,r.kt)("a",{parentName:"li",href:"#set-entity-fields-from-user-metadata"},"automatically set from user data"),"."),(0,r.kt)("li",{parentName:"ul"},"One entry for each supported CRUD operation: ",(0,r.kt)("inlineCode",{parentName:"li"},"find"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"save"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"delete"))),(0,r.kt)("p",null,"One of ",(0,r.kt)("inlineCode",{parentName:"p"},"entity")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"entities")," must be specified."),(0,r.kt)("h2",{id:"operation-checks"},"Operation checks"),(0,r.kt)("p",null,"Every entity operation \u2014 such as ",(0,r.kt)("inlineCode",{parentName:"p"},"find"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"insert"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"save")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"delete")," \u2014 can have\nauthorization ",(0,r.kt)("inlineCode",{parentName:"p"},"checks")," specified for them. This value can be ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," (operation disabled)\nor ",(0,r.kt)("inlineCode",{parentName:"p"},"true")," (operation enabled with no checks)."),(0,r.kt)("p",null,"To specify more fine-grained authorization controls, add a ",(0,r.kt)("inlineCode",{parentName:"p"},"checks")," field, e.g.:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "role": "user",\n "entity": "page",\n "find": {\n "checks": {\n "userId": "X-PLATFORMATIC-USER-ID"\n }\n },\n ...\n}\n\n')),(0,r.kt)("p",null,"In this example, when a user with a ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," role executes a ",(0,r.kt)("inlineCode",{parentName:"p"},"findPage"),", they can\naccess all the data that has ",(0,r.kt)("inlineCode",{parentName:"p"},"userId")," equal to the value in user metadata with\nkey ",(0,r.kt)("inlineCode",{parentName:"p"},"X-PLATFORMATIC-USER-ID"),"."),(0,r.kt)("p",null,"Note that ",(0,r.kt)("inlineCode",{parentName:"p"},'"userId": "X-PLATFORMATIC-USER-ID"')," is syntactic sugar for:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},' "find": {\n "checks": {\n "userId": {\n "eq": "X-PLATFORMATIC-USER-ID"\n }\n }\n }\n')),(0,r.kt)("p",null,"It's possible to specify more complex rules using all the ",(0,r.kt)("a",{parentName:"p",href:"/docs/0.41.1/reference/sql-mapper/entities/api#where-clause"},"supported where clause operators"),"."),(0,r.kt)("p",null,"Note that ",(0,r.kt)("inlineCode",{parentName:"p"},"userId")," MUST exist as a field in the database table to use this feature."),(0,r.kt)("h3",{id:"graphql-events-and-subscriptions"},"GraphQL events and subscriptions"),(0,r.kt)("p",null,"Platformatic DB supports GraphQL subscriptions and therefore db-authorization must protect them.\nThe check is performed based on the ",(0,r.kt)("inlineCode",{parentName:"p"},"find")," permissions, the only permissions that are supported are:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},"find: false"),", the subscription for that role is disabled"),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},"find: { checks: { [prop]: 'X-PLATFORMATIC-PROP' } }")," validates that the given prop is equal"),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},"find: { checks: { [prop]: { eq: 'X-PLATFORMATIC-PROP' } } }")," validates that the given prop is equal")),(0,r.kt)("p",null,"Conflicting rules across roles for different equality checks will not be supported."),(0,r.kt)("h2",{id:"restrict-access-to-entity-fields"},"Restrict access to entity fields"),(0,r.kt)("p",null,"If a ",(0,r.kt)("inlineCode",{parentName:"p"},"fields")," array is present on an operation, Platformatic DB restricts the columns on which the user can execute to that list.\nFor ",(0,r.kt)("inlineCode",{parentName:"p"},"save")," operations, the configuration must specify all the not-nullable fields (otherwise, it would fail at runtime).\nPlatformatic does these checks at startup."),(0,r.kt)("p",null,"Example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},' "rule": {\n "entity": "page",\n "role": "user",\n "find": {\n "checks": {\n "userId": "X-PLATFORMATIC-USER-ID"\n },\n "fields": ["id", "title"]\n }\n ...\n }\n')),(0,r.kt)("p",null,"In this case, only ",(0,r.kt)("inlineCode",{parentName:"p"},"id")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"title")," are returned for a user with a ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," role on the ",(0,r.kt)("inlineCode",{parentName:"p"},"page")," entity."),(0,r.kt)("h2",{id:"set-entity-fields-from-user-metadata"},"Set entity fields from user metadata"),(0,r.kt)("p",null,"Defaults are used in database insert and are default fields added automatically populated from user metadata, e.g.:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},' "defaults": {\n "userId": "X-PLATFORMATIC-USER-ID"\n },\n')),(0,r.kt)("p",null,"When an entity is created, the ",(0,r.kt)("inlineCode",{parentName:"p"},"userId")," column is used and populated using the value from user metadata."),(0,r.kt)("h2",{id:"programmatic-rules"},"Programmatic rules"),(0,r.kt)("p",null,"If it's necessary to have more control over the authorizations, it's possible to specify the rules programmatically, e.g.:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"\n app.register(auth, {\n jwt: {\n secret: 'supersecret'\n },\n rules: [{\n role: 'user',\n entity: 'page',\n async find ({ user, ctx, where }) {\n return {\n ...where,\n userId: {\n eq: user['X-PLATFORMATIC-USER-ID']\n }\n }\n },\n async delete ({ user, ctx, where }) {\n return {\n ...where,\n userId: {\n eq: user['X-PLATFORMATIC-USER-ID']\n }\n }\n },\n defaults: {\n userId: async function ({ user, ctx, input }) {\n match(user, {\n 'X-PLATFORMATIC-USER-ID': generated.shift(),\n 'X-PLATFORMATIC-ROLE': 'user'\n })\n return user['X-PLATFORMATIC-USER-ID']\n }\n\n },\n async save ({ user, ctx, where }) {\n return {\n ...where,\n userId: {\n eq: user['X-PLATFORMATIC-USER-ID']\n }\n }\n }\n }]\n })\n\n")),(0,r.kt)("p",null,"In this example, the ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," role can delete all the posts edited before yesterday:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"}," app.register(auth, {\n jwt: {\n secret: 'supersecret'\n },\n roleKey: 'X-PLATFORMATIC-ROLE',\n anonymousRole: 'anonymous',\n rules: [{\n role: 'user',\n entity: 'page',\n find: true,\n save: true,\n async delete ({ user, ctx, where }) {\n return {\n ...where,\n editedAt: {\n lt: yesterday\n }\n }\n },\n defaults: {\n userId: 'X-PLATFORMATIC-USER-ID'\n }\n }]\n })\n")),(0,r.kt)("h2",{id:"access-validation-on-entity-mapper-for-plugins"},"Access validation on ",(0,r.kt)("inlineCode",{parentName:"h2"},"entity mapper")," for plugins"),(0,r.kt)("p",null,"To assert that a specific user with it's ",(0,r.kt)("inlineCode",{parentName:"p"},"role(s)")," has the correct access rights to use entities on a ",(0,r.kt)("inlineCode",{parentName:"p"},"platformatic plugin")," the context should be passed to the ",(0,r.kt)("inlineCode",{parentName:"p"},"entity mapper")," in order to verify it's permissions like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"//plugin.js\n\napp.post('/', async (req, reply) => {\n const ctx = req.createPlatformaticCtx()\n \n await app.platformatic.entities.movie.find({\n where: { /*...*/ },\n ctx\n })\n})\n\n")),(0,r.kt)("h2",{id:"skip-authorization-rules"},"Skip authorization rules"),(0,r.kt)("p",null,"In custom plugins, it's possible to skip the authorization rules on entities programmatically by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"skipAuth")," flag to ",(0,r.kt)("inlineCode",{parentName:"p"},"true")," or not passing a ",(0,r.kt)("inlineCode",{parentName:"p"},"ctx"),", e.g.:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"// this works even if the user's role doesn't have the `find` permission.\nconst result = await app.platformatic.entities.page.find({skipAuth: true, ...})\n")),(0,r.kt)("p",null,"This has the same effect:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"// this works even if the user's role doesn't have the `find` permission\nconst result = await app.platformatic.entities.page.find() // no `ctx`\n")),(0,r.kt)("p",null,"This is useful for custom plugins for which the authentication is not necessary, so there is no user role set when invoked."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Skip authorization rules is not possible on the automatically generated REST and GraphQL APIs.")),(0,r.kt)("h2",{id:"avoid-repetition-of-the-same-rule-multiple-times"},"Avoid repetition of the same rule multiple times"),(0,r.kt)("p",null,"Very often we end up writing the same rules over and over again.\nInstead, it's possible to condense the rule for multiple entities on a single entry:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"}," app.register(auth, {\n jwt: {\n secret: 'supersecret'\n },\n roleKey: 'X-PLATFORMATIC-ROLE',\n anonymousRole: 'anonymous',\n rules: [{\n role: 'anonymous',\n entities: ['category', 'page'],\n find: true,\n delete: false,\n save: false\n }]\n})\n")))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/13826def.fa197dce.js b/assets/js/13826def.fa197dce.js
new file mode 100644
index 00000000000..90670ad72cf
--- /dev/null
+++ b/assets/js/13826def.fa197dce.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[39721],{3905:(e,n,r)=>{r.d(n,{Zo:()=>c,kt:()=>m});var t=r(67294);function i(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function o(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function a(e){for(var n=1;nArchive