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..3bdc749c0ec --- /dev/null +++ b/404.html @@ -0,0 +1,17 @@ + + +
+ + +We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
[ENTITY]Saved
",id:"entitysaved",level:2},{value:"[ENTITY]Deleted
",id:"entitydeleted",level:2}],p={toc:c},u="wrapper";function d(e){let{components:t,...n}=e;return(0,i.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"subscription"},"Subscription"),(0,i.kt)("p",null,"When the GraphQL plugin is loaded, some subscriptions are automatically adding to\nthe GraphQL schema if the ",(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/sql-events")," plugin has been previously registered."),(0,i.kt)("p",null,"It's possible to avoid creating the subscriptions for a given entity by adding the ",(0,i.kt)("inlineCode",{parentName:"p"},"subscriptionIgnore")," config,\nlike so: ",(0,i.kt)("inlineCode",{parentName:"p"},"subscriptionIgnore: ['page']"),"."),(0,i.kt)("h2",{id:"entitysaved"},(0,i.kt)("inlineCode",{parentName:"h2"},"[ENTITY]Saved")),(0,i.kt)("p",null,"Published whenever an entity is saved, e.g. when the mutation ",(0,i.kt)("inlineCode",{parentName:"p"},"insert[ENTITY]")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"save[ENTITY]")," are called."),(0,i.kt)("h2",{id:"entitydeleted"},(0,i.kt)("inlineCode",{parentName:"h2"},"[ENTITY]Deleted")),(0,i.kt)("p",null,"Published whenever an entity is deleted, e.g. when the mutation ",(0,i.kt)("inlineCode",{parentName:"p"},"delete[ENTITY]")," is called.."))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/06ff8815.ba210ee1.js b/assets/js/06ff8815.ba210ee1.js
new file mode 100644
index 00000000000..7cbfdd8bad7
--- /dev/null
+++ b/assets/js/06ff8815.ba210ee1.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[73301],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>f});var a=r(67294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function o(e){for(var t=1;tserver
",id:"server",level:3},{value:"metrics
",id:"metrics",level:3},{value:"plugins
",id:"plugins",level:3},{value:"composer
",id:"composer",level:3},{value:"openapi
",id:"openapi",level:4},{value:"openapi-configuration
",id:"openapi-configuration",level:5},{value:"telemetry
",id:"telemetry",level:3},{value:"watch
",id:"watch",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}],m={toc:s},c="wrapper";function d(e){let{components:t,...n}=e;return(0,i.kt)(c,(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"configuration"},"Configuration"),(0,i.kt)("p",null,"Platformatic Composer configured with a configuration file. It supports the use\nof environment variables as setting values with ",(0,i.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,i.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,i.kt)("p",null,"If the Platformatic CLI finds a file in the current working directory matching\none of these filenames, it will automatically load it:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.json")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.json5")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.yml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.yaml")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.tml")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"platformatic.composer.toml"))),(0,i.kt)("p",null,"Alternatively, a ",(0,i.kt)("a",{parentName:"p",href:"/docs/1.0.0/reference/cli#composer"},(0,i.kt)("inlineCode",{parentName:"a"},"--config")," option")," with a configuration\nfilepath can be passed to most ",(0,i.kt)("inlineCode",{parentName:"p"},"platformatic composer")," CLI commands."),(0,i.kt)("p",null,"The configuration examples in this reference use JSON."),(0,i.kt)("h3",{id:"supported-formats"},"Supported formats"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"left"},"Format"),(0,i.kt)("th",{parentName:"tr",align:"left"},"Extensions"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"JSON"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".json"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"JSON5"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".json5"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"YAML"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".yml"),", ",(0,i.kt)("inlineCode",{parentName:"td"},".yaml"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"left"},"TOML"),(0,i.kt)("td",{parentName:"tr",align:"left"},(0,i.kt)("inlineCode",{parentName:"td"},".tml"))))),(0,i.kt)("p",null,"Comments are supported by the JSON5, YAML and TOML file formats."),(0,i.kt)("h2",{id:"settings"},"Settings"),(0,i.kt)("p",null,"Configuration settings are organised into the following groups:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#server"},(0,i.kt)("inlineCode",{parentName:"a"},"server"))," ",(0,i.kt)("strong",{parentName:"li"},"(required)")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#composer"},(0,i.kt)("inlineCode",{parentName:"a"},"composer"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#metrics"},(0,i.kt)("inlineCode",{parentName:"a"},"metrics"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#plugins"},(0,i.kt)("inlineCode",{parentName:"a"},"plugins"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#telemetry"},(0,i.kt)("inlineCode",{parentName:"a"},"telemetry"))),(0,i.kt)("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 containing sensitive data should be set using ",(0,i.kt)("a",{parentName:"p",href:"#configuration-placeholders"},"configuration placeholders"),"."),(0,i.kt)("h3",{id:"server"},(0,i.kt)("inlineCode",{parentName:"h3"},"server")),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#server"},"Platformatic Service server")," for more details."),(0,i.kt)("h3",{id:"metrics"},(0,i.kt)("inlineCode",{parentName:"h3"},"metrics")),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#metrics"},"Platformatic Service metrics")," for more details."),(0,i.kt)("h3",{id:"plugins"},(0,i.kt)("inlineCode",{parentName:"h3"},"plugins")),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#plugins"},"Platformatic Service plugins")," for more details."),(0,i.kt)("h3",{id:"composer"},(0,i.kt)("inlineCode",{parentName:"h3"},"composer")),(0,i.kt)("p",null,"Configure ",(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/composer")," specific settings such as ",(0,i.kt)("inlineCode",{parentName:"p"},"services")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"refreshTimeout"),":"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"services"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"array"),", default: ",(0,i.kt)("inlineCode",{parentName:"p"},"[]"),") \u2014 is an array of objects that defines\nthe services managed by the composer. Each service object supports the following settings:"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"id"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A unique identifier for the service. Use a Platformatic Runtime service id if the service is executing inside of ",(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"},"origin"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A service origin. Skip this option if the service is executing inside of ",(0,i.kt)("a",{parentName:"li",href:"/docs/next/reference/runtime/introduction#platformatic-runtime-context"},"Platformatic Runtime context"),". In this case, service id will be used instead of origin."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"openapi"))," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"object"),") - The configuration file used to compose OpenAPI specification. See the ",(0,i.kt)("a",{parentName:"li",href:"#openapi"},"openapi")," for details."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"proxy"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"object")," or ",(0,i.kt)("inlineCode",{parentName:"li"},"false"),") - Service proxy configuration. If ",(0,i.kt)("inlineCode",{parentName:"li"},"false"),", the service proxy is disabled.",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"prefix")," (",(0,i.kt)("strong",{parentName:"li"},"required"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - Service proxy prefix. All service routes will be prefixed with this value."))))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"openapi"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"object"),") - See the Platformatic Service ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#service"},"service")," openapi option for 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"},"refreshTimeout"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"number"),") - The number of milliseconds to wait for check for changes in the service OpenAPI specification. If not specified, the default value is ",(0,i.kt)("inlineCode",{parentName:"p"},"1000"),"."))),(0,i.kt)("h4",{id:"openapi"},(0,i.kt)("inlineCode",{parentName:"h4"},"openapi")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"url"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A path of the route that exposes the OpenAPI specification. If a service is a Platformatic Service or Platformatic DB, use ",(0,i.kt)("inlineCode",{parentName:"li"},"/documentation/json")," as a value. Use this or ",(0,i.kt)("inlineCode",{parentName:"li"},"file")," option to specify the OpenAPI specification."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"file"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A path to the OpenAPI specification file. Use this or ",(0,i.kt)("inlineCode",{parentName:"li"},"url")," option to specify the OpenAPI specification."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"prefix"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A prefix for the OpenAPI specification. All service routes will be prefixed with this value."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"config"))," (",(0,i.kt)("inlineCode",{parentName:"li"},"string"),") - A path to the OpenAPI configuration file. This file is used to customize the OpenAPI specification. See the ",(0,i.kt)("a",{parentName:"li",href:"#openapi-configuration"},"openapi-configuration")," for details.")),(0,i.kt)("h5",{id:"openapi-configuration"},(0,i.kt)("inlineCode",{parentName:"h5"},"openapi-configuration")),(0,i.kt)("p",null,"The OpenAPI configuration file is a JSON file that is used to customize the OpenAPI specification. It supports the following options:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"ignore"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"boolean"),") - If ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),", the route will be ignored by the composer.\nIf you want to ignore a specific method, use the ",(0,i.kt)("inlineCode",{parentName:"p"},"ignore")," option in the nested method object."),(0,i.kt)("p",{parentName:"li"}," ",(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "paths": {\n "/users": {\n "ignore": true\n },\n "/users/{id}": {\n "get": { "ignore": true },\n "put": { "ignore": true }\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"alias")," (",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") - Use it create an alias for the route path. Original route path will be ignored."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "paths": {\n "/users": {\n "alias": "/customers"\n }\n }\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"rename"))," (",(0,i.kt)("inlineCode",{parentName:"p"},"string"),") - Use it to rename composed route response fields.\nUse json schema format to describe the response structure. For now it works only for ",(0,i.kt)("inlineCode",{parentName:"p"},"200")," response."),(0,i.kt)("p",{parentName:"li"}," ",(0,i.kt)("em",{parentName:"p"},"Example")),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "paths": {\n "/users": {\n "responses": {\n "200": {\n "type": "array",\n "items": {\n "type": "object",\n "properties": {\n "id": { "rename": "user_id" },\n "name": { "rename": "first_name" }\n }\n }\n }\n }\n }\n }\n}\n')))),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"Examples")),(0,i.kt)("p",null," Composition of two remote services:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "composer": {\n "services": [\n {\n "id": "auth-service",\n "origin": "https://auth-service.com",\n "openapi": {\n "url": "/documentation/json",\n "prefix": "auth"\n }\n },\n {\n "id": "payment-service",\n "origin": "https://payment-service.com",\n "openapi": {\n "file": "./schemas/payment-service.json"\n }\n }\n ],\n "refreshTimeout": 1000\n }\n}\n')),(0,i.kt)("p",null," Composition of two local services inside of Platformatic Runtime:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "composer": {\n "services": [\n {\n "id": "auth-service",\n "openapi": {\n "url": "/documentation/json",\n "prefix": "auth"\n }\n },\n {\n "id": "payment-service",\n "openapi": {\n "file": "./schemas/payment-service.json"\n }\n }\n ],\n "refreshTimeout": 1000\n }\n}\n')),(0,i.kt)("h3",{id:"telemetry"},(0,i.kt)("inlineCode",{parentName:"h3"},"telemetry")),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#telemetry"},"Platformatic Service telemetry")," for more details."),(0,i.kt)("h3",{id:"watch"},(0,i.kt)("inlineCode",{parentName:"h3"},"watch")),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#watch"},"Platformatic Service watch")," for more details."),(0,i.kt)("h3",{id:"clients"},(0,i.kt)("inlineCode",{parentName:"h3"},"clients")),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#clients"},"Platformatic Service clients")," for more details."),(0,i.kt)("h2",{id:"environment-variable-placeholders"},"Environment variable placeholders"),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#environment-variable-placeholders"},"Environment variable placeholders")," for more details."),(0,i.kt)("h3",{id:"setting-environment-variables"},"Setting environment variables"),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#setting-environment-variables"},"Setting environment variables")," for more details."),(0,i.kt)("h3",{id:"allowed-placeholder-names"},"Allowed placeholder names"),(0,i.kt)("p",null,"See ",(0,i.kt)("a",{parentName:"p",href:"/docs/next/reference/service/configuration#allowed-placeholder-names"},"Allowed placeholder names")," for more details."))}d.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/0b0d3b2b.955d3d83.js b/assets/js/0b0d3b2b.955d3d83.js
new file mode 100644
index 00000000000..6817229ae7f
--- /dev/null
+++ b/assets/js/0b0d3b2b.955d3d83.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[11889],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>d});var i=n(67294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;tPOST [PLURAL_ENTITY_NAME]
",id:"post-plural_entity_name",level:2},{value:"GET [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
",id:"get-plural_entity_nameprimary_key",level:2},{value:"POST [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
",id:"post-plural_entity_nameprimary_key",level:2},{value:"PUT [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
",id:"put-plural_entity_nameprimary_key",level:2},{value:"DELETE [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
",id:"delete-plural_entity_nameprimary_key",level:2},{value:"Nested Relationships",id:"nested-relationships",level:2},{value:"GET [P_PARENT_ENTITY]/[PARENT_PRIMARY_KEY]/[P_CHILDREN_ENTITY]
",id:"get-p_parent_entityparent_primary_keyp_children_entity",level:3},{value:"GET [P_CHILDREN_ENTITY]/[CHILDREN_PRIMARY_KEY]/[S_PARENT_ENTITY]
",id:"get-p_children_entitychildren_primary_keys_parent_entity",level:3},{value:"Many-to-Many Relationships",id:"many-to-many-relationships",level:2},{value:"GET [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
",id:"get-p_entitys_rel_1key_rel_1s_rel_2key_rel_2",level:3},{value:"POST [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
",id:"post-p_entitys_rel_1key_rel_1s_rel_2key_rel_2",level:3},{value:"PUT [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
",id:"put-p_entitys_rel_1key_rel_1s_rel_2key_rel_2",level:3},{value:"DELETE [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
",id:"delete-p_entitys_rel_1key_rel_1s_rel_2key_rel_2",level:3},{value:"GET /[P_ENTITY]
",id:"get-p_entity",level:2},{value:"Pagination",id:"pagination",level:2},{value:"Limit",id:"limit",level:3},{value:"Offset",id:"offset",level:3}],s={toc:d},m="wrapper";function u(e){let{components:t,...n}=e;return(0,l.kt)(m,(0,a.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"api"},"API"),(0,l.kt)("p",null,"Each table is mapped to an ",(0,l.kt)("inlineCode",{parentName:"p"},"entity")," named after table's name. "),(0,l.kt)("p",null,"In the following reference we'll use some placeholders, but let's see an example"),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("p",null,"Given this SQL executed against your database:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE pages (\n id SERIAL PRIMARY KEY,\n title VARCHAR(255) NOT NULL,\n body TEXT NOT NULL\n);\n")),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[PLURAL_ENTITY_NAME]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"pages")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[SINGULAR_ENTITY_NAME]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"page")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[PRIMARY_KEY]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"id")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"fields")," are ",(0,l.kt)("inlineCode",{parentName:"li"},"id"),", ",(0,l.kt)("inlineCode",{parentName:"li"},"title"),", ",(0,l.kt)("inlineCode",{parentName:"li"},"body"))),(0,l.kt)("h2",{id:"get-and-post-parameters"},"GET and POST parameters"),(0,l.kt)("p",null,"Some APIs needs the ",(0,l.kt)("inlineCode",{parentName:"p"},"GET")," method, where parameters must be defined in the URL, or ",(0,l.kt)("inlineCode",{parentName:"p"},"POST/PUT")," methods, where parameters can be defined in the http request payload."),(0,l.kt)("h2",{id:"fields"},"Fields"),(0,l.kt)("p",null,"Every API can define a ",(0,l.kt)("inlineCode",{parentName:"p"},"fields")," parameter, representing the entity fields you want to get back for each row of the table. If not specified all fields are returned."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"fields")," parameter are always sent in query string, even for ",(0,l.kt)("inlineCode",{parentName:"p"},"POST"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"PUT")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"DELETE")," requests, as a comma separated value."),(0,l.kt)("a",{name:"plural"}),"## `GET /[PLURAL_ENTITY_NAME]`",(0,l.kt)("p",null,"Return all entities matching ",(0,l.kt)("inlineCode",{parentName:"p"},"where")," clause"),(0,l.kt)("h3",{id:"where-clause"},"Where clause"),(0,l.kt)("p",null,"You can define many ",(0,l.kt)("inlineCode",{parentName:"p"},"WHERE")," clauses in REST API, each clause includes a ",(0,l.kt)("strong",{parentName:"p"},"field"),", an ",(0,l.kt)("strong",{parentName:"p"},"operator")," and a ",(0,l.kt)("strong",{parentName:"p"},"value"),"."),(0,l.kt)("p",null,"The ",(0,l.kt)("strong",{parentName:"p"},"field")," is one of the fields found in the schema."),(0,l.kt)("p",null,"The ",(0,l.kt)("strong",{parentName:"p"},"operator")," follows this table:"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Platformatic operator"),(0,l.kt)("th",{parentName:"tr",align:null},"SQL operator"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"eq"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'='"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"in"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'IN'"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"nin"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'NOT IN'"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"neq"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'<>'"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"gt"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'>'"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"gte"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'>='"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"lt"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'<'"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"lte"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"'<='"))))),(0,l.kt)("p",null,"The ",(0,l.kt)("strong",{parentName:"p"},"value")," is the value you want to compare the field to."),(0,l.kt)("p",null,"For GET requests all these clauses are specified in the query string using the format ",(0,l.kt)("inlineCode",{parentName:"p"},"where.[FIELD].[OPERATOR]=[VALUE]")),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("p",null,"If you want to get the ",(0,l.kt)("inlineCode",{parentName:"p"},"title")," and the ",(0,l.kt)("inlineCode",{parentName:"p"},"body")," of every ",(0,l.kt)("inlineCode",{parentName:"p"},"page")," where ",(0,l.kt)("inlineCode",{parentName:"p"},"id < 15")," you can make an HTTP request like this:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"$ curl -X 'GET' \\\n 'http://localhost:3042/pages/?fields=body,title&where.id.lt=15' \\\n -H 'accept: application/json'\n")),(0,l.kt)("p",null,"Where clause operations are by default combined with the ",(0,l.kt)("inlineCode",{parentName:"p"},"AND")," operator. To create an ",(0,l.kt)("inlineCode",{parentName:"p"},"OR")," condition use the ",(0,l.kt)("inlineCode",{parentName:"p"},"where.or")," query param."),(0,l.kt)("p",null,"Each ",(0,l.kt)("inlineCode",{parentName:"p"},"where.or")," query param can contain multiple conditions separated by a ",(0,l.kt)("inlineCode",{parentName:"p"},"|")," (pipe)."),(0,l.kt)("p",null,"The ",(0,l.kt)("inlineCode",{parentName:"p"},"where.or")," conditions are similar to the ",(0,l.kt)("inlineCode",{parentName:"p"},"where")," conditions, except that they don't have the ",(0,l.kt)("inlineCode",{parentName:"p"},"where")," prefix."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("p",null,"If you want to get the ",(0,l.kt)("inlineCode",{parentName:"p"},"posts")," where ",(0,l.kt)("inlineCode",{parentName:"p"},"counter = 10")," ",(0,l.kt)("inlineCode",{parentName:"p"},"OR")," ",(0,l.kt)("inlineCode",{parentName:"p"},"counter > 30")," you can make an HTTP request like this:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"$ curl -X 'GET' \\\n 'http://localhost:3042/pages/?where.or=(counter.eq=10|counter.gte=30)' \\\n -H 'accept: application/json'\n")),(0,l.kt)("h2",{id:"orderby-clause"},"OrderBy clause"),(0,l.kt)("p",null,"You can define the ordering of the returned rows within your REST API calls with the ",(0,l.kt)("inlineCode",{parentName:"p"},"orderby")," clause using the following pattern:"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"?orderby.[field]=[asc | desc]")),(0,l.kt)("p",null,"The ",(0,l.kt)("strong",{parentName:"p"},"field")," is one of the fields found in the schema.\nThe ",(0,l.kt)("strong",{parentName:"p"},"value")," can be ",(0,l.kt)("inlineCode",{parentName:"p"},"asc")," or ",(0,l.kt)("inlineCode",{parentName:"p"},"desc"),"."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("p",null,"If you want to get the ",(0,l.kt)("inlineCode",{parentName:"p"},"pages")," ordered alphabetically by their ",(0,l.kt)("inlineCode",{parentName:"p"},"titles")," you can make an HTTP request like this:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"$ curl -X 'GET' \\\n 'http://localhost:3042/pages?orderby.title=asc' \\\n -H 'accept: application/json'\n")),(0,l.kt)("h3",{id:"total-count"},"Total Count"),(0,l.kt)("p",null,"If ",(0,l.kt)("inlineCode",{parentName:"p"},"totalCount")," boolean is ",(0,l.kt)("inlineCode",{parentName:"p"},"true")," in query, the GET returns the total number of elements in the ",(0,l.kt)("inlineCode",{parentName:"p"},"X-Total-Count")," header ignoring ",(0,l.kt)("inlineCode",{parentName:"p"},"limit")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"offset")," (if specified)."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'$ curl -v -X \'GET\' \\\n \'http://localhost:3042/pages/?limit=2&offset=0&totalCount=true\' \\\n -H \'accept: application/json\'\n\n (...)\n> HTTP/1.1 200 OK\n> x-total-count: 18\n (...)\n\n[{"id":1,"title":"Movie1"},{"id":2,"title":"Movie2"}]%\n')),(0,l.kt)("h2",{id:"post-plural_entity_name"},(0,l.kt)("inlineCode",{parentName:"h2"},"POST [PLURAL_ENTITY_NAME]")),(0,l.kt)("p",null,"Creates a new row in table. Expects fields to be sent in a JSON formatted request body."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'POST\' \\\n \'http://localhost:3042/pages/\' \\\n -H \'accept: application/json\' \\\n -H \'Content-Type: application/json\' \\\n -d \'{\n "title": "Hello World",\n "body": "Welcome to Platformatic!"\n}\'\n\n{\n "id": 1,\n "title": "Hello World",\n "body": "Welcome to Platformatic"\n}\n')),(0,l.kt)("h2",{id:"get-plural_entity_nameprimary_key"},(0,l.kt)("inlineCode",{parentName:"h2"},"GET [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]")),(0,l.kt)("p",null,"Returns a single row, identified by ",(0,l.kt)("inlineCode",{parentName:"p"},"PRIMARY_KEY"),"."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'GET\' \'http://localhost:3042/pages/1?fields=title,body\n\n{\n "title": "Hello World",\n "body": "Welcome to Platformatic"\n}\n')),(0,l.kt)("h2",{id:"post-plural_entity_nameprimary_key"},(0,l.kt)("inlineCode",{parentName:"h2"},"POST [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]")),(0,l.kt)("p",null,"Updates a row identified by ",(0,l.kt)("inlineCode",{parentName:"p"},"PRIMARY_KEY"),". "),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'POST\' \\\n \'http://localhost:3042/pages/1\' \\\n -H \'accept: application/json\' \\\n -H \'Content-Type: application/json\' \\\n -d \'{\n "title": "Hello Platformatic!",\n "body": "Welcome to Platformatic!"\n}\'\n\n{\n "id": 1,\n "title": "Hello Platformatic!",\n "body": "Welcome to Platformatic"\n}\n')),(0,l.kt)("h2",{id:"put-plural_entity_nameprimary_key"},(0,l.kt)("inlineCode",{parentName:"h2"},"PUT [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]")),(0,l.kt)("p",null,"Same as ",(0,l.kt)("inlineCode",{parentName:"p"},"POST [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]"),"."),(0,l.kt)("a",{name:"put-plural"}),"## `PUT [PLURAL_ENTITY_NAME]`",(0,l.kt)("p",null,"Updates all entities matching ",(0,l.kt)("inlineCode",{parentName:"p"},"where")," clause"),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'PUT\' \\\n \'http://localhost:3042/pages?where.id.in=1,2\' \\\n -H \'accept: application/json\' \\\n -H \'Content-Type: application/json\' \\\n -d \'{\n "title": "Updated title!",\n "body": "Updated body!"\n}\'\n\n[{\n "id": 1,\n "title": "Updated title!",\n "body": "Updated body!"\n},{\n "id": 2,\n "title": "Updated title!",\n "body": "Updated body!"\n}]\n')),(0,l.kt)("h2",{id:"delete-plural_entity_nameprimary_key"},(0,l.kt)("inlineCode",{parentName:"h2"},"DELETE [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]")),(0,l.kt)("p",null,"Deletes a row identified by the ",(0,l.kt)("inlineCode",{parentName:"p"},"PRIMARY_KEY"),"."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"$ curl -X 'DELETE' 'http://localhost:3042/pages/1?fields=title'\n\n{\n \"title\": \"Hello Platformatic!\"\n}\n")),(0,l.kt)("h2",{id:"nested-relationships"},"Nested Relationships"),(0,l.kt)("p",null,"Let's consider the following SQL:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sql"},"CREATE TABLE IF NOT EXISTS movies (\n movie_id INTEGER PRIMARY KEY,\n title TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS quotes (\n id INTEGER PRIMARY KEY,\n quote TEXT NOT NULL,\n movie_id INTEGER NOT NULL REFERENCES movies(movie_id)\n);\n")),(0,l.kt)("p",null,"And:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[P_PARENT_ENTITY]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"movies")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[S_PARENT_ENTITY]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"movie")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[P_CHILDREN_ENTITY]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"quotes")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[S_CHILDREN_ENTITY]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"quote"))),(0,l.kt)("p",null,"In this case, more APIs are available:"),(0,l.kt)("h3",{id:"get-p_parent_entityparent_primary_keyp_children_entity"},(0,l.kt)("inlineCode",{parentName:"h3"},"GET [P_PARENT_ENTITY]/[PARENT_PRIMARY_KEY]/[P_CHILDREN_ENTITY]")),(0,l.kt)("p",null,"Given a 1-to-many relationship, where a parent entity can have many children, you can query for the children directly."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'GET\' \'http://localhost:3042/movies/1/quotes?fields=quote\n\n[\n {\n "quote": "I\'ll be back"\n },\n {\n "quote": "Hasta la vista, baby"\n }\n]\n')),(0,l.kt)("h3",{id:"get-p_children_entitychildren_primary_keys_parent_entity"},(0,l.kt)("inlineCode",{parentName:"h3"},"GET [P_CHILDREN_ENTITY]/[CHILDREN_PRIMARY_KEY]/[S_PARENT_ENTITY]")),(0,l.kt)("p",null,"You can query for the parent directly, e.g.:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'GET\' \'http://localhost:3042/quotes/1/movie?fields=title\n\n{\n "title": "Terminator"\n}\n')),(0,l.kt)("h2",{id:"many-to-many-relationships"},"Many-to-Many Relationships"),(0,l.kt)("p",null,"Many-to-Many relationship lets you relate each row in one table to many rows in\nanother table and vice versa. "),(0,l.kt)("p",null,'Many-to-many relationship are implemented in SQL via a "join table", a table whose ',(0,l.kt)("strong",{parentName:"p"},"primary key"),"\nis composed by the identifier of the two parts of the many-to-many relationship."),(0,l.kt)("p",null,"Platformatic DB fully support many-to-many relationships on all supported database."),(0,l.kt)("p",null,"Let's consider the following SQL:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-SQL"},"CREATE TABLE pages (\n id INTEGER PRIMARY KEY,\n the_title VARCHAR(42)\n);\n\nCREATE TABLE users (\n id INTEGER PRIMARY KEY,\n username VARCHAR(255) NOT NULL\n);\n\nCREATE TABLE editors (\n page_id INTEGER NOT NULL,\n user_id INTEGER NOT NULL,\n role VARCHAR(255) NOT NULL,\n CONSTRAINT fk_editor_pages FOREIGN KEY (page_id) REFERENCES pages(id),\n CONSTRAINT fk_editor_users FOREIGN KEY (user_id) REFERENCES users(id),\n PRIMARY KEY (page_id, user_id)\n);\n")),(0,l.kt)("p",null,"And:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[P_ENTITY]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"editors")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[P_REL_1]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"pages")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[S_REL_1]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"page")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[KEY_REL_1]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"pages")," PRIMARY KEY: ",(0,l.kt)("inlineCode",{parentName:"li"},"pages(id)")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[P_REL_2]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"users")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[S_REL_2]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"user")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[KEY_REL_2]")," is ",(0,l.kt)("inlineCode",{parentName:"li"},"users")," PRIMARY KEY: ",(0,l.kt)("inlineCode",{parentName:"li"},"users(id)"))),(0,l.kt)("p",null,"In this case, here the APIs that are available for the join table:"),(0,l.kt)("h3",{id:"get-p_entitys_rel_1key_rel_1s_rel_2key_rel_2"},(0,l.kt)("inlineCode",{parentName:"h3"},"GET [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]")),(0,l.kt)("p",null,'This returns the entity in the "join table", e.g. ',(0,l.kt)("inlineCode",{parentName:"p"},"GET /editors/page/1/user/1"),"."),(0,l.kt)("h3",{id:"post-p_entitys_rel_1key_rel_1s_rel_2key_rel_2"},(0,l.kt)("inlineCode",{parentName:"h3"},"POST [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]")),(0,l.kt)("p",null,'Creates a new entity in the "join table", e.g. ',(0,l.kt)("inlineCode",{parentName:"p"},"POST /editors/page/1/user/1"),"."),(0,l.kt)("h3",{id:"put-p_entitys_rel_1key_rel_1s_rel_2key_rel_2"},(0,l.kt)("inlineCode",{parentName:"h3"},"PUT [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]")),(0,l.kt)("p",null,'Updates an entity in the "join table", e.g. ',(0,l.kt)("inlineCode",{parentName:"p"},"PUT /editors/page/1/user/1"),"."),(0,l.kt)("h3",{id:"delete-p_entitys_rel_1key_rel_1s_rel_2key_rel_2"},(0,l.kt)("inlineCode",{parentName:"h3"},"DELETE [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]")),(0,l.kt)("p",null,'Delete the entity in the "join table", e.g. ',(0,l.kt)("inlineCode",{parentName:"p"},"DELETE /editors/page/1/user/1"),"."),(0,l.kt)("h2",{id:"get-p_entity"},(0,l.kt)("inlineCode",{parentName:"h2"},"GET /[P_ENTITY]")),(0,l.kt)("p",null,"See the ",(0,l.kt)("a",{parentName:"p",href:"#plural"},"above"),"."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Offset")," only accepts values ",(0,l.kt)("inlineCode",{parentName:"p"},">= 0"),". Otherwise an error is return."),(0,l.kt)("h2",{id:"pagination"},"Pagination"),(0,l.kt)("p",null,"The Platformatic DB supports for result's pagination through input parameters: ",(0,l.kt)("inlineCode",{parentName:"p"},"limit")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"offset")),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Example")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},'$ curl -X \'GET\' \'http://localhost:3042/movies?limit=5&offset=10\n\n[\n {\n "title": "Star Wars",\n "movie_id": 10\n },\n ...\n {\n "title": "007",\n "movie_id": 14\n }\n]\n')),(0,l.kt)("p",null,"It returns 5 movies starting from position 10."),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"#total-count"},"TotalCount")," functionality can be used in order to evaluate if there are more pages."),(0,l.kt)("h3",{id:"limit"},"Limit"),(0,l.kt)("p",null,"By default a ",(0,l.kt)("em",{parentName:"p"},"limit")," value (",(0,l.kt)("inlineCode",{parentName:"p"},"10"),") is applied to each request."),(0,l.kt)("p",null,"Clients can override this behavior by passing a value.\nIn this case the server validates the input and an error is return if exceeds the ",(0,l.kt)("inlineCode",{parentName:"p"},"max")," accepted value (",(0,l.kt)("inlineCode",{parentName:"p"},"100"),")."),(0,l.kt)("p",null,"Limit's values can be customized through configuration:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json"},'{\n ...\n "db": {\n ...\n "limit": {\n "default": 50,\n "max": 1000\n }\n }\n}\n')),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Limit")," only accepts values ",(0,l.kt)("inlineCode",{parentName:"p"},">= 0"),". Otherwise an error is return."),(0,l.kt)("h3",{id:"offset"},"Offset"),(0,l.kt)("p",null,"By default ",(0,l.kt)("em",{parentName:"p"},"offset")," is not applied to the request.\nClients can override this behavior by passing a value."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Offset")," only accepts values ",(0,l.kt)("inlineCode",{parentName:"p"},">= 0"),". Otherwise an error is return."))}u.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/0dc7c502.dc940cf1.js b/assets/js/0dc7c502.dc940cf1.js
new file mode 100644
index 00000000000..ac861558069
--- /dev/null
+++ b/assets/js/0dc7c502.dc940cf1.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[68782],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(67294);function a(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 s(e){for(var t=1;tconnect(opts) : Promise
",id:"connectopts--promise",level:3},{value:"createConnectionPool(opts) : Promise
",id:"createconnectionpoolopts--promise",level:3},{value:"Code samples",id:"code-samples",level:2}],c={toc:s},m="wrapper";function u(e){let{components:t,...n}=e;return(0,i.kt)(m,(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"introduction-to-platformaticsql-mapper"},"Introduction to @platformatic/sql-mapper"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"@platformatic/sql-mapper")," is the underlining utility that Platformatic DB uses to create useful utilities to\nmanipulate your SQL database using JavaScript. "),(0,i.kt)("p",null,"This module is bundled with ",(0,i.kt)("a",{parentName:"p",href:"/docs/0.47.3/reference/db/introduction"},"Platformatic DB")," via ",(0,i.kt)("a",{parentName:"p",href:"/docs/0.47.3/reference/sql-mapper/fastify-plugin"},"a fastify plugin"),"\nThe rest of this guide shows how to use this module directly."),(0,i.kt)("h2",{id:"install"},"Install"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"npm i @platformatic/sql-mapper\n")),(0,i.kt)("h2",{id:"api"},"API"),(0,i.kt)("h3",{id:"connectopts--promise"},(0,i.kt)("inlineCode",{parentName:"h3"},"connect(opts) : Promise")),(0,i.kt)("p",null,"It will inspect a database schema and return an object containing:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"db")," \u2014 A database abstraction layer from ",(0,i.kt)("a",{parentName:"li",href:"https://www.atdatabases.org/"},(0,i.kt)("inlineCode",{parentName:"a"},"@databases"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"sql")," \u2014 The SQL builder from ",(0,i.kt)("a",{parentName:"li",href:"https://www.atdatabases.org/"},(0,i.kt)("inlineCode",{parentName:"a"},"@databases"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"entities")," \u2014 An object containing a key for each table found in the schema, with basic CRUD operations. See ",(0,i.kt)("a",{parentName:"li",href:"/docs/0.47.3/reference/sql-mapper/entities/introduction"},"Entity Reference")," for details.")),(0,i.kt)("p",null,"The valid options are:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"connectionString")," \u2014 The Database connection string"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"poolSize")," - Maximum number of connections in the connection pool. Defaults to ",(0,i.kt)("inlineCode",{parentName:"li"},"10"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"log")," \u2014 A logger object (like ",(0,i.kt)("a",{parentName:"li",href:"https://getpino.io"},"Pino"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"onDatabaseLoad")," \u2014 An async function that is called after the connection is established. It will receive ",(0,i.kt)("inlineCode",{parentName:"li"},"db")," and ",(0,i.kt)("inlineCode",{parentName:"li"},"sql")," as parameter."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ignore")," \u2014 Object used to ignore some tables from building entities. (i.e. ",(0,i.kt)("inlineCode",{parentName:"li"},"{ 'versions': true }")," will ignore ",(0,i.kt)("inlineCode",{parentName:"li"},"versions")," table)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"autoTimestamp")," \u2014 Generate timestamp automatically when inserting/updating records."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"hooks")," \u2014 For each entity name (like ",(0,i.kt)("inlineCode",{parentName:"li"},"Page"),") you can customize any of the entity API function. Your custom function will receive the original function as first parameter, and then all the other parameters passed to it.")),(0,i.kt)("h3",{id:"createconnectionpoolopts--promise"},(0,i.kt)("inlineCode",{parentName:"h3"},"createConnectionPool(opts) : Promise")),(0,i.kt)("p",null,"It will inspect a database schema and return an object containing:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"db")," \u2014 A database abstraction layer from ",(0,i.kt)("a",{parentName:"li",href:"https://www.atdatabases.org/"},(0,i.kt)("inlineCode",{parentName:"a"},"@databases"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"sql")," \u2014 The SQL builder from ",(0,i.kt)("a",{parentName:"li",href:"https://www.atdatabases.org/"},(0,i.kt)("inlineCode",{parentName:"a"},"@databases")))),(0,i.kt)("p",null,"The valid options are:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"connectionString")," \u2014 The Database connection string"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"poolSize")," - Maximum number of connections in the connection pool. Defaults to ",(0,i.kt)("inlineCode",{parentName:"li"},"10"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"log")," \u2014 A logger object (like ",(0,i.kt)("a",{parentName:"li",href:"https://getpino.io"},"Pino"),")")),(0,i.kt)("p",null,"This utility is useful if you just need to connect to the db without generating any entity."),(0,i.kt)("h2",{id:"code-samples"},"Code samples"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-javascript"},"const { connect } = require('@platformatic/sql-mapper')\nconst { pino } = require('pino')\n\nconst logger = pino()\n\nasync function onDatabaseLoad (db, sql) {\n await db.query(sql`CREATE TABLE pages (\n id SERIAL PRIMARY KEY,\n title VARCHAR(255) NOT NULL\n );`)\n}\nconst connectionString =\n 'postgres://postgres:postgres@localhost:5432/postgres'\nconst mapper = await connect({\n connectionString,\n log: logger,\n onDatabaseLoad,\n ignore: {},\n hooks: {\n Page: {\n find: async function(_find, opts) {\n console.log('hook called');\n return await _find(opts)\n }\n }\n }\n})\nconst pageEntity = mapper.entities.page\n\nawait mapper.db.query(mapper.sql`SELECT * FROM pages`)\nawait mapper.db.find('option1', 'option2')\n")))}u.isMDXComponent=!0}}]);
\ No newline at end of file
diff --git a/assets/js/12221bab.38378a32.js b/assets/js/12221bab.38378a32.js
new file mode 100644
index 00000000000..9b364f243c1
--- /dev/null
+++ b/assets/js/12221bab.38378a32.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkplatformatic_oss_website=self.webpackChunkplatformatic_oss_website||[]).push([[70127],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>f});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 a(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 i(e){for(var t=1;tArchive