diff --git a/docs/.vuepress/config/sidebar-developer.js b/docs/.vuepress/config/sidebar-developer.js index caa2ed7d24..629a076ab0 100644 --- a/docs/.vuepress/config/sidebar-developer.js +++ b/docs/.vuepress/config/sidebar-developer.js @@ -23,18 +23,6 @@ const developer = [ children: [ ['/developer-docs/latest/setup-deployment-guides/installation/cli.md', 'CLI'], ['/developer-docs/latest/setup-deployment-guides/installation/docker.md', 'Docker'], - [ - '/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.md', - 'DigitalOcean One-Click', - ], - [ - '/developer-docs/latest/setup-deployment-guides/installation/platformsh.md', - 'Platform.sh One-Click', - ], - [ - '/developer-docs/latest/setup-deployment-guides/installation/render.md', - 'Render One-Click', - ], ], }, ['/developer-docs/latest/setup-deployment-guides/file-structure.md', 'Project structure'], diff --git a/docs/.vuepress/redirects b/docs/.vuepress/redirects index 73b7a11d68..073a8289ee 100644 --- a/docs/.vuepress/redirects +++ b/docs/.vuepress/redirects @@ -1,2 +1,7 @@ /developer-docs/latest/update-migration-guides/migration-guides/v4/migration-guide-4.0.x-to4.0.6.html /developer-docs/latest/update-migration-guides/migration-guides/v4/migration-guide-4.0.0+-to-4.0.6.html /developer-docs/latest/update-migration-guides/migration-guides/v4/migration-guide-4.0.x-to-4.1.8.html /developer-docs/latest/update-migration-guides/migration-guides/v4/migration-guide-4.0.6+-to-4.1.8.html +/developer-docs/latest/setup-deployment-guides/installation/render.html /developer-docs/latest/setup-deployment-guides/installation/installation.html +/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.html /developer-docs/latest/setup-deployment-guides/installation/installation.html +/developer-docs/latest/setup-deployment-guides/installation/platformsh.html /developer-docs/latest/setup-deployment-guides/installation/installation.html +/developer-docs/latest/setup-deployment-guides/installation/digitalocean-customization.html /developer-docs/latest/setup-deployment-guides/installation/installation.html +/developer-docs/latest/concepts/draft-and-publish.html /user-docs/latest/content-manager/saving-and-publishing-content.html diff --git a/docs/developer-docs/latest/developer-resources/cli/snippets/installation-prerequisites.md b/docs/developer-docs/latest/developer-resources/cli/snippets/installation-prerequisites.md new file mode 100644 index 0000000000..12f560ed7e --- /dev/null +++ b/docs/developer-docs/latest/developer-resources/cli/snippets/installation-prerequisites.md @@ -0,0 +1,5 @@ +The installation requires the following software to be already installed on your computer: + +- [Node.js](https://nodejs.org): only LTS versions are supported (v14 and v16). Other versions of Node.js may not be compatible with the latest release of Strapi. The 14.x version is most recommended by Strapi. +- [npm](https://docs.npmjs.com/cli/v6/commands/npm-install) (v6 only) or [yarn](https://yarnpkg.com/getting-started/install) to run the CLI installation scripts. +- [Python](https://www.python.org/downloads/) when using a SQLite database diff --git a/docs/developer-docs/latest/developer-resources/content-api/integrations/next-js.md b/docs/developer-docs/latest/developer-resources/content-api/integrations/next-js.md index 950e79fd55..6d8d1345f0 100644 --- a/docs/developer-docs/latest/developer-resources/content-api/integrations/next-js.md +++ b/docs/developer-docs/latest/developer-resources/content-api/integrations/next-js.md @@ -6,8 +6,6 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/developer-resources/c # Getting Started with Next.js -!!!include(developer-docs/latest/developer-resources/content-api/snippets/integration-guide-not-updated.md)!!! - This integration guide is following the [Quick Start Guide](/developer-docs/latest/getting-started/quick-start.md). We assume that you have fully completed its "Hands-on" path, and therefore can consume the API by browsing this [url](http://localhost:1337/api/restaurants). If you haven't gone through the Quick Start Guide, the way you request a Strapi API with [Next.js](https://nextjs.org/) remains the same except that you will not fetch the same content. @@ -64,13 +62,15 @@ Be sure that you activated the `find` permission for the `restaurant` collection :::: tab axios ::: request Example GET request with axios + ```js import axios from 'axios'; axios.get('http://localhost:1337/api/restaurants').then(response => { - console.log(response); + console.log(response.data); }); ``` + ::: :::: @@ -94,38 +94,30 @@ fetch('http://localhost:1337/api/restaurants', { ::::: :::response Example response + ```json -[ - { - "id": 1, - "name": "Biscotte Restaurant", - "description": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.", - "created_by": { - "id": 1, - "firstname": "Paul", - "lastname": "Bocuse", - "username": null - }, - "updated_by": { +{ + "data": [ + { "id": 1, - "firstname": "Paul", - "lastname": "Bocuse", - "username": null - }, - "created_at": "2020-07-31T11:37:16.964Z", - "updated_at": "2020-07-31T11:37:16.975Z", - "categories": [ - { - "id": 1, - "name": "French Food", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-07-31T11:36:23.164Z", - "updated_at": "2020-07-31T11:36:23.172Z" + "attributes": { + "name": "Biscotte Restaurant", + "description": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.", + "createdAt": "2022-07-31T09:14:12.569Z", + "updatedAt": "2022-07-31T09:14:12.569Z", + "publishedAt": "2022-07-31T09:14:12.569Z" } - ] + } + ], + "meta": { + "pagination": { + "page": 1, + "pageSize": 25, + "pageCount": 1, + "total": 1 + } } -] +} ``` :::: @@ -147,8 +139,8 @@ const Home = ({ restaurants, error }) => { } return ( ); @@ -180,8 +172,8 @@ const Home = ({ restaurants, error }) => { } return ( ); @@ -230,6 +222,7 @@ export default Home; Execute a `POST` request on the `restaurant` collection type in order to create a restaurant. Be sure that you activated the `create` permission for the `restaurant` collection type and the `find` permission for the `category` Collection type. +Add the `?populate=categories` query parameter to return categories with the response. In this example a `japanese` category has been created which has the id: 3. @@ -242,10 +235,13 @@ In this example a `japanese` category has been created which has the id: 3. import axios from 'axios'; axios - .post('http://localhost:1337/api/restaurants', { - name: 'Dolemon Sushi', - description: 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', - categories: [3], + .post('http://localhost:1337/api/restaurants/?populate=categories', { + data: { + name: 'Dolemon Sushi', + description: + 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', + categories: [3], + }, }) .then(response => { console.log(response); @@ -257,16 +253,20 @@ axios :::: tab fetch ::: request Example POST request with fetch + ```js -fetch('http://localhost:1337/api/restaurants', { +fetch('http://localhost:1337/api/restaurants/?populate=categories', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ - name: 'Dolemon Sushi', - description: 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', - categories: [3], + data: { + name: 'Dolemon Sushi', + description: + 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', + categories: [3], + }, }), }) .then(response => response.json()) @@ -278,29 +278,37 @@ fetch('http://localhost:1337/api/restaurants', { ::::: :::response Example response + ```json { - "id": 2, - "name": "Dolemon Sushi", - "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", - "created_by": null, - "updated_by": null, - "created_at": "2020-08-04T09:57:11.669Z", - "updated_at": "2020-08-04T09:57:11.669Z", - "categories": [ - { - "id": 3, - "name": "Japanese", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-07-31T11:36:23.164Z", - "updated_at": "2020-07-31T11:36:23.172Z" + "data": { + "id": 2, + "attributes": { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "createdAt": "2022-07-31T09:14:12.569Z", + "updatedAt": "2022-07-31T09:14:12.569Z", + "publishedAt": "2022-07-31T09:14:12.566Z", + "categories": { + "data": [ + { + "id": 3, + "attributes": { + "name": "Japanese", + "createdAt": "2022-07-31T10:49:03.933Z", + "updatedAt": "2022-07-31T10:49:04.893Z", + "publishedAt": "2022-07-31T10:49:04.890Z" + } + } + ] + } } - ] + }, + "meta": {} } ``` -::: +::: ### Example @@ -333,7 +341,9 @@ const Home = ({ allCategories, errorCategories }) => { e.preventDefault(); try { - const response = await axios.post('http://localhost:1337/api/restaurants', modifiedData); + const response = await axios.post('http://localhost:1337/api/restaurants', { + data: modifiedData, + }); console.log(response); } catch (error) { setErrorRestaurants(error); @@ -354,7 +364,7 @@ const Home = ({ allCategories, errorCategories }) => { }; return (
- + {
Select categories
- {allCategories.map(renderCheckbox)} + {allCategories.data.map(renderCheckbox)}

@@ -461,7 +471,7 @@ const Home = ({ allCategories, errorCategories }) => { const response = await fetch('http://localhost:1337/api/restaurants', { method: 'POST', headers, - body: JSON.stringify(modifiedData), + body: JSON.stringify({ data: modifiedData }), }) .then(checkStatus) .then(parseJSON); @@ -484,7 +494,7 @@ const Home = ({ allCategories, errorCategories }) => { }; return (
- + {
Select categories
- {allCategories.map(renderCheckbox)} + {allCategories.data.map(renderCheckbox)}

@@ -572,8 +582,10 @@ and the id of your category is `2`. import axios from 'axios'; axios - .put('http://localhost:1337/api/restaurants/2', { - categories: [2], + .put('http://localhost:1337/api/restaurants/2/?populate=categories', { + data: { + categories: [2], + }, }) .then(response => { console.log(response); @@ -585,14 +597,17 @@ axios :::: tab fetch ::: request Example PUT request with fetch + ```js -fetch('http://localhost:1337/api/restaurants/2', { +fetch('http://localhost:1337/api/restaurants/2/?populate=categories', { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ - categories: [2], + data: { + categories: [2], + }, }), }) .then(response => response.json()) @@ -609,27 +624,34 @@ fetch('http://localhost:1337/api/restaurants/2', { ```json { - "id": 2, - "name": "Dolemon Sushi", - "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", - "created_by": null, - "updated_by": null, - "created_at": "2020-08-04T10:21:30.219Z", - "updated_at": "2020-08-04T10:21:30.219Z", - "categories": [ - { - "id": 2, - "name": "Brunch", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-08-04T10:24:26.901Z", - "updated_at": "2020-08-04T10:24:26.911Z" + "data": { + "id": 2, + "attributes": { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "createdAt": "2022-07-31T09:14:12.569Z", + "updatedAt": "2022-07-31T11:17:31.598Z", + "publishedAt": "2022-07-31T09:14:12.566Z", + "categories": { + "data": [ + { + "id": 2, + "attributes": { + "name": "Brunch", + "createdAt": "2022-07-30T09:23:57.857Z", + "updatedAt": "2022-07-30T09:26:37.236Z", + "publishedAt": "2022-07-30T09:26:37.233Z" + } + } + ] + } } - ] + }, + "meta": {} } ``` -::: +::: ## Starter diff --git a/docs/developer-docs/latest/developer-resources/content-api/integrations/python.md b/docs/developer-docs/latest/developer-resources/content-api/integrations/python.md index 16d00b31b7..f5482a800c 100644 --- a/docs/developer-docs/latest/developer-resources/content-api/integrations/python.md +++ b/docs/developer-docs/latest/developer-resources/content-api/integrations/python.md @@ -6,8 +6,6 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/developer-resources/c # Getting Started with Python -!!!include(developer-docs/latest/developer-resources/content-api/snippets/integration-guide-not-updated.md)!!! - This integration guide is following the [Quick Start Guide](/developer-docs/latest/getting-started/quick-start.md). We assume that you have fully completed its "Hands-on" path, and therefore can consume the API by browsing this [url](http://localhost:1337/api/restaurants). If you haven't gone through the Quick Start Guide, the way you request a Strapi API with [Python](https://www.python.org/) remains the same except that you will not fetch the same content. @@ -38,66 +36,53 @@ Be sure that you activated the `find` permission for the `restaurant` collection ::: request Example GET request ```python -requests.get("http://localhost:1337/api/restaurants", - headers={ - 'Content-Type': 'application/json' - }) +requests.get("http://localhost:1337/api/restaurants") ``` + ::: ::: response Example response ```json -[ - { - "id": 1, - "name": "Biscotte Restaurant", - "description": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.", - "created_by": { - "id": 1, - "firstname": "Paul", - "lastname": "Bocuse", - "username": null - }, - "updated_by": { +{ + "data": [ + { "id": 1, - "firstname": "Paul", - "lastname": "Bocuse", - "username": null - }, - "created_at": "2020-07-31T11:37:16.964Z", - "updated_at": "2020-07-31T11:37:16.975Z", - "categories": [ - { - "id": 1, - "name": "French Food", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-07-31T11:36:23.164Z", - "updated_at": "2020-07-31T11:36:23.172Z" + "attributes": { + "name": "Biscotte Restaurant", + "description": "Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.", + "createdAt": "2022-07-31T11:57:01.330Z", + "updatedAt": "2022-07-31T11:57:44.945Z", + "publishedAt": "2022-07-31T11:57:44.943Z" } - ] + } + ], + "meta": { + "pagination": { + "page": 1, + "pageSize": 25, + "pageCount": 1, + "total": 1 + } } -] +} ``` + ::: :::: ### Example ```python -import requests import json +import requests class Restaurant: def __init__(self): - self.api_url = "http://localhost:1337" + self.api_url = "http://localhost:1337/api" def all(self): - r = requests.get(self.api_url + "/restaurants", - headers={ - 'Content-Type': 'application/json' - }) + r = requests.get(self.api_url + "/restaurants") return r.json() restaurant = Restaurant() @@ -109,6 +94,7 @@ print(restaurant.all()) Execute a `POST` request on the `restaurant` collection type in order to create a restaurant. Be sure that you activated the `create` permission for the `restaurant` collection type and the `find` permission for the `category` Collection type. +Add the `?populate=categories` query parameter to return categories with the response. In this example a `japanese` category has been created which has the id: 3. @@ -116,75 +102,99 @@ In this example a `japanese` category has been created which has the id: 3. ::: request Example POST request ```python -requests.post("http://localhost:1337/api/restaurants", -data=json_dumps({ - 'name': 'Dolemon Sushi', - 'description': 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', - 'categories': [3], - }), - headers={ - 'Content-Type': 'application/json' - }) +requests.post( + "http://localhost:1337/api/restaurants", + headers={"Content-Type": "application/json"}, + params={"populate": "categories"}, + data=json.dumps( + { + "data": { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "categories": [3], + } + } + ), +) ``` + ::: ::: response Example response ```json { - "id": 2, - "name": "Dolemon Sushi", - "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", - "created_by": null, - "updated_by": null, - "created_at": "2020-08-04T09:57:11.669Z", - "updated_at": "2020-08-04T09:57:11.669Z", - "categories": [ - { - "id": 3, - "name": "Japanese", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-07-31T11:36:23.164Z", - "updated_at": "2020-07-31T11:36:23.172Z" + "data": { + "id": 2, + "attributes": { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "createdAt": "2022-07-31T15:36:56.336Z", + "updatedAt": "2022-07-31T15:36:56.336Z", + "publishedAt": "2022-07-31T15:36:56.336Z", + "categories": { + "data": [ + { + "id": 3, + "attributes": { + "name": "japanese", + "createdAt": "2022-07-31T11:57:35.040Z", + "updatedAt": "2022-07-31T11:57:35.631Z", + "publishedAt": "2022-07-31T11:57:35.629Z" + } + } + ] + } } - ] + }, + "meta": {} } ``` + ::: :::: ### Example ```python -import requests import json +import requests class Restaurant: def __init__(self): - self.api_url = "http://localhost:1337" + self.api_url = "http://localhost:1337/api" def all(self): r = requests.get(self.api_url + "/restaurants") return r.json() def create(self, params): - r = requests.post(self.api_url + "/restaurants", - data=json.dumps({ - 'name': params["name"], - 'description': params["description"], - 'categories': params["categories"] - }), - headers={ - 'Content-Type': 'application/json' - }) + r = requests.post( + self.api_url + "/restaurants", + headers={"Content-Type": "application/json"}, + data=json.dumps( + { + "data": { + "name": params["name"], + "description": params["description"], + "categories": params["categories"], + } + } + ), + ) + return r.json() + restaurant = Restaurant() -print(restaurant.create({ - 'name': 'Dolemon Sushi', - 'description': 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', - 'categories': [3], -})) +print( + restaurant.create( + { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "categories": [3], + } + ) +) ``` ## PUT Request your collection type @@ -197,80 +207,98 @@ Be sure that you activated the `put` permission for the `restaurant` collection ::: request Example PUT request ```python -requests.put("http://localhost:1337/api/restaurants/2", -data=json_dumps({ - 'categories': [2] -}), -headers={ -'Content-Type': 'application/json' -}) +requests.put( + "http://localhost:1337/api/restaurants/2", + params={"populate": "categories"}, + headers={"Content-Type": "application/json"}, + data=json.dumps( + { + "data": { + "categories": [2], + } + } + ), +) ``` + ::: ::: response Example response ```json { - "id": 2, - "name": "Dolemon Sushi", - "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", - "created_by": null, - "updated_by": null, - "created_at": "2020-08-04T10:21:30.219Z", - "updated_at": "2020-08-04T10:21:30.219Z", - "categories": [ - { - "id": 2, - "name": "Brunch", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-08-04T10:24:26.901Z", - "updated_at": "2020-08-04T10:24:26.911Z" + "data": { + "id": 2, + "attributes": { + "name": "Dolemon Sushi", + "description": null, + "createdAt": "2022-07-31T15:43:44.039Z", + "updatedAt": "2022-07-31T15:46:29.903Z", + "publishedAt": "2022-07-31T15:43:44.038Z", + "categories": { + "data": [ + { + "id": 2, + "attributes": { + "name": "Brunch", + "createdAt": "2022-07-31T11:57:23.472Z", + "updatedAt": "2022-07-31T11:57:25.180Z", + "publishedAt": "2022-07-31T11:57:25.179Z" + } + } + ] + } } - ] + }, + "meta": {} } ``` + ::: :::: ### Example ```python -import requests import json +import requests class Restaurant: def __init__(self): - self.api_url = "http://localhost:1337" + self.api_url = "http://localhost:1337/api" def all(self): r = requests.get(self.api_url + "/restaurants") return r.json() def create(self, params): - r = requests.post(self.api_url + "/restaurants", - data=json.dumps({ - 'name': params["name"], - 'description': params["description"], - 'categories': params["categories"] - }), - headers={ - 'Content-Type': 'application/json' - }) + r = requests.post( + self.api_url + "/restaurants", + headers={"Content-Type": "application/json"}, + data=json.dumps( + { + "data": { + "name": params["name"], + "description": params["description"], + "categories": params["categories"], + } + } + ), + ) + return r.json() def update(self, id, params): - r = requests.put(self.api_url + "/restaurants/" + str(id), - data=json.dumps({ - 'categories': params["categories"] - }), - headers={ - 'Content-Type': 'application/json' - }) + r = requests.put( + self.api_url + "/restaurants/" + str(id), + headers={"Content-Type": "application/json"}, + params={"populate": "categories"}, + data=json.dumps({"data": {"categories": params["categories"]}}), + ) + return r.json() + restaurant = Restaurant() -print(restaurant.update(2, { - 'categories': [2] -})) +print(restaurant.update(2, {"categories": [2]})) ``` ## Conclusion diff --git a/docs/developer-docs/latest/developer-resources/content-api/integrations/ruby.md b/docs/developer-docs/latest/developer-resources/content-api/integrations/ruby.md index 6ce55c706a..7a73ea10d1 100644 --- a/docs/developer-docs/latest/developer-resources/content-api/integrations/ruby.md +++ b/docs/developer-docs/latest/developer-resources/content-api/integrations/ruby.md @@ -6,8 +6,6 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/developer-resources/c # Getting Started with Ruby -!!!include(developer-docs/latest/developer-resources/content-api/snippets/integration-guide-not-updated.md)!!! - This integration guide is following the [Quick Start Guide](/developer-docs/latest/getting-started/quick-start.md). We assume that you have fully completed its "Hands-on" path, and therefore can consume the API by browsing this [url](http://localhost:1337/api/restaurants). If you haven't gone through the Quick Start Guide, the way you request a Strapi API with [Ruby](https://www.ruby-lang.org/en/) remains the same except that you will not fetch the same content. @@ -49,10 +47,7 @@ Be sure that you activated the `find` permission for the `restaurant` collection ::: request Example GET request ```ruby -HTTParty.get('http://localhost:1337/api/restaurants', - header: { - 'Content-Type' => 'application/json' - }) +HTTParty.get('http://localhost:1337/api/restaurants/') ``` ::: @@ -60,38 +55,30 @@ HTTParty.get('http://localhost:1337/api/restaurants', ::: response Example response ```json -[ - { - "id": 1, - "name": "Biscotte Restaurant", - "description": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.", - "created_by": { - "id": 1, - "firstname": "Paul", - "lastname": "Bocuse", - "username": null - }, - "updated_by": { +{ + "data": [ + { "id": 1, - "firstname": "Paul", - "lastname": "Bocuse", - "username": null - }, - "created_at": "2020-07-31T11:37:16.964Z", - "updated_at": "2020-07-31T11:37:16.975Z", - "categories": [ - { - "id": 1, - "name": "French Food", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-07-31T11:36:23.164Z", - "updated_at": "2020-07-31T11:36:23.172Z" + "attributes": { + "name": "Biscotte Restaurant", + "description": "Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.", + "createdAt": "2022-07-31T11:57:01.330Z", + "updatedAt": "2022-07-31T11:57:44.945Z", + "publishedAt": "2022-07-31T11:57:44.943Z" } - ] + } + ], + "meta": { + "pagination": { + "page": 1, + "pageSize": 25, + "pageCount": 1, + "total": 1 + } } -] +} ``` + ::: :::: @@ -102,15 +89,11 @@ require 'httparty' class Restaurant include HTTParty - - def initialize - @api_url = "http://localhost:1337" - end + base_uri 'http://localhost:1337/api' def all - self.class.get("#{@api_url}/restaurants") + self.class.get('/restaurants') end - end restaurant = Restaurant.new @@ -122,6 +105,7 @@ puts restaurant.all Execute a `POST` request on the `restaurant` collection type in order to create a restaurant. Be sure that you activated the `create` permission for the `restaurant` collection type and the `find` permission for the `category` Collection type. +Add the `?populate=categories` query parameter to return the categories with the response. In this example a `japanese` category has been created which has the id: 3. @@ -129,14 +113,20 @@ In this example a `japanese` category has been created which has the id: 3. ::: request Example POST request ```ruby -HTTParty.post("http://localhost:1337/api/restaurants", +HTTParty.post( + 'http://localhost:1337/api/restaurants/', body: { - name: 'Dolemon Sushi', - description: 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', - categories: [3], + data: { + name: 'Dolemon Sushi', + description: 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', + categories: [3] + } }, header: { - 'Content-Type' => 'application/json' + 'Content-Type': 'application/json' + }, + query: { + 'populate': 'categories' } ) ``` @@ -147,25 +137,33 @@ HTTParty.post("http://localhost:1337/api/restaurants", ```json { - "id": 2, - "name": "Dolemon Sushi", - "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", - "created_by": null, - "updated_by": null, - "created_at": "2020-08-04T09:57:11.669Z", - "updated_at": "2020-08-04T09:57:11.669Z", - "categories": [ - { - "id": 3, - "name": "Japanese", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-07-31T11:36:23.164Z", - "updated_at": "2020-07-31T11:36:23.172Z" + "data": { + "id": 2, + "attributes": { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "createdAt": "2022-07-31T18:29:58.876Z", + "updatedAt": "2022-07-31T18:29:58.876Z", + "publishedAt": "2022-07-31T18:29:58.875Z", + "categories": { + "data": [ + { + "id": 3, + "attributes": { + "name": "japanese", + "createdAt": "2022-07-31T11:57:35.040Z", + "updatedAt": "2022-07-31T11:57:35.631Z", + "publishedAt": "2022-07-31T11:57:35.629Z" + } + } + ] + } } - ] + }, + "meta": {} } ``` + ::: :::: @@ -176,34 +174,36 @@ require 'httparty' class Restaurant include HTTParty + base_uri 'http://localhost:1337/api' def initialize - @api_url = "http://localhost:1337" + @options = { + header: { 'Content-Type': 'application/json' }, + query: { 'populate': 'categories' } + } end def all - self.class.get("#{@api_url}/restaurants") + self.class.get('/restaurants') end def create(params) - self.class.post("#{@api_url}/restaurants", - body: { + @options[:body] = { + data: { name: params[:name], description: params[:description], categories: params[:categories] - }, - header: { - 'Content-Type' => 'application/json' } - ) - end + } + self.class.post('/restaurants', @options) + end end restaurant = Restaurant.new puts restaurant.create({ - name: "Dolemon Sushi", - description: "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + name: 'Dolemon Sushi', + description: 'Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious', categories: [3] }) ``` @@ -213,17 +213,24 @@ puts restaurant.create({ Execute a `PUT` request on the `restaurant` collection type in order to update the category of a restaurant. Be sure that you activated the `put` permission for the `restaurant` collection type. +Add the `?populate=categories` query parameter to return the categories with the response. :::: api-call ::: request Example PUT request ```ruby -HTTParty.put("http://localhost:1337/api/restaurants/2", +HTTParty.put( + 'http://localhost:1337/api/restaurants/2', body: { - categories: [2] + data: { + categories: [2] + } }, header: { - 'Content-Type' => 'application/json' + 'Content-Type': 'application/json' + }, + query: { + 'populate': 'categories' } ) ``` @@ -234,25 +241,33 @@ HTTParty.put("http://localhost:1337/api/restaurants/2", ```json { - "id": 2, - "name": "Dolemon Sushi", - "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", - "created_by": null, - "updated_by": null, - "created_at": "2020-08-04T10:21:30.219Z", - "updated_at": "2020-08-04T10:21:30.219Z", - "categories": [ - { - "id": 2, - "name": "Brunch", - "created_by": 1, - "updated_by": 1, - "created_at": "2020-08-04T10:24:26.901Z", - "updated_at": "2020-08-04T10:24:26.911Z" + "data": { + "id": 2, + "attributes": { + "name": "Dolemon Sushi", + "description": "Unmissable Japanese Sushi restaurant. The cheese and salmon makis are delicious", + "createdAt": "2022-07-31T18:15:09.290Z", + "updatedAt": "2022-07-31T18:16:53.448Z", + "publishedAt": "2022-07-31T18:15:09.289Z", + "categories": { + "data": [ + { + "id": 2, + "attributes": { + "name": "Brunch", + "createdAt": "2022-07-31T11:57:23.472Z", + "updatedAt": "2022-07-31T11:57:25.180Z", + "publishedAt": "2022-07-31T11:57:25.179Z" + } + } + ] + } } - ] + }, + "meta": {} } ``` + ::: :::: @@ -263,43 +278,43 @@ require 'httparty' class Restaurant include HTTParty + base_uri 'http://localhost:1337/api' def initialize - @api_url = "http://localhost:1337" + @options = { + header: { 'Content-Type': 'application/json' }, + query: { 'populate': 'categories' } + } end def all - self.class.get("#{@api_url}/restaurants") + self.class.get('/restaurants') end def create(params) - self.class.post("#{@api_url}/restaurants", - body: { + @options[:body] = { + data: { name: params[:name], description: params[:description], categories: params[:categories] - }, - header: { - 'Content-Type' => 'application/json' } - ) + } + + self.class.post('/restaurants', @options) end def update(id, params) - self.class.put("#{@api_url}/restaurants/#{id}", - body: { + @options[:body] = { + data: { categories: params[:categories] - }, - header: { - 'Content-Type' => 'application/json' } - ) + } + self.class.put("/restaurants/#{id}", @options) end - end restaurant = Restaurant.new -puts restaurant.update(2, {categories: [2]}) +puts restaurant.update(16, { categories: [2] }) ``` ## Conclusion diff --git a/docs/developer-docs/latest/developer-resources/database-apis-reference/snippets/entity-query-knex-callout.md b/docs/developer-docs/latest/developer-resources/database-apis-reference/snippets/entity-query-knex-callout.md index db792261c3..15f80d9b4a 100644 --- a/docs/developer-docs/latest/developer-resources/database-apis-reference/snippets/entity-query-knex-callout.md +++ b/docs/developer-docs/latest/developer-resources/database-apis-reference/snippets/entity-query-knex-callout.md @@ -1,5 +1,5 @@ Strapi v4 offers several layers to interact with the backend and build your queries: -* The Entity Service API is the recommended API to interact with the Strapi backend. The Entity Service is the layer that handles Strapi's complex data structures like components and dynamic zones, which the lower-level layers are not aware of. -* The Query Engine API interacts with the database layer at a lower level and is used under the hood to execute database queries. It gives unrestricted internal access to the database layer, but should be used only if the Entity Service API does not cover your use case. -* If you need direct access to `knex` functions, use `strapi.db.connection`. +- The Entity Service API is the recommended API to interact with your application's database. The Entity Service is the layer that handles Strapi's complex data structures like components and dynamic zones, which the lower-level layers are not aware of. +- The Query Engine API interacts with the database layer at a lower level and is used under the hood to execute database queries. It gives unrestricted internal access to the database layer, but should be used only if the Entity Service API does not cover your use case. +- If you need direct access to `knex` functions, use `strapi.db.connection`. diff --git a/docs/developer-docs/latest/development/backend-customization/models.md b/docs/developer-docs/latest/development/backend-customization/models.md index a6f53e0c78..abd3d3f1dd 100644 --- a/docs/developer-docs/latest/development/backend-customization/models.md +++ b/docs/developer-docs/latest/development/backend-customization/models.md @@ -598,7 +598,6 @@ Lifecycle hooks are functions that take an `event` parameter, an object with the | -------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `action` | String | Lifecycle event that has been triggered (see [list](#available-lifecycle-events)) | | `model` | Object | Model object | -| `em` | EntityManagerObject | EntityManager | | | `params` | Object | Accepts the following parameters: | | `result` | Object | _Optional, only available with `afterXXX` events_

Contains the result of the action. | | `state` | Object | Query state, can be used to share state between `beforeXXX` and `afterXXX` events of a query. | diff --git a/docs/developer-docs/latest/development/backend-customization/services.md b/docs/developer-docs/latest/development/backend-customization/services.md index 2fd4091734..1df90482dc 100644 --- a/docs/developer-docs/latest/development/backend-customization/services.md +++ b/docs/developer-docs/latest/development/backend-customization/services.md @@ -158,7 +158,7 @@ module.exports = createCoreService('api::email.email', ({ strapi }) => ({ // path: ./src/api/email/services/email.ts -import { factories } from '@strapi/strapi'; //check with soup +import { factories } from '@strapi/strapi'; const nodemailer = require('nodemailer'); // Requires nodemailer to be installed (npm install nodemailer) // Create reusable transporter object using SMTP transport. diff --git a/docs/developer-docs/latest/development/providers.md b/docs/developer-docs/latest/development/providers.md index 27b68d0e2b..4cb30d513f 100644 --- a/docs/developer-docs/latest/development/providers.md +++ b/docs/developer-docs/latest/development/providers.md @@ -8,7 +8,7 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/development/providers Certain [plugins](../../../user-docs/latest/plugins/introduction-to-plugins.md) can be extended via the installation and configuration of additional [providers](../../../user-docs/latest/plugins/introduction-to-plugins.md#providers). -Providers add an extension to the core capabilities of the plugin, for example to upload media files to Rackspace instead of the local server, or using Amazon SES for emails instead of Sendmail. +Providers add an extension to the core capabilities of the plugin, for example to upload media files to AWS S3 instead of the local server, or using Amazon SES for emails instead of Sendmail. ::: note Only the [Upload](../plugins/upload.md) and [Email](../plugins/email.md) plugins are currently designed to work with providers. @@ -202,4 +202,4 @@ If you want to create your own provider without publishing it on npm you can fol ``` 4. Update your `./config/plugins.js` file to [configure the provider](#configuring-providers). -5. Finally, run `yarn install` or `npm install` to install your new custom provider. \ No newline at end of file +5. Finally, run `yarn install` or `npm install` to install your new custom provider. diff --git a/docs/developer-docs/latest/development/typescript.md b/docs/developer-docs/latest/development/typescript.md index dba7b8deb8..e4a1e393d3 100644 --- a/docs/developer-docs/latest/development/typescript.md +++ b/docs/developer-docs/latest/development/typescript.md @@ -6,14 +6,10 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/development/typescrip # TypeScript development -TypeScript adds an additional type system layer above JavaScript, which means that existing JavaScript code is also TypeScript code. Strapi supports TypeScript in new projects on v4.2.0 and above. TypeScript-enabled projects allow developing plugins with TypeScript as well as using TypeScript typings. +TypeScript adds an additional type system layer above JavaScript, which means that existing JavaScript code is also TypeScript code. Strapi supports TypeScript in new projects on v4.3.0 and above. Existing JavaScript projects can [add TypeScript support](#add-typescript-support-to-an-existing-strapi-project) through a conversion procedure. TypeScript-enabled projects allow developing plugins with TypeScript as well as using TypeScript typings. ::: strapi Getting started with TypeScript -To start developing in TypeScript, use the [CLI installation documentation](/developer-docs/latest/setup-deployment-guides/installation/cli.md) to create a new TypeScript project. Additionally, the [project structure](/developer-docs/latest/setup-deployment-guides/file-structure.md) and [TypeScript configuration](/developer-docs/latest/setup-deployment-guides/configurations/optional/typescript.md) sections have TypeScript-specific resources for understanding and configuring an application. -::: - -::: callout 🚧 JavaScript to TypeScript migration -Migrating existing Strapi applications written in JavaScript is not currently recommended. In the meantime, feel free to ask for help on the [forum](https://forum.strapi.io/) or the community [Discord](https://discord.strapi.io). +To start developing in TypeScript, use the [CLI installation documentation](/developer-docs/latest/setup-deployment-guides/installation/cli.md) to create a new TypeScript project. For existing projects, [TypeScript support can be added](#add-typescript-support-to-an-existing-strapi-project) with the provided conversion steps. Additionally, the [project structure](/developer-docs/latest/setup-deployment-guides/file-structure.md) and [TypeScript configuration](/developer-docs/latest/setup-deployment-guides/configurations/optional/typescript.md) sections have TypeScript-specific resources for understanding and configuring an application. ::: ## Start developing in TypeScript @@ -54,7 +50,7 @@ To experience TypeScript-based autocomplete while developing Strapi applications ```js // path: ./src/index.ts - import '@strapi/strapi'; + import { Strapi } from '@strapi/strapi'; export default { register( { strapi }: { strapi: Strapi }) { @@ -132,3 +128,86 @@ const appContext = await strapi.compile(); const app = await strapi(appContext); ``` + +## Add TypeScript support to an existing Strapi project + +Adding TypeScript support to an existing project requires adding 2 `tsconfig.json` files and rebuilding the admin panel. Additionally, the `eslintrc` and `eslintignore` files can be optionally removed. The TypeScript flag `allowJs` should be set to `true` in the root `tsconfig.json` file to incrementally add TypeScript files to existing JavaScript projects. The `allowJs` flag allows `.ts` and `.tsx` files to coexist with JavaScript files. + +TypeScript support can be added to an existing Strapi project using the following procedure: + +1. Add a `tsconfig.json` file at the project root and copy the following code, with the `allowJs` flag, to the file: + +```json +// path: ./tsconfig.json + +{ + "extends": "@strapi/typescript-utils/tsconfigs/server", + "compilerOptions": { + "outDir": "dist", + "rootDir": ".", + "allowJs": true //enables the build without .ts files + }, + "include": [ + "./", + "src/**/*.json" + ], + "exclude": [ + "node_modules/", + "build/", + "dist/", + ".cache/", + ".tmp/", + "src/admin/", + "**/*.test.ts", + "src/plugins/**" + ] + + } + +``` + +2. Add a `tsconfig.json` file in the `./src/admin/` directory and copy the following code to the file: + +```json +// path: ./src/admin/tsconfig.json + +{ + "extends": "@strapi/typescript-utils/tsconfigs/admin", + "include": [ + "../plugins/**/admin/src/**/*", + "./" + ], + "exclude": [ + "node_modules/", + "build/", + "dist/", + "**/*.test.ts" + ] + } + +``` + +3. (optional) Delete the `.eslintrc` and `.eslintignore` files from the project root. +4. Rebuild the admin panel and start the development server: + + + + +```sh +npm run build +npm run develop +``` + + + + + +```sh +yarn build +yarn develop +``` + + + + +After completing the preceding procedure a `dist` directory will be added at the project route and the project has access to the same TypeScript features as a new TypeScript-supported Strapi project. \ No newline at end of file diff --git a/docs/developer-docs/latest/getting-started/quick-start.md b/docs/developer-docs/latest/getting-started/quick-start.md index 5b2f6de759..ca1cb5a41a 100644 --- a/docs/developer-docs/latest/getting-started/quick-start.md +++ b/docs/developer-docs/latest/getting-started/quick-start.md @@ -87,9 +87,12 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/getting-started/quick Strapi offers a lot of flexibility. Whether you want to go fast and quickly see the final result, or would rather dive deeper into the product, we got you covered. ::: prerequisites -Make sure [Node.js and npm are properly installed](/developer-docs/latest/setup-deployment-guides/installation/cli.md#preparing-the-installation) on your machine. It is also possible to use Yarn instead of npm (see [install the Yarn package](https://yarnpkg.com/en/)). + +!!!include(developer-docs/latest/developer-resources/cli/snippets/installation-prerequisites.md)!!! + ::: + 👇 Let's get started! Using the big buttons below, please choose between: - the **Hands-on** path for a DIY approach to run your project diff --git a/docs/developer-docs/latest/plugins/upload.md b/docs/developer-docs/latest/plugins/upload.md index fd77fdf3d2..fa6b5cb2ad 100644 --- a/docs/developer-docs/latest/plugins/upload.md +++ b/docs/developer-docs/latest/plugins/upload.md @@ -15,11 +15,10 @@ The providers maintained by Strapi include: - [Amazon S3](https://www.npmjs.com/package/@strapi/provider-upload-aws-s3) - [Cloudinary](https://www.npmjs.com/package/@strapi/provider-upload-cloudinary) - [Local](https://www.npmjs.com/package/@strapi/provider-upload-local) -- [Rackspace](https://www.npmjs.com/package/@strapi/provider-upload-rackspace) ## Configuration -This section details configuration options for the default upload provider. If using another provider (e.g. AWS S3 or Rackspace), see the available configuration parameters in that provider's documentation. +This section details configuration options for the default upload provider. If using another provider (e.g. AWS S3 or Cloudinary), see the available configuration parameters in that provider's documentation. ### Local server diff --git a/docs/developer-docs/latest/plugins/users-permissions.md b/docs/developer-docs/latest/plugins/users-permissions.md index d2a2879af8..89efef2eca 100644 --- a/docs/developer-docs/latest/plugins/users-permissions.md +++ b/docs/developer-docs/latest/plugins/users-permissions.md @@ -67,11 +67,11 @@ axios Authorization: `Bearer ${token}`, }, }) - .then((response) => { + .then(response => { // Handle success. console.log('Data: ', response.data); }) - .catch((error) => { + .catch(error => { // Handle error. console.log('An error occurred:', error.response); }); @@ -132,7 +132,6 @@ export default ({ env }) => ({ - :::warning Setting JWT expiry for more than 30 days is **absolutely not recommended** due to massive security concerns. ::: @@ -154,13 +153,13 @@ axios email: 'user@strapi.io', password: 'strapiPassword', }) - .then((response) => { + .then(response => { // Handle success. console.log('Well done!'); console.log('User profile', response.data.user); console.log('User token', response.data.jwt); }) - .catch((error) => { + .catch(error => { // Handle error. console.log('An error occurred:', error.response); }); @@ -183,13 +182,13 @@ axios identifier: 'user@strapi.io', password: 'strapiPassword', }) - .then((response) => { + .then(response => { // Handle success. console.log('Well done!'); console.log('User profile', response.data.user); console.log('User token', response.data.jwt); }) - .catch((error) => { + .catch(error => { // Handle error. console.log('An error occurred:', error.response); }); @@ -250,11 +249,11 @@ export default ({ env }) => ({ url: env('', 'http://localhost:1337'), }); ``` + - :::tip Later on you will give this url to your provider.
For development, some providers accept the use of localhost urls but many don't. In this case we recommand to use [ngrok](https://ngrok.com/docs) (`ngrok http 1337`) that will make a proxy tunnel from a url it created to your localhost url (ex: `url: env('', 'https://5299e8514242.ngrok.io'),`). ::: @@ -775,10 +774,14 @@ Now you can make authenticated requests 🎉 More info here: [token usage](#toke - **You can't access your admin panel**: It's most likely because you built it with the backend url set with a ngrok url and you stopped/restarted ngrok. You need to replace the backend url with the new ngrok url and run `yarn build` or `npm run build` again. ::: -### Forgotten & reset password +### Reset password **Can only be used for users registered using the email provider.** +:::: tabs card + +::: tab Forgot & Reset flow + The flow was thought this way: 1. The user goes to your **forgotten password page** @@ -810,10 +813,10 @@ axios .post('http://localhost:1337/api/auth/forgot-password', { email: 'user@strapi.io', // user's email }) - .then((response) => { + .then(response => { console.log('Your user received an email'); }) - .catch((error) => { + .catch(error => { console.log('An error occurred:', error.response); }); ``` @@ -835,15 +838,43 @@ axios password: 'userNewPassword', passwordConfirmation: 'userNewPassword', }) - .then((response) => { + .then(response => { console.log("Your user's password has been reset."); }) - .catch((error) => { + .catch(error => { console.log('An error occurred:', error.response); }); ``` Congrats, you're done! +::: + +::: tab Change password flow + +You can also update an authenticated user password through the `/change-password` API endpoint: + +```js +import axios from 'axios'; + +// Request API. +axios.post( + 'http://localhost:1337/api/auth/change-password', + { + currentPassword: 'currentPassword', + password: 'userNewPassword', + passwordConfirmation: 'userNewPassword', + }, + { + headers: { + Authorization: 'Bearer ', + }, + } +); +``` + +::: + +:::: ### Email validation @@ -865,10 +896,10 @@ axios .post(`http://localhost:1337/api/auth/send-email-confirmation`, { email: 'user@strapi.io', // user's email }) - .then((response) => { + .then(response => { console.log('Your user received an email'); }) - .catch((error) => { + .catch(error => { console.error('An error occurred:', error.response); }); ``` @@ -882,7 +913,7 @@ The `user` object is available to successfully authenticated requests. - The authenticated `user` object is a property of `ctx.state`. ```js -create: async (ctx) => { +create: async ctx => { const { id } = ctx.state.user; const depositObj = { @@ -1065,7 +1096,6 @@ module.exports = { ```js - //path: ./extensions/users-permissions/config/jwt.ts export default { @@ -1077,7 +1107,6 @@ export default { - ::: tip You can learn more on configuration in the documentation [here](/developer-docs/latest/setup-deployment-guides/configurations.md). ::: diff --git a/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/digitalocean.md b/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/digitalocean.md index e590c5a73a..e89df54bfe 100644 --- a/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/digitalocean.md +++ b/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/digitalocean.md @@ -14,10 +14,6 @@ Databases can be on a [DigitalOcean Droplet](https://www.digitalocean.com/docs/d Prior to starting this guide, you should have created a [Strapi project](/developer-docs/latest/getting-started/quick-start.md). And have read through the [configuration](/developer-docs/latest/setup-deployment-guides/deployment.md#application-configuration) section. -::: tip -Strapi does have a [One-Click](/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.md) deployment option for DigitalOcean -::: - ### DigitalOcean Install Requirements - If you don't have a DigitalOcean account you will need to create one, you can use [this referral link](https://try.digitalocean.com/strapi/). diff --git a/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/heroku.md b/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/heroku.md index 66d56e6be7..02731c97b1 100644 --- a/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/heroku.md +++ b/docs/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/heroku.md @@ -415,7 +415,7 @@ heroku open Like with project updates on Heroku, the file system doesn't support local uploading of files as they will be wiped when Heroku "cycles" the dyno. This type of file system is called [ephemeral](https://devcenter.heroku.com/articles/dynos#ephemeral-filesystem), which means the file system only lasts until the dyno is restarted (with Heroku this happens any time you redeploy or during their regular restart which can happen every few hours or every day). -Due to Heroku's filesystem you will need to use an upload provider such as AWS S3, Cloudinary, or Rackspace. You can view the documentation for installing providers [here](/developer-docs/latest/development/providers.md) and you can see a list of providers from both Strapi and the community on [npmjs.com](https://www.npmjs.com/search?q=strapi-provider-upload-&page=0&perPage=20). +Due to Heroku's filesystem you will need to use an upload provider such as AWS S3 or Cloudinary. You can view the documentation for installing providers [here](/developer-docs/latest/development/providers.md) and you can see a list of providers from both Strapi and the community on [npmjs.com](https://www.npmjs.com/search?q=strapi-provider-upload-&page=0&perPage=20). ## Gzip diff --git a/docs/developer-docs/latest/setup-deployment-guides/installation.md b/docs/developer-docs/latest/setup-deployment-guides/installation.md index cbc8c73861..476543471c 100644 --- a/docs/developer-docs/latest/setup-deployment-guides/installation.md +++ b/docs/developer-docs/latest/setup-deployment-guides/installation.md @@ -6,7 +6,7 @@ canonicalUrl: https://docs.strapi.io/developer-docs/latest/setup-deployment-guid # Installation -Strapi projects and applications can be installed either locally on a computer, manually on a remote server, or on third-party services offering one-click installations options. The following installation guides will guide you step-by-step to create a new Strapi project and get it started. +Strapi projects and applications can be installed either locally on a computer or on a remote server. The following installation guides will guide you step-by-step instructions on how to install and create a new Strapi project. ## Local installations @@ -42,44 +42,4 @@ Strapi projects and applications can be installed either locally on a computer, Create a project on your local machine using Docker. - - -## One-click installations - -!!!include(developer-docs/latest/setup-deployment-guides/snippets/one-click-install-not-updated.md)!!! - -
- - - - - -
- -
- - - - - -
- -
- - - - - -
+ \ No newline at end of file diff --git a/docs/developer-docs/latest/setup-deployment-guides/installation/cli.md b/docs/developer-docs/latest/setup-deployment-guides/installation/cli.md index c0eb6fa939..38d5e51ce1 100644 --- a/docs/developer-docs/latest/setup-deployment-guides/installation/cli.md +++ b/docs/developer-docs/latest/setup-deployment-guides/installation/cli.md @@ -10,10 +10,7 @@ Strapi CLI (Command Line Interface) installation scripts are the fastest way to ## Preparing the installation -The CLI installation guide requires at least two software prerequisites to be already installed on your computer: - -- [Node.js](https://nodejs.org): only LTS versions are supported (v14 and v16). Other versions of Node.js may not be compatible with the latest release of Strapi. The 14.x version is most recommended by Strapi. -- [npm](https://docs.npmjs.com/cli/v6/commands/npm-install) (v6 only) or [yarn](https://yarnpkg.com/getting-started/install) to run the CLI installation scripts. +!!!include(developer-docs/latest/developer-resources/cli/snippets/installation-prerequisites.md)!!! A database is also required for any Strapi project. Strapi currently supports the following databases: diff --git a/docs/developer-docs/latest/setup-deployment-guides/installation/digitalocean-customization.md b/docs/developer-docs/latest/setup-deployment-guides/installation/digitalocean-customization.md deleted file mode 100644 index 2f23160d87..0000000000 --- a/docs/developer-docs/latest/setup-deployment-guides/installation/digitalocean-customization.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: DigitalOcean Virtual Machine Configuration - Strapi Developer Docs -description: Learn how to handle the DigitalOcean virtual machine running the Strapi application. ---- - -# DigitalOcean Virtual Machine Configuration - -This DigitalOcean configuration documentation is related to the [DigitalOcean One-click installation guide](/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.md). It should guide you through the handling of the DigitalOcean virtual machine running the Strapi application. - -You can click below for more information about the installed software and the Nginx server configuration. - -::: details Installed software -The Strapi application running on the droplet has the following softwares installed and configured: - -| Software | Version | Comments | -| ---------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -| Node.js | 12 | Installed via the official [apt repository](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions)) | -| Yarn | latest stable version | Installed via the official [apt repository](https://classic.yarnpkg.com/en/docs/install/#debian-stable)) | -| Nginx | latest version | Installed via Ubuntu default repository | -| UFW (Uncomplicated Firewall) | latest stable version | Configured to only allow incoming ports 80 (HTTP), 443 (HTTPS), and 22 (SSH) | -| PostgreSQL | latest version | Installed via Ubuntu default repository | -| PM2 | latest version | Installed globally using Yarn | - -::: - -::::: details Nginx default configuration -The DigitalOcean one-click application uses Nginx to proxy http on port 80 to Strapi. This is to ensure the system is secure as running any application on ports below 1024 require root permissions. - -Here are the config files included by default: - -:::: tabs card - -::: tab strapi.conf -Path: `/etc/nginx/sites-available/strapi.conf` - -``` -server { - -# Listen HTTP - listen 80; - server_name _; - -# Proxy Config - location / { - proxy_pass http://strapi; - proxy_http_version 1.1; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Server $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_pass_request_headers on; - } -} -``` - -::: - -::: tab upstream.conf -Path: `/etc/nginx/conf.d/upstream.conf` - -``` -upstream strapi { - server 127.0.0.1:1337; -} -``` - -::: - -:::: - -:::: tip TIP -To learn more about the Nginx proxy options you can view the Nginx proxy [documentation](http://nginx.org/en/docs/http/ngx_http_proxy_module.html). -:::: -::::: - -## Strapi service account - -For security purposes, the DigitalOcean virtual machine hosting the Strapi application uses a service user. This user is extremely limited into what it can do and access. - -The service user home directory is located at `/srv/strapi`. The actual Strapi application is located within this home directory at `/srv/strapi/strapi-development`. - -The Strapi application runs in the `development` environment to allow for creating content-types. It is not recommended to use it directly in production. For staging and production environments, it's recommended to configure a private git repository to commit changes into, and create a new application directory within the service user's home (e.g. `/srv/strapi/strapi-production`). - -To run the new `production` or `staging` environments you can refer to the [PM2 Documentation](https://pm2.keymetrics.io/docs/usage/quick-start/#managing-processes) - -### Accessing the service account - -To access your service account: - -1. SSH into the `root` user. Depending on your Operating System or your SSH client, there may be multiple ways to do this. You should refer to your SSH client documentation for clarification on using SSH keys. -2. Run the `sudo su strapi` command. This will take you to the `strapi` user's shell. - -To go back to the `root` user, run `exit`. - -::: warning -Please note that by default the strapi user cannot run `sudo` commands. This is intended. -::: - -### Controlling the Strapi service and viewing logs - -While identified as the service user on the DigitalOcean virtual machine, [PM2](https://pm2.keymetrics.io/docs/usage/quick-start/#managing-processes) can be used to control the Strapi process and view logs with the following commands: - -- `pm2 list`: Show a list of all running processes. The default service is called "strapi-development" and should be running with an ID of 0. -- `pm2 restart strapi-development`: Restart the Strapi process manually. -- `pm2 stop strapi-development`: Stop the Strapi process. -- `pm2 start strapi-development`: Start the Strapi process. Strapi will automatically start if the virtual machine is rebooted. -- `pm2 logs strapi-development`: Show the logs in real time; to exit, use Ctrl+C. - -:::tip TIP -You can also manually view the log files under `/srv/strapi/.pm2/logs` if you encounter any errors during the bootup. -::: - -## Strapi application access with ssh - -To ssh into your Strapi application, run the following command: - -```bash -ssh root@ -``` - -where `` should be replaced with the address found by clicking on the droplet name in the [droplets list on DigitalOcean](https://cloud.digitalocean.com/droplets). - -There is no password for SSH as DigitalOcean uses SSH keys by default with password authentication disabled. - -## PostgreSQL Password - -To change the PostgreSQL password and update Strapi's config: - -1. Log into the [`strapi`](#accessing-the-service-account) service user. -2. Run the `pm2 stop strapi-development` command to stop the current strapi process. -3. Run this command to change the password for the `strapi` database user: - -```bash -psql -c "ALTER USER strapi with password '';" -``` - -where `` should be replaced by the password you want to use. - -4. Update the `/srv/strapi/strapi-development/.env` file with the new password: - -``` -DATABASE_PASSWORD= -``` - -5. Restart Strapi and confirm the password change was successful by running these commands: - -```bash -pm2 start strapi-development -pm2 logs strapi-development -``` diff --git a/docs/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.md b/docs/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.md deleted file mode 100644 index a2b0076929..0000000000 --- a/docs/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: DigitalOcean One-click - Strapi Developer Docs -description: Quickly deploy a Strapi application on DigitalOcean by simply using their One-click button. -canonicalUrl: https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/installation/digitalocean-one-click.html ---- - -# DigitalOcean One-click - -::: caution -The one-click install droplet is currently missing from DigitalOcean's marketplace. We are not planning to continue support for this installation method but if you want to configure it yourself you can use our [one-click repo](https://github.com/strapi/one-click-deploy) to build the image yourself. -::: - -The following documentation will guide you through the one-click creation of a new Strapi project hosted on [DigitalOcean](https://www.digitalocean.com/) - -DigitalOcean is a cloud platform that helps to deploy and scale applications by offering an Infrastructure as a Service (IaaS) platform for developers. - -::: prerequisites -A DigitalOcean account is necessary to follow this installation guide. Please visit the [DigitalOcean website](https://try.digitalocean.com/strapi/) to create an account if you don't already have one. -::: - -## Creating a Strapi project - -1. Go to the Strapi page on DigitalOcean's marketplace. -2. Click on **Create Strapi Droplet** button. -3. Keep the selected "Shared CPU - Basic" plan. -4. Choose "Regular Intel with SSD" as a CPU option. -5. Select your virtual machine size (minimum of 2 GB/1 CPU). -6. Choose a datacenter region (closest to you or your target area). -7. Add a new SSH key. You can follow [this guide](https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/). -8. Give your virtual machine a hostname. -9. Click **Create Droplet**. It may take from 30 seconds to a few minutes for the droplet to start, and a few minutes more to finish the Strapi installation. - -## Running Strapi - -Your Strapi application on DigitalOcean will be running in development mode. It is not recommended to use the application directly in production. - -To visit your Strapi application: - -1. Go to the [droplets list on DigitalOcean](https://cloud.digitalocean.com/droplets), logged in. -2. Click on the droplet name that is used for your Strapi application. -3. Copy the public ipv4 address of the droplet. -4. Use this address to access the Strapi application. - -Visiting the Strapi application page for the first time will require to create the first administrator user. - -::: strapi Customization options for the DigitalOcean droplet -The DigitalOcean droplet includes everything you need to run Strapi. However, should you need to access and customize the droplet environment and change some of its settings, you may want to refer to [our dedicated documentation](/developer-docs/latest/setup-deployment-guides/installation/digitalocean-customization.md). You can also find the image generation [source code](https://github.com/strapi/one-click-deploy/tree/master/digital-ocean) on Strapi's GitHub. -::: diff --git a/docs/developer-docs/latest/setup-deployment-guides/installation/platformsh.md b/docs/developer-docs/latest/setup-deployment-guides/installation/platformsh.md deleted file mode 100644 index f5fe6a5470..0000000000 --- a/docs/developer-docs/latest/setup-deployment-guides/installation/platformsh.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Install using Platform.sh - Strapi Developer Docs -description: Quickly deploy a Strapi application using the official Platform.sh Strapi template. -canonicalUrl: https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/installation/platformsh.html -sidebarDepth: 1 ---- - -# Platform.sh One-Click - -!!!include(developer-docs/latest/setup-deployment-guides/snippets/one-click-install-not-updated.md)!!! - -The following documentation will guide you through the one-click creation of a new Strapi project hosted on [Platform.sh](https://platform.sh/). - -Platform.sh is a Platform as a Service (PaaS) that allows the management of multiple websites and applications. In particular, it allows to quickly install and deploy a Strapi application. - -::: prerequisites -A Platform.sh account is necessary to follow this installation guide. Please visit the [Platform.sh website](https://console.platform.sh/) to create an account if you don't already have one. -::: - -## Creating a Strapi project - -There are 2 ways to create a new project hosted on Platform.sh: either by clicking the **One-Click** button, or following the numbered steps right below the button. - - - Deploy on Platform.sh - - -1. In the [Platform.sh website](https://console.platform.sh/), click on the **Add project** button. -2. Select the *Use a template* option. -3. Fill the *Project name* and *Region* fields. -4. Click on the **Next** button. -5. Using the search bar, search for the `Strapi` template (see [source code](https://github.com/platformsh-templates/strapi#customizations)). -6. Select the template. After a few seconds, your Strapi application should be setup with a PostgreSQL database. - -## Running Strapi - -To visit your Strapi application: - -1. Go to the [Platform.sh website](https://console.platform.sh/), logged in. -2. Go to *Settings > Domains*. -3. Click on the Platform.sh domain name that is used for your Strapi application. diff --git a/docs/developer-docs/latest/setup-deployment-guides/installation/render.md b/docs/developer-docs/latest/setup-deployment-guides/installation/render.md deleted file mode 100644 index 4cf3a282c8..0000000000 --- a/docs/developer-docs/latest/setup-deployment-guides/installation/render.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Render One-Click - Strapi Developer Docs -description: Quickly deploy a Strapi application on Render by simply using their One-click button. -canonicalUrl: https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/installation/render.html ---- - -# Render One-Click - -!!!include(developer-docs/latest/setup-deployment-guides/snippets/one-click-install-not-updated.md)!!! - -The following documentation will guide you through the one-click creation of a new Strapi project hosted on [Render](https://render.com). - -Render is a cloud provider with persistent disks and managed PostgreSQL databases, that offers multiple different ways to store content. - -::: prerequisites -A Render account is necessary to follow this installation guide. Please visit [the Render dashboard](https://dashboard.render.com) to create an account if you do not already have one. -::: - -## Creating a Strapi project - -Render maintains 3 "Strapi on Render" example repositories (see [Render's Deploy Strapi guide](https://render.com/docs/deploy-strapi) for more information), which differ based on the database used and the storage location of uploaded media library files: - -- [Strapi with SQLite and uploads on disk](https://github.com/render-examples/strapi-sqlite) -- [Strapi with PostgreSQL and uploads on Cloudinary](https://github.com/render-examples/strapi-postgres-cloudinary) -- [Strapi with PostgreSQL and uploads on disk](https://github.com/render-examples/strapi-postgres) - -Once the choice between the 3 repositories is made: - -1. Fork the repository on GitHub. -2. In the README file of your forked repository, click the **Deploy on Render** button. -3. Make sure you granted Render the permission to access your forked repository. - -::: note -When using Cloudinary, you will be prompted to enter your account credentials as environment variables. Render encrypts environment variables and stores them securely. -::: - -## Running Strapi - -Your Strapi application on Render will be running in production mode, with `NODE_ENV=production`. However, to add or edit content-types via the admin panel (see [Content-type Builder](https://strapi.io/documentation/user-docs/latest/content-types-builder/introduction-to-content-types-builder.html) documentation), Strapi must be running locally in development mode. - -To run Strapi locally: - -1. Clone the forked repository to your local machine. -2. Still in terminal, access the repository using the `cd ` command. -3. Run the `yarn install && yarn develop` command to run your Strapi project. - -When committing changes and pushing them to your remote repository, Render will automatically deploy these changes to your production application. A [typical workflow](https://render.com/docs/deploy-strapi#development-%E2%86%92-staging-%E2%86%92-production) would also include a staging environment for testing. diff --git a/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/dependencies.md b/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/dependencies.md index a80e888af2..dc0597dfb3 100644 --- a/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/dependencies.md +++ b/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/dependencies.md @@ -112,8 +112,8 @@ The following table highlights new and removed packages: - Packages with a ✨ emoji before their name have a new name in Strapi v4 but do not need to be defined in your `package.json`. - Packages identified with the ❌ emoji have been removed from Strapi v4 and all references to these packages should be removed from the code. -| Package name in Strapi v3 | Package name in Strapi v4 | -| ---------------------------------- | ------------------------------------- | +| Package name in Strapi v3 | Package name in Strapi v4 | +| ---------------------------------- | -------------------------------------- | | strapi | ❗ @strapi/strapi | | strapi-database | ✨ @strapi/database | | strapi-admin | ✨ @strapi/admin | @@ -131,22 +131,22 @@ The following table highlights new and removed packages: | strapi-provider-upload-local | ✨ @strapi/provider-upload-local | | strapi-provider-upload-aws-s3 | 🔌 @strapi/provider-upload-aws-s3 | | strapi-provider-upload-cloudinary | 🔌 @strapi/provider-upload-cloudinary | -| strapi-provider-upload-rackspace | 🔌 @strapi/provider-upload-rackspace | | strapi-provider-email-sendmail | ✨ @strapi/provider-email-sendmail | | strapi-provider-email-amazon-ses | 🔌 @strapi/provider-email-amazon-ses | | strapi-provider-email-mailgun | 🔌 @strapi/provider-email-mailgun | | strapi-provider-email-nodemailer | 🔌 @strapi/provider-email-nodemailer | | strapi-provider-email-sendgrid | 🔌 @strapi/provider-email-sendgrid | -| create-strapi-starter | create-strapi-starter | -| create-strapi-app | create-strapi-app | -| strapi-generate-policy | strapi-generate-policy | -| strapi-generate-controller | strapi-generate-model | -| strapi-generate-model | strapi-generate-controller | -| strapi-generate-new | strapi-generate-new | -| strapi-generate | strapi-generate | -| strapi-generate-api | strapi-generate-api | -| strapi-generate-plugin | strapi-generate-plugin | -| strapi-generate-service | strapi-generate-service | +| create-strapi-starter | create-strapi-starter | +| create-strapi-app | create-strapi-app | +| strapi-generate-policy | strapi-generate-policy | +| strapi-generate-controller | strapi-generate-model | +| strapi-generate-model | strapi-generate-controller | +| strapi-generate-new | strapi-generate-new | +| strapi-generate | strapi-generate | +| strapi-generate-api | strapi-generate-api | +| strapi-generate-plugin | strapi-generate-plugin | +| strapi-generate-service | strapi-generate-service | +| strapi-provider-upload-rackspace | ❌ (removed from v4) | | strapi-connector-mongoose | ❌ (removed from v4) | | strapi-connector-bookshelf | ❌ (removed from v4) | | strapi-hook-redis | ❌ (removed from v4) | diff --git a/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/graphql.md b/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/graphql.md index 713149b4bc..925a705c44 100644 --- a/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/graphql.md +++ b/docs/developer-docs/latest/update-migration-guides/migration-guides/v4/code/backend/graphql.md @@ -43,7 +43,7 @@ The following code example adds a new `MyEnum` type definition to Strapi v3: module.exports = { definition: ` - enum MyInput { + enum MyEnum { a b c diff --git a/docs/package.json b/docs/package.json index 43153c639b..7e2b9f8487 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "strapi-docs", - "version": "4.3.2", + "version": "4.3.3", "main": "index.js", "scripts": { "dev": "yarn create:config-file && vuepress dev", diff --git a/docs/user-docs/latest/assets/media-library/media-library_folder-content.png b/docs/user-docs/latest/assets/media-library/media-library_folder-content.png index 66bf153ce7..06121fe2a4 100644 Binary files a/docs/user-docs/latest/assets/media-library/media-library_folder-content.png and b/docs/user-docs/latest/assets/media-library/media-library_folder-content.png differ diff --git a/docs/user-docs/latest/media-library/organizing-assets-with-folders.md b/docs/user-docs/latest/media-library/organizing-assets-with-folders.md index 2bfc3d5faf..03a7b41f8b 100644 --- a/docs/user-docs/latest/media-library/organizing-assets-with-folders.md +++ b/docs/user-docs/latest/media-library/organizing-assets-with-folders.md @@ -18,7 +18,7 @@ Folders follow the permission system of assets (see [Users, Roles & Permissions] By default, the Media Library displays folders and assets created at the root level. Clicking a folder navigates to this folder, and displays the following elements: -- the folder title and the number of subfolders and assets the current folder contains (1) +- the folder title and breadcrumbs to navigate to a parent folder (1) - the subfolders (2) the current folder contains - all assets (3) from this folder @@ -28,6 +28,10 @@ From this dedicated folder view, folders and assets can be managed, filtered, so To navigate back to the parent folder, one level up, use the **Back** button at the top of the interface. +::: tip +The breadcrumb navigation can also be used to go back to a parent folder: click on a folder name to directly jump to it or click on the 3 dots `...` and select a parent folder from the drop-down list. +::: + ## Adding folders To create a new folder in the Media Library: