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..390ed3214f7 --- /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.
server
",id:"server",level:3},{value:"db
",id:"db",level:3},{value:"metrics
",id:"metrics",level:3},{value:"migrations
",id:"migrations",level:3},{value:"plugins
",id:"plugins",level:3},{value:"watch
",id:"watch",level:3},{value:"authorization
",id:"authorization",level:3},{value:"Example",id:"example",level:4},{value:"telemetry
",id:"telemetry",level:3},{value:"watch
",id:"watch-1",level:3},{value:"clients
",id:"clients",level:3},{value:"Environment variable placeholders",id:"environment-variable-placeholders",level:2},{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 c(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"configuration"},"Configuration"),(0,r.kt)("p",null,"Platformatic DB is configured with a configuration file. It supports the use\nof environment variables as setting values with ",(0,r.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,r.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,r.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,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.json")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.json5")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.yml")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.yaml")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.tml")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.toml"))),(0,r.kt)("p",null,"Alternatively, a ",(0,r.kt)("a",{parentName:"p",href:"/docs/1.3.1/reference/cli#db"},(0,r.kt)("inlineCode",{parentName:"a"},"--config")," option")," with a configuration\nfilepath can be passed to most ",(0,r.kt)("inlineCode",{parentName:"p"},"platformatic db")," CLI commands."),(0,r.kt)("p",null,"The configuration examples in this reference use JSON."),(0,r.kt)("h3",{id:"supported-formats"},"Supported formats"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:"left"},"Format"),(0,r.kt)("th",{parentName:"tr",align:"left"},"Extensions"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"JSON"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".json"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"JSON5"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".json5"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"YAML"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".yml"),", ",(0,r.kt)("inlineCode",{parentName:"td"},".yaml"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"TOML"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".tml"))))),(0,r.kt)("p",null,"Comments are supported by the JSON5, YAML and TOML file formats."),(0,r.kt)("h2",{id:"settings"},"Settings"),(0,r.kt)("p",null,"Configuration settings are organised into the following groups:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#server"},(0,r.kt)("inlineCode",{parentName:"a"},"server"))," ",(0,r.kt)("strong",{parentName:"li"},"(required)")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#db"},(0,r.kt)("inlineCode",{parentName:"a"},"db"))," ",(0,r.kt)("strong",{parentName:"li"},"(required)")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#metrics"},(0,r.kt)("inlineCode",{parentName:"a"},"metrics"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#migrations"},(0,r.kt)("inlineCode",{parentName:"a"},"migrations"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#plugins"},(0,r.kt)("inlineCode",{parentName:"a"},"plugins"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#authorization"},(0,r.kt)("inlineCode",{parentName:"a"},"authorization"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#telemetry"},(0,r.kt)("inlineCode",{parentName:"a"},"telemetry"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#watch"},(0,r.kt)("inlineCode",{parentName:"a"},"watch"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#clients"},(0,r.kt)("inlineCode",{parentName:"a"},"clients")))),(0,r.kt)("p",null,"Sensitive configuration settings, such as a database connection URL that contains\na password, should be set using ",(0,r.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,r.kt)("h3",{id:"server"},(0,r.kt)("inlineCode",{parentName:"h3"},"server")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#server"},"Platformatic Service server")," for more details."),(0,r.kt)("h3",{id:"db"},(0,r.kt)("inlineCode",{parentName:"h3"},"db")),(0,r.kt)("p",null,"A ",(0,r.kt)("strong",{parentName:"p"},"required")," object with the following settings:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"connectionString"))," (",(0,r.kt)("strong",{parentName:"p"},"required"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"string"),") \u2014 Database connection URL."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Example: ",(0,r.kt)("inlineCode",{parentName:"li"},"postgres://user:password@my-database:5432/db-name")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"}," ",(0,r.kt)("inlineCode",{parentName:"strong"},"schema"))," (array of ",(0,r.kt)("inlineCode",{parentName:"p"},"string"),") - Currently supported only for postgres, schemas used tolook for entities. If not provided, the default ",(0,r.kt)("inlineCode",{parentName:"p"},"public")," schema is used."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},' "db": {\n "connectionString": "(...)",\n "schema": [\n "schema1", "schema2"\n ],\n ...\n\n },\n\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Platformatic DB supports MySQL, MariaDB, PostgreSQL and SQLite.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"graphql"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Controls the GraphQL API interface, with optional GraphiQL UI."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("p",{parentName:"li"},"Enables GraphQL support"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": true\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables GraphQL support with GraphiQL"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "graphiql": true\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore entites:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "ignore": {\n "categories": true\n }\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore fields:"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("p",{parentName:"li"},"It's possible to add a custom GraphQL schema during the startup:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "schemaPath": "path/to/schema.graphql"\n }\n }\n }\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"openapi"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Enables OpenAPI REST support."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"If value is an object, all ",(0,r.kt)("a",{parentName:"li",href:"https://swagger.io/specification/"},"OpenAPI v3")," allowed properties can be passed. Also a ",(0,r.kt)("inlineCode",{parentName:"li"},"prefix")," property can be passed to set the OpenAPI prefix."),(0,r.kt)("li",{parentName:"ul"},"Platformatic DB uses ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-swagger"},(0,r.kt)("inlineCode",{parentName:"a"},"@fastify/swagger"))," under the hood to manage this configuration.")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": true\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI with prefix"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "prefix": "/api"\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI with options"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("p",{parentName:"li"},"You can for example add the ",(0,r.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,r.kt)("a",{parentName:"p",href:"/docs/1.3.1/reference/db/authorization/strategies#json-web-token-jwt"},"JWT"),":"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore entites:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "ignore": {\n "categories": true\n }\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore fields:"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"autoTimestamp"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),") - Generate timestamp automatically when inserting/updating records.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"poolSize"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"number"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"10"),") \u2014 Maximum number of connections in the connection pool.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"limit"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"object"),") - Set the default and max limit for pagination. Default is 10, max is 1000."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "limit": {\n "default": 10,\n "max": 1000\n }\n }\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Key/value object that defines which database tables should not be mapped as API entities."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"events"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.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,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "events": {\n "connectionString": "redis://:password@redishost.com:6380/"\n }\n }\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"schemalock"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"false"),") \u2014 Controls the caching of the database schema on disk.\nIf set to ",(0,r.kt)("inlineCode",{parentName:"p"},"true")," the database schema metadata is stored inside a ",(0,r.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,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "schemalock": {\n "path": "./dbmetadata"\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Starting Platformatic DB or running a migration will automatically create the schemalock file."))),(0,r.kt)("h3",{id:"metrics"},(0,r.kt)("inlineCode",{parentName:"h3"},"metrics")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#metrics"},"Platformatic Service metrics")," for more details."),(0,r.kt)("h3",{id:"migrations"},(0,r.kt)("inlineCode",{parentName:"h3"},"migrations")),(0,r.kt)("p",null,"Configures ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rickbergfalk/postgrator"},"Postgrator")," to run migrations against the database."),(0,r.kt)("p",null,"An optional object with the following settings:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"dir"))," (",(0,r.kt)("strong",{parentName:"li"},"required"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): Relative path to the migrations directory."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"autoApply"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"boolean"),", default: ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"): Automatically apply migrations when Platformatic DB server starts.")),(0,r.kt)("h3",{id:"plugins"},(0,r.kt)("inlineCode",{parentName:"h3"},"plugins")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#plugins"},"Platformatic Service plugins")," for more details."),(0,r.kt)("h3",{id:"watch"},(0,r.kt)("inlineCode",{parentName:"h3"},"watch")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#watch"},"Platformatic Service watch")," for more details."),(0,r.kt)("h3",{id:"authorization"},(0,r.kt)("inlineCode",{parentName:"h3"},"authorization")),(0,r.kt)("p",null,"An optional object with the following settings:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"adminSecret")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): A secret that should be sent in an\n",(0,r.kt)("inlineCode",{parentName:"li"},"x-platformatic-admin-secret")," HTTP header when performing GraphQL/REST API\ncalls. Use an ",(0,r.kt)("a",{parentName:"li",href:"#environment-variable-placeholders"},"environment variable placeholder"),"\nto securely provide the value for this setting."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"roleKey")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),", default: ",(0,r.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,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/user-roles-metadata#role-configuration"},"Role configuration"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"anonymousRole")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),", default: ",(0,r.kt)("inlineCode",{parentName:"li"},"anonymous"),"): The name of the anonymous role. See ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/user-roles-metadata#role-configuration"},"Role configuration"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"jwt")," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): Configuration for the ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#json-web-token-jwt"},"JWT authorization strategy"),".\nAny option accepted by ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-jwt"},(0,r.kt)("inlineCode",{parentName:"a"},"@fastify/jwt")),"\ncan be passed in this object.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"secret")," (required, ",(0,r.kt)("inlineCode",{parentName:"li"},"string")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): The secret key that the JWT was signed with.\nSee the ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-jwt#secret-required"},(0,r.kt)("inlineCode",{parentName:"a"},"@fastify/jwt")," documentation"),"\nfor accepted string and object values. Use an ",(0,r.kt)("a",{parentName:"li",href:"#environment-variable-placeholders"},"environment variable placeholder"),"\nto securely provide the value for this setting."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"jwks")," (",(0,r.kt)("inlineCode",{parentName:"li"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): Configure authorization with JSON Web Key Sets (JWKS). See the ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#json-web-key-sets-jwks"},"JWKS documentation"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"namespace")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): Configure a ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#jwt-custom-claim-namespace"},"JWT Custom Claim Namespace"),"\nto avoid name collisions."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"webhook")," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): Configuration for the ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#webhook"},"Webhook authorization strategy"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"url")," (required, ",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): Webhook URL that Platformatic DB will make a\nPOST request to."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"rules")," (",(0,r.kt)("inlineCode",{parentName:"li"},"array"),"): Authorization rules that describe the CRUD actions that\nusers are allowed to perform against entities. See ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/rules"},"Rules"),"\ndocumentation.")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"If an ",(0,r.kt)("inlineCode",{parentName:"p"},"authorization")," object is present, but no rules are specified, no CRUD\noperations are allowed unless ",(0,r.kt)("inlineCode",{parentName:"p"},"adminSecret")," is passed.")),(0,r.kt)("h4",{id:"example"},"Example"),(0,r.kt)("pre",null,(0,r.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,r.kt)("h3",{id:"telemetry"},(0,r.kt)("inlineCode",{parentName:"h3"},"telemetry")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#telemetry"},"Platformatic Service telemetry")," for more details."),(0,r.kt)("h3",{id:"watch-1"},(0,r.kt)("inlineCode",{parentName:"h3"},"watch")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#watch"},"Platformatic Service watch")," for more details."),(0,r.kt)("h3",{id:"clients"},(0,r.kt)("inlineCode",{parentName:"h3"},"clients")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#clients"},"Platformatic Service clients")," for more details."),(0,r.kt)("h2",{id:"environment-variable-placeholders"},"Environment variable placeholders"),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#environment-variable-placeholders"},"Environment variable placeholders")," for more details."),(0,r.kt)("h3",{id:"setting-environment-variables"},"Setting environment variables"),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#setting-environment-variables"},"Setting environment variables")," for more details."),(0,r.kt)("h3",{id:"allowed-placeholder-names"},"Allowed placeholder names"),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#allowed-placeholder-names"},"Allowed placeholder names")," for more details."),(0,r.kt)("h2",{id:"sample-configuration"},"Sample Configuration"),(0,r.kt)("p",null,"This is a bare minimum configuration for Platformatic DB. Uses a local ",(0,r.kt)("inlineCode",{parentName:"p"},"./db.sqlite")," SQLite database, with OpenAPI and GraphQL support."),(0,r.kt)("p",null,"Server will listen to ",(0,r.kt)("inlineCode",{parentName:"p"},"http://127.0.0.1:3042")),(0,r.kt)("pre",null,(0,r.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')))}c.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/0644d42d.04ebfe4f.js b/assets/js/0644d42d.04ebfe4f.js
new file mode 100644
index 00000000000..da54a1fce8a
--- /dev/null
+++ b/assets/js/0644d42d.04ebfe4f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[88587],{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/068aa65f.7dfb88b4.js b/assets/js/068aa65f.7dfb88b4.js
new file mode 100644
index 00000000000..22950bd1a91
--- /dev/null
+++ b/assets/js/068aa65f.7dfb88b4.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[47868],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>f});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;nserver
",id:"server",level:3},{value:"metrics
",id:"metrics",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:"service
",id:"service",level:3},{value:"telemetry
",id:"telemetry",level:3},{value:"clients
",id:"clients",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},k="wrapper";function d(e){let{components:t,...n}=e;return(0,i.kt)(k,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"configuration"},"Configuration"),(0,i.kt)("p",null,"Platformatic Service 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.service.json")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.service.json5")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.service.yml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.service.yaml")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.service.tml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.service.toml"))),(0,i.kt)("p",null,"Alternatively, a ",(0,i.kt)("a",{parentName:"p",href:"/docs/1.4.0/reference/cli#service"},(0,i.kt)("inlineCode",{parentName:"a"},"--config")," option")," with a configuration\nfilepath can be passed to most ",(0,i.kt)("inlineCode",{parentName:"p"},"platformatic service")," 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:"#service"},(0,i.kt)("inlineCode",{parentName:"a"},"service"))),(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)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#watch"},(0,i.kt)("inlineCode",{parentName:"a"},"watch"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#clients"},(0,i.kt)("inlineCode",{parentName:"a"},"clients")))),(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:"server"},(0,i.kt)("inlineCode",{parentName:"h3"},"server")),(0,i.kt)("p",null,"A 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 Service 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")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") \u2014 Port where Platformatic Service 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:"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")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") \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 Service."),(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 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)("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. See ",(0,i.kt)("a",{parentName:"li",href:"#typescript-compilation-options"},"TypeScript compilation options")," for more details.")),(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 "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")," 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"),".")),(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:"service"},(0,i.kt)("inlineCode",{parentName:"h3"},"service")),(0,i.kt)("p",null,"Configure ",(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/service")," specific settings such as ",(0,i.kt)("inlineCode",{parentName:"p"},"graphql")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"openapi"),":"),(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"},"graphql"))," (",(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 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 "service": {\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 "service": {\n "graphql": {\n "graphiql": true\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"},"false"),") \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 Service 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 "service": {\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 "service": {\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 "service": {\n "openapi": {\n "info": {\n "title": "Platformatic Service",\n "description": "Exposing a SQL database as REST"\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)("h3",{id:"clients"},(0,i.kt)("inlineCode",{parentName:"h3"},"clients")),(0,i.kt)("p",null,"An array of ",(0,i.kt)("a",{parentName:"p",href:"/docs/1.4.0/reference/client/introduction"},"Platformatic Client")," configurations that will be loaded by Platformatic Service."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"serviceId"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - The ID of Platformatic Service inside the Platformatic Runtime. Used only in ",(0,i.kt)("a",{parentName:"li",href:"/docs/next/reference/runtime/introduction#platformatic-runtime-context"},"Platformatic Runtime context"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"name"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - The name of the client."),(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"),") - The type of the client. Supported values are ",(0,i.kt)("inlineCode",{parentName:"li"},"graphql")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"openapi"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"schema"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - Path to the generated client schema file."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"path"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - Path to the generated client folder."),(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"),") - The URL of the service that the client will connect to.")),(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 command line, for example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"PLT_SERVER_LOGGER_LEVEL=debug npx platformatic service\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 service 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."))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/0aa1da90.191514d9.js b/assets/js/0aa1da90.191514d9.js
new file mode 100644
index 00000000000..80238f4422d
--- /dev/null
+++ b/assets/js/0aa1da90.191514d9.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[60188],{3905:(e,t,o)=>{o.d(t,{Zo:()=>c,kt:()=>f});var n=o(67294);function r(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function a(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function i(e){for(var t=1;taddComposerOnRouteHook(openApiPath, methods, handler)
",id:"addcomposeronroutehookopenapipath-methods-handler",level:4},{value:"onComposerResponse",id:"oncomposerresponse",level:3}],c={toc:l},m="wrapper";function d(e){let{components:t,...o}=e;return(0,r.kt)(m,(0,n.Z)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"api-modification"},"API modification"),(0,r.kt)("p",null,"If you want to modify automatically generated API, you can use composer custom ",(0,r.kt)("inlineCode",{parentName:"p"},"onRoute")," hook."),(0,r.kt)("h4",{id:"addcomposeronroutehookopenapipath-methods-handler"},(0,r.kt)("inlineCode",{parentName:"h4"},"addComposerOnRouteHook(openApiPath, methods, handler)")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"openApiPath"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),") - A route OpenAPI path that Platformatic Composer takes from the OpenAPI specification."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"methods"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"string[]"),") - Route HTTP methods that Platformatic Composer takes from the OpenAPI specification."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"handler"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"function"),") - fastify ",(0,r.kt)("a",{parentName:"li",href:"https://www.fastify.io/docs/latest/Reference/Hooks/#onroute"},"onRoute")," hook handler.")),(0,r.kt)("h3",{id:"oncomposerresponse"},"onComposerResponse"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"onComposerResponse")," hook is called after the response is received from a composed service.\nIt might be useful if you want to modify the response before it is sent to the client.\nIf you want to use it you need to add ",(0,r.kt)("inlineCode",{parentName:"p"},"onComposerResponse")," property to the ",(0,r.kt)("inlineCode",{parentName:"p"},"config")," object of the route options."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"request"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),") - fastify request object."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"reply"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),") - fastify reply object."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"body"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),") - ",(0,r.kt)("a",{parentName:"li",href:"https://undici.nodejs.org/"},"undici")," response body object.")),(0,r.kt)("p",null,(0,r.kt)("em",{parentName:"p"},"Example")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"app.platformatic.addComposerOnRouteHook('/users/{id}', ['GET'], routeOptions => {\n routeOptions.schema.response[200] = {\n type: 'object',\n properties: {\n firstName: { type: 'string' },\n lastName: { type: 'string' }\n }\n }\n\n async function onComposerResponse (request, reply, body) {\n const payload = await body.json()\n const newPayload = {\n firstName: payload.first_name,\n lastName: payload.last_name\n }\n reply.send(newPayload)\n }\n routeOptions.config.onComposerResponse = onComposerResponse\n})\n")))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/0bfc61ef.558c22cc.js b/assets/js/0bfc61ef.558c22cc.js
new file mode 100644
index 00000000000..cdeb0cef484
--- /dev/null
+++ b/assets/js/0bfc61ef.558c22cc.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[98831],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(67294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(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;tentity 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/1.4.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/1248580c.9ac5a9b6.js b/assets/js/1248580c.9ac5a9b6.js
new file mode 100644
index 00000000000..ce4b16ba006
--- /dev/null
+++ b/assets/js/1248580c.9ac5a9b6.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[95953],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});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 a(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 i(e){for(var t=1;tserver
",id:"server",level:3},{value:"db
",id:"db",level:3},{value:"metrics
",id:"metrics",level:3},{value:"migrations
",id:"migrations",level:3},{value:"plugins
",id:"plugins",level:3},{value:"watch
",id:"watch",level:3},{value:"authorization
",id:"authorization",level:3},{value:"Example",id:"example",level:4},{value:"telemetry
",id:"telemetry",level:3},{value:"watch
",id:"watch-1",level:3},{value:"clients
",id:"clients",level:3},{value:"Environment variable placeholders",id:"environment-variable-placeholders",level:2},{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 c(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"configuration"},"Configuration"),(0,r.kt)("p",null,"Platformatic DB is configured with a configuration file. It supports the use\nof environment variables as setting values with ",(0,r.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,r.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,r.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,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.json")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.json5")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.yml")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.yaml")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.tml")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"platformatic.db.toml"))),(0,r.kt)("p",null,"Alternatively, a ",(0,r.kt)("a",{parentName:"p",href:"/docs/reference/cli#db"},(0,r.kt)("inlineCode",{parentName:"a"},"--config")," option")," with a configuration\nfilepath can be passed to most ",(0,r.kt)("inlineCode",{parentName:"p"},"platformatic db")," CLI commands."),(0,r.kt)("p",null,"The configuration examples in this reference use JSON."),(0,r.kt)("h3",{id:"supported-formats"},"Supported formats"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:"left"},"Format"),(0,r.kt)("th",{parentName:"tr",align:"left"},"Extensions"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"JSON"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".json"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"JSON5"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".json5"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"YAML"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".yml"),", ",(0,r.kt)("inlineCode",{parentName:"td"},".yaml"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"left"},"TOML"),(0,r.kt)("td",{parentName:"tr",align:"left"},(0,r.kt)("inlineCode",{parentName:"td"},".tml"))))),(0,r.kt)("p",null,"Comments are supported by the JSON5, YAML and TOML file formats."),(0,r.kt)("h2",{id:"settings"},"Settings"),(0,r.kt)("p",null,"Configuration settings are organised into the following groups:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#server"},(0,r.kt)("inlineCode",{parentName:"a"},"server"))," ",(0,r.kt)("strong",{parentName:"li"},"(required)")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#db"},(0,r.kt)("inlineCode",{parentName:"a"},"db"))," ",(0,r.kt)("strong",{parentName:"li"},"(required)")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#metrics"},(0,r.kt)("inlineCode",{parentName:"a"},"metrics"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#migrations"},(0,r.kt)("inlineCode",{parentName:"a"},"migrations"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#plugins"},(0,r.kt)("inlineCode",{parentName:"a"},"plugins"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#authorization"},(0,r.kt)("inlineCode",{parentName:"a"},"authorization"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#telemetry"},(0,r.kt)("inlineCode",{parentName:"a"},"telemetry"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#watch"},(0,r.kt)("inlineCode",{parentName:"a"},"watch"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"#clients"},(0,r.kt)("inlineCode",{parentName:"a"},"clients")))),(0,r.kt)("p",null,"Sensitive configuration settings, such as a database connection URL that contains\na password, should be set using ",(0,r.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,r.kt)("h3",{id:"server"},(0,r.kt)("inlineCode",{parentName:"h3"},"server")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#server"},"Platformatic Service server")," for more details."),(0,r.kt)("h3",{id:"db"},(0,r.kt)("inlineCode",{parentName:"h3"},"db")),(0,r.kt)("p",null,"A ",(0,r.kt)("strong",{parentName:"p"},"required")," object with the following settings:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"connectionString"))," (",(0,r.kt)("strong",{parentName:"p"},"required"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"string"),") \u2014 Database connection URL."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Example: ",(0,r.kt)("inlineCode",{parentName:"li"},"postgres://user:password@my-database:5432/db-name")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"}," ",(0,r.kt)("inlineCode",{parentName:"strong"},"schema"))," (array of ",(0,r.kt)("inlineCode",{parentName:"p"},"string"),") - Currently supported only for postgres, schemas used tolook for entities. If not provided, the default ",(0,r.kt)("inlineCode",{parentName:"p"},"public")," schema is used."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},' "db": {\n "connectionString": "(...)",\n "schema": [\n "schema1", "schema2"\n ],\n ...\n\n },\n\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Platformatic DB supports MySQL, MariaDB, PostgreSQL and SQLite.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"graphql"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Controls the GraphQL API interface, with optional GraphiQL UI."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("p",{parentName:"li"},"Enables GraphQL support"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": true\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables GraphQL support with the ",(0,r.kt)("inlineCode",{parentName:"p"},"enabled")," option"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n ...\n "enabled": true\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables GraphQL support with GraphiQL"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "graphiql": true\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore entites:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "ignore": {\n "categories": true\n }\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore fields:"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("p",{parentName:"li"},"It's possible to add a custom GraphQL schema during the startup:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "graphql": {\n "schemaPath": "path/to/schema.graphql"\n }\n }\n }\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"openapi"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"true"),") \u2014 Enables OpenAPI REST support."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"If value is an object, all ",(0,r.kt)("a",{parentName:"li",href:"https://swagger.io/specification/"},"OpenAPI v3")," allowed properties can be passed. Also a ",(0,r.kt)("inlineCode",{parentName:"li"},"prefix")," property can be passed to set the OpenAPI prefix."),(0,r.kt)("li",{parentName:"ul"},"Platformatic DB uses ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-swagger"},(0,r.kt)("inlineCode",{parentName:"a"},"@fastify/swagger"))," under the hood to manage this configuration.")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": true\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI using the ",(0,r.kt)("inlineCode",{parentName:"p"},"enabled")," option"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n ...\n "enabled": true\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI with prefix"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "prefix": "/api"\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Enables OpenAPI with options"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("p",{parentName:"li"},"You can for example add the ",(0,r.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,r.kt)("a",{parentName:"p",href:"/docs/reference/db/authorization/strategies#json-web-token-jwt"},"JWT"),":"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore entites:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "openapi": {\n "ignore": {\n "categories": true\n }\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"It's possible to selectively ignore fields:"),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"autoTimestamp"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),") - Generate timestamp automatically when inserting/updating records.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"poolSize"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"number"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"10"),") \u2014 Maximum number of connections in the connection pool.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"idleTimeoutMilliseconds"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"number"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"30000"),") - Max milliseconds a client can go unused before it is removed from the pool and destroyed.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"queueTimeoutMilliseconds"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"number"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"60000"),") - Number of milliseconds to wait for a connection from the connection pool before throwing a timeout error.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"acquireLockTimeoutMilliseconds"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"number"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"60000"),") - Number of milliseconds to wait for a lock on a connection/transaction.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"limit"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"object"),") - Set the default and max limit for pagination. Default is 10, max is 1000."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "limit": {\n "default": 10,\n "max": 1000\n }\n }\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"object"),") \u2014 Key/value object that defines which database tables should not be mapped as API entities."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.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,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"events"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.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,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("p",{parentName:"li"},"Enable events using the ",(0,r.kt)("inlineCode",{parentName:"p"},"enabled")," option."),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "events": {\n ...\n "enabled": true\n }\n }\n}\n')),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "events": {\n "connectionString": "redis://:password@redishost.com:6380/"\n }\n }\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"schemalock"))," (",(0,r.kt)("inlineCode",{parentName:"p"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"object"),", default: ",(0,r.kt)("inlineCode",{parentName:"p"},"false"),") \u2014 Controls the caching of the database schema on disk.\nIf set to ",(0,r.kt)("inlineCode",{parentName:"p"},"true")," the database schema metadata is stored inside a ",(0,r.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,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"Examples")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "db": {\n ...\n "schemalock": {\n "path": "./dbmetadata"\n }\n }\n}\n')),(0,r.kt)("p",{parentName:"li"},"Starting Platformatic DB or running a migration will automatically create the schemalock file."))),(0,r.kt)("h3",{id:"metrics"},(0,r.kt)("inlineCode",{parentName:"h3"},"metrics")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#metrics"},"Platformatic Service metrics")," for more details."),(0,r.kt)("h3",{id:"migrations"},(0,r.kt)("inlineCode",{parentName:"h3"},"migrations")),(0,r.kt)("p",null,"Configures ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rickbergfalk/postgrator"},"Postgrator")," to run migrations against the database."),(0,r.kt)("p",null,"An optional object with the following settings:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"dir"))," (",(0,r.kt)("strong",{parentName:"li"},"required"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): Relative path to the migrations directory."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"autoApply"))," (",(0,r.kt)("inlineCode",{parentName:"li"},"boolean"),", default: ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"): Automatically apply migrations when Platformatic DB server starts.")),(0,r.kt)("h3",{id:"plugins"},(0,r.kt)("inlineCode",{parentName:"h3"},"plugins")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#plugins"},"Platformatic Service plugins")," for more details."),(0,r.kt)("h3",{id:"watch"},(0,r.kt)("inlineCode",{parentName:"h3"},"watch")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#watch"},"Platformatic Service watch")," for more details."),(0,r.kt)("h3",{id:"authorization"},(0,r.kt)("inlineCode",{parentName:"h3"},"authorization")),(0,r.kt)("p",null,"An optional object with the following settings:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"adminSecret")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): A secret that should be sent in an\n",(0,r.kt)("inlineCode",{parentName:"li"},"x-platformatic-admin-secret")," HTTP header when performing GraphQL/REST API\ncalls. Use an ",(0,r.kt)("a",{parentName:"li",href:"#environment-variable-placeholders"},"environment variable placeholder"),"\nto securely provide the value for this setting."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"roleKey")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),", default: ",(0,r.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,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/user-roles-metadata#role-configuration"},"Role configuration"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"anonymousRole")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),", default: ",(0,r.kt)("inlineCode",{parentName:"li"},"anonymous"),"): The name of the anonymous role. See ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/user-roles-metadata#role-configuration"},"Role configuration"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"jwt")," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): Configuration for the ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#json-web-token-jwt"},"JWT authorization strategy"),".\nAny option accepted by ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-jwt"},(0,r.kt)("inlineCode",{parentName:"a"},"@fastify/jwt")),"\ncan be passed in this object.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"secret")," (required, ",(0,r.kt)("inlineCode",{parentName:"li"},"string")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): The secret key that the JWT was signed with.\nSee the ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fastify/fastify-jwt#secret-required"},(0,r.kt)("inlineCode",{parentName:"a"},"@fastify/jwt")," documentation"),"\nfor accepted string and object values. Use an ",(0,r.kt)("a",{parentName:"li",href:"#environment-variable-placeholders"},"environment variable placeholder"),"\nto securely provide the value for this setting."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"jwks")," (",(0,r.kt)("inlineCode",{parentName:"li"},"boolean")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): Configure authorization with JSON Web Key Sets (JWKS). See the ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#json-web-key-sets-jwks"},"JWKS documentation"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"namespace")," (",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): Configure a ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#jwt-custom-claim-namespace"},"JWT Custom Claim Namespace"),"\nto avoid name collisions."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"webhook")," (",(0,r.kt)("inlineCode",{parentName:"li"},"object"),"): Configuration for the ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/strategies#webhook"},"Webhook authorization strategy"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"url")," (required, ",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"): Webhook URL that Platformatic DB will make a\nPOST request to."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"rules")," (",(0,r.kt)("inlineCode",{parentName:"li"},"array"),"): Authorization rules that describe the CRUD actions that\nusers are allowed to perform against entities. See ",(0,r.kt)("a",{parentName:"li",href:"/docs/reference/db/authorization/rules"},"Rules"),"\ndocumentation.")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"If an ",(0,r.kt)("inlineCode",{parentName:"p"},"authorization")," object is present, but no rules are specified, no CRUD\noperations are allowed unless ",(0,r.kt)("inlineCode",{parentName:"p"},"adminSecret")," is passed.")),(0,r.kt)("h4",{id:"example"},"Example"),(0,r.kt)("pre",null,(0,r.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,r.kt)("h3",{id:"telemetry"},(0,r.kt)("inlineCode",{parentName:"h3"},"telemetry")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#telemetry"},"Platformatic Service telemetry")," for more details."),(0,r.kt)("h3",{id:"watch-1"},(0,r.kt)("inlineCode",{parentName:"h3"},"watch")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#watch"},"Platformatic Service watch")," for more details."),(0,r.kt)("h3",{id:"clients"},(0,r.kt)("inlineCode",{parentName:"h3"},"clients")),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#clients"},"Platformatic Service clients")," for more details."),(0,r.kt)("h2",{id:"environment-variable-placeholders"},"Environment variable placeholders"),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#environment-variable-placeholders"},"Environment variable placeholders")," for more details."),(0,r.kt)("h3",{id:"setting-environment-variables"},"Setting environment variables"),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#setting-environment-variables"},"Setting environment variables")," for more details."),(0,r.kt)("h3",{id:"allowed-placeholder-names"},"Allowed placeholder names"),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#allowed-placeholder-names"},"Allowed placeholder names")," for more details."),(0,r.kt)("h2",{id:"sample-configuration"},"Sample Configuration"),(0,r.kt)("p",null,"This is a bare minimum configuration for Platformatic DB. Uses a local ",(0,r.kt)("inlineCode",{parentName:"p"},"./db.sqlite")," SQLite database, with OpenAPI and GraphQL support."),(0,r.kt)("p",null,"Server will listen to ",(0,r.kt)("inlineCode",{parentName:"p"},"http://127.0.0.1:3042")),(0,r.kt)("pre",null,(0,r.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')))}c.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/1786350c.94c79cc3.js b/assets/js/1786350c.94c79cc3.js
new file mode 100644
index 00000000000..652f2bd0e98
--- /dev/null
+++ b/assets/js/1786350c.94c79cc3.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[92151,41037],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var a=n(67294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;tArchive