mirror of
https://github.com/strapi/strapi.git
synced 2025-12-12 07:27:46 +00:00
Merge branch 'master' into typo-2
This commit is contained in:
commit
18a966ca7c
@ -124,8 +124,12 @@ module.exports = {
|
||||
collapsable: true,
|
||||
title: '📚 Guides',
|
||||
children: [
|
||||
'/3.0.0-beta.x/guides/update-version',
|
||||
'/3.0.0-beta.x/guides/databases',
|
||||
'/3.0.0-beta.x/guides/deployment',
|
||||
'/3.0.0-beta.x/guides/jwt-validation',
|
||||
'/3.0.0-beta.x/guides/error-catching',
|
||||
'/3.0.0-beta.x/guides/slug',
|
||||
'/3.0.0-beta.x/guides/webhooks',
|
||||
],
|
||||
},
|
||||
|
||||
@ -142,7 +142,7 @@ export default WysiwygWithErrors;
|
||||
|
||||
The AdminUI package source can be easily found in `./node_modules/strapi-admin/src/`.
|
||||
|
||||
For example, to change the top-left displayed admin panel's color, `./node_modules/strapi-admin/admin/src/components/LeftMenuHeader/styles.scss` should be overriden by `./admin/src/components/LeftMenuHeader/styles.scss` with your own styles.
|
||||
For example, to change the top-left displayed admin panel's color, copy the `./node_modules/strapi-admin/admin/src/components/LeftMenuHeader` folder to `./admin/src/components/LeftMenuHeader` and change the styles inside `./admin/src/components/LeftMenuHeader/Wrapper.js`.
|
||||
|
||||
Thus, you are replacing the files that would normally be in `node_modules/strapi-admin/admin/src` and directing them to `admin/src/some/file/path`.
|
||||
|
||||
|
||||
BIN
docs/3.0.0-beta.x/assets/guides/slug/fields.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/fields.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-after.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-after.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-before.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-before.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-config.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
@ -98,6 +98,8 @@ module.exports = async () => {
|
||||
|
||||
CRON tasks allow you to schedule jobs (arbitrary functions) for execution at specific dates, with optional recurrence rules. It only uses a single timer at any given time (rather than reevaluating upcoming jobs every second/minute).
|
||||
|
||||
This feature is powered by [`node-schedule`](https://www.npmjs.com/package/node-schedule) node modules. Check it for more information.
|
||||
|
||||
::: note
|
||||
Make sure the `enabled` cron config is set to `true` in `./config/environments/**/server.json` file.
|
||||
:::
|
||||
|
||||
@ -50,6 +50,8 @@ const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
|
||||
#### `find`
|
||||
|
||||
```js
|
||||
const { sanitizeEntity } = require('strapi-utils');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Retrieve records.
|
||||
@ -60,9 +62,9 @@ module.exports = {
|
||||
async find(ctx) {
|
||||
let entities;
|
||||
if (ctx.query._q) {
|
||||
entities = await service.search(ctx.query);
|
||||
entities = await strapi.services.restaurant.search(ctx.query);
|
||||
} else {
|
||||
entities = await service.find(ctx.query);
|
||||
entities = await strapi.services.restaurant.find(ctx.query);
|
||||
}
|
||||
|
||||
return entities.map(entity => sanitizeEntity(entity, { model }));
|
||||
@ -77,6 +79,8 @@ module.exports = {
|
||||
#### `findOne`
|
||||
|
||||
```js
|
||||
const { sanitizeEntity } = require('strapi-utils');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Retrieve a record.
|
||||
@ -85,7 +89,7 @@ module.exports = {
|
||||
*/
|
||||
|
||||
async findOne(ctx) {
|
||||
const entity = await service.findOne(ctx.params);
|
||||
const entity = await strapi.services.restaurant.findOne(ctx.params);
|
||||
return sanitizeEntity(entity, { model });
|
||||
},
|
||||
};
|
||||
@ -107,9 +111,9 @@ module.exports = {
|
||||
|
||||
count(ctx) {
|
||||
if (ctx.query._q) {
|
||||
return service.countSearch(ctx.query);
|
||||
return strapi.services.restaurant.countSearch(ctx.query);
|
||||
}
|
||||
return service.count(ctx.query);
|
||||
return strapi.services.restaurant.count(ctx.query);
|
||||
},
|
||||
};
|
||||
```
|
||||
@ -121,6 +125,8 @@ module.exports = {
|
||||
#### `create`
|
||||
|
||||
```js
|
||||
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Create a record.
|
||||
@ -132,9 +138,9 @@ module.exports = {
|
||||
let entity;
|
||||
if (ctx.is('multipart')) {
|
||||
const { data, files } = parseMultipartData(ctx);
|
||||
entity = await service.create(data, { files });
|
||||
entity = await strapi.services.restaurant.create(data, { files });
|
||||
} else {
|
||||
entity = await service.create(ctx.request.body);
|
||||
entity = await strapi.services.restaurant.create(ctx.request.body);
|
||||
}
|
||||
return sanitizeEntity(entity, { model });
|
||||
},
|
||||
@ -148,6 +154,8 @@ module.exports = {
|
||||
#### `update`
|
||||
|
||||
```js
|
||||
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Update a record.
|
||||
@ -159,9 +167,14 @@ module.exports = {
|
||||
let entity;
|
||||
if (ctx.is('multipart')) {
|
||||
const { data, files } = parseMultipartData(ctx);
|
||||
entity = await service.update(ctx.params, data, { files });
|
||||
entity = await strapi.services.restaurant.update(ctx.params, data, {
|
||||
files,
|
||||
});
|
||||
} else {
|
||||
entity = await service.update(ctx.params, ctx.request.body);
|
||||
entity = await strapi.services.restaurant.update(
|
||||
ctx.params,
|
||||
ctx.request.body
|
||||
);
|
||||
}
|
||||
|
||||
return sanitizeEntity(entity, { model });
|
||||
@ -176,6 +189,8 @@ module.exports = {
|
||||
#### `delete`
|
||||
|
||||
```js
|
||||
const { sanitizeEntity } = require('strapi-utils');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* delete a record.
|
||||
@ -184,7 +199,7 @@ module.exports = {
|
||||
*/
|
||||
|
||||
async delete(ctx) {
|
||||
const entity = await service.delete(ctx.params);
|
||||
const entity = await strapi.services.restaurant.delete(ctx.params);
|
||||
return sanitizeEntity(entity, { model });
|
||||
},
|
||||
};
|
||||
|
||||
@ -4,48 +4,50 @@
|
||||
|
||||
Models are a representation of the database's structure and lifecycle. They are split into two separate files. A JavaScript file that contains the lifecycle callbacks, and a JSON one that represents the data stored in the database and their format. The models also allow you to define the relationships between them.
|
||||
|
||||
**Path —** `./api/user/models/User.js`.
|
||||
**Path —** `./api/restaurant/models/Restaurant.js`.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
// Before saving a value.
|
||||
// Fired before an `insert` or `update` query.
|
||||
beforeSave: next => {
|
||||
// Use `this` to get your current object
|
||||
next();
|
||||
},
|
||||
beforeSave: (model, attrs, options) => {},
|
||||
|
||||
// After saving a value.
|
||||
// Fired after an `insert` or `update` query.
|
||||
afterSave: (doc, next) => {
|
||||
next();
|
||||
},
|
||||
afterSave: (model, attrs, options) => {},
|
||||
|
||||
// ... and more
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/user/models/User.settings.json`.
|
||||
**Path —** `./api/restaurant/models/Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"connection": "default",
|
||||
"info": {
|
||||
"name": "user",
|
||||
"description": "This represents the User Model"
|
||||
"name": "restaurant",
|
||||
"description": "This represents the Restaurant Model"
|
||||
},
|
||||
"attributes": {
|
||||
"firstname": {
|
||||
"cover": {
|
||||
"collection": "file",
|
||||
"via": "related",
|
||||
"plugin": "upload"
|
||||
},
|
||||
"name": {
|
||||
"default": "",
|
||||
"type": "string"
|
||||
},
|
||||
"lastname": {
|
||||
"type": "string"
|
||||
"description": {
|
||||
"default": "",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, there is a `User` model which contains two attributes `firstname` and `lastname`.
|
||||
In this example, there is a `Restaurant` model which contains two attributes `cover`, `name` and `description`.
|
||||
|
||||
### Where are the models defined?
|
||||
|
||||
@ -57,12 +59,12 @@ The models are defined in each `./api/**/models/` folder. Every JavaScript or JS
|
||||
If you are just starting out it is very convenient to generate some models with the Content Type Builder, directly in the admin interface. You can then review the generated model mappings on the code level. The UI takes over a lot of validation tasks and gives you a fast feeling for available features.
|
||||
:::
|
||||
|
||||
Use the CLI, and run the following command `strapi generate:model user firstname:string lastname:string`. Read the [CLI documentation](../cli/CLI.md) for more information.
|
||||
Use the CLI, and run the following command `strapi generate:model restaurant name:string description:text`. Read the [CLI documentation](../cli/CLI.md) for more information.
|
||||
|
||||
This will create two files located at `./api/user/models`:
|
||||
This will create two files located at `./api/restaurant/models`:
|
||||
|
||||
- `User.settings.json`: contains the list of attributes and settings. The JSON format makes the file easily editable.
|
||||
- `User.js`: imports `User.settings.json` and extends it with additional settings and lifecycle callbacks.
|
||||
- `Restaurant.settings.json`: contains the list of attributes and settings. The JSON format makes the file easily editable.
|
||||
- `Restaurant.js`: imports `Restaurant.settings.json` and extends it with additional settings and lifecycle callbacks.
|
||||
|
||||
::: note
|
||||
when you create a new API using the CLI (`strapi generate:api <name>`), a model is automatically created.
|
||||
@ -76,18 +78,18 @@ Additional settings can be set on models:
|
||||
- `collectionName` (string) - Collection's name (or table's name) in which the data should be stored.
|
||||
- `globalId` (string) -Global variable name for this model (case-sensitive).
|
||||
|
||||
**Path —** `User.settings.json`.
|
||||
**Path —** `Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"connection": "mongo",
|
||||
"collectionName": "Users_v1",
|
||||
"globalId": "Users",
|
||||
"collectionName": "Restaurants_v1",
|
||||
"globalId": "Restaurants",
|
||||
"attributes": {}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, the model `User` will be accessible through the `Users` global variable. The data will be stored in the `Users_v1` collection or table and the model will use the `mongo` connection defined in `./config/environments/**/database.json`
|
||||
In this example, the model `Restaurant` will be accessible through the `Restaurants` global variable. The data will be stored in the `Restaurants_v1` collection or table and the model will use the `mongo` connection defined in `./config/environments/**/database.json`
|
||||
|
||||
::: note
|
||||
The `connection` value can be changed whenever you want, but you should be aware that there is no automatic data migration process. Also if the new connection doesn't use the same ORM you will have to rewrite your queries.
|
||||
@ -101,12 +103,12 @@ The info key on the model-json states information about the model. This informat
|
||||
- `description`: The description of the model.
|
||||
- `mainField`: Determines which model-attribute is shown when displaying the model.
|
||||
|
||||
**Path —** `User.settings.json`.
|
||||
**Path —** `Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"name": "user",
|
||||
"name": "restaurant",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
@ -137,6 +139,7 @@ The following types are currently available:
|
||||
|
||||
- `string`
|
||||
- `text`
|
||||
- `richtext`
|
||||
- `integer`
|
||||
- `biginteger`
|
||||
- `float`
|
||||
@ -172,45 +175,24 @@ To improve the Developer eXperience when developing or using the administration
|
||||
|
||||
### Example
|
||||
|
||||
**Path —** `User.settings.json`.
|
||||
**Path —** `Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"connection": "default",
|
||||
"info": {
|
||||
"name": "user",
|
||||
"description": "This represents the User Model",
|
||||
"mainField": "email"
|
||||
},
|
||||
...
|
||||
"attributes": {
|
||||
"firstname": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastname": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "email",
|
||||
"required": true,
|
||||
"title": {
|
||||
"type": "string",
|
||||
"min": 3,
|
||||
"max": 99,
|
||||
"unique": true
|
||||
},
|
||||
"password": {
|
||||
"type": "password",
|
||||
"required": true,
|
||||
"private": true
|
||||
"description": {
|
||||
"default": "My descrioption",
|
||||
"type": "text",
|
||||
"required": true
|
||||
},
|
||||
"about": {
|
||||
"type": "description"
|
||||
},
|
||||
"age": {
|
||||
"type": "integer",
|
||||
"min": 18,
|
||||
"max": 99,
|
||||
"index": true
|
||||
},
|
||||
"birthday": {
|
||||
"type": "date"
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -243,21 +225,6 @@ A `pet` can be owned by someone (a `user`).
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/pet/controllers/Pet.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findPetsWithOwners: async ctx => {
|
||||
// Retrieve the list of pets with their owners.
|
||||
const pets = Pet.find().populate('owner');
|
||||
|
||||
// Send the list of pets.
|
||||
ctx.body = pets;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
@ -309,36 +276,6 @@ A `user` can have one `address`. And this address is only related to this `user`
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/user/controllers/User.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findUsersWithAddresses: async ctx => {
|
||||
// Retrieve the list of users with their addresses.
|
||||
const users = User.find().populate('address');
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = users;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/adress/controllers/Address.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findArticlesWithUsers: async ctx => {
|
||||
// Retrieve the list of addresses with their users.
|
||||
const articles = Address.find().populate('user');
|
||||
|
||||
// Send the list of addresses.
|
||||
ctx.body = addresses;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
@ -390,36 +327,6 @@ A `user` can have many `articles`, and an `article` can be related to one `user`
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/user/controllers/User.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findUsersWithArticles: async ctx => {
|
||||
// Retrieve the list of users with their articles.
|
||||
const users = User.find().populate('articles');
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = users;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/article/controllers/Article.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findArticlesWithAuthors: async ctx => {
|
||||
// Retrieve the list of articles with their authors.
|
||||
const articles = Article.find().populate('author');
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = articles;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
@ -486,36 +393,6 @@ A `product` can be related to many `categories`, so a `category` can have many `
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/product/controllers/Product.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findProductsWithCategories: async ctx => {
|
||||
// Retrieve the list of products.
|
||||
const products = Product.find().populate('categories');
|
||||
|
||||
// Send the list of products.
|
||||
ctx.body = products;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/category/controllers/Category.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findCategoriesWithProducts: async ctx => {
|
||||
// Retrieve the list of categories.
|
||||
const categories = Category.find().populate('products');
|
||||
|
||||
// Send the list of categories.
|
||||
ctx.body = categories;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
@ -644,102 +521,6 @@ A `Image` model might belongs to many either `Article` models or a `Product` mod
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/image/controllers/Image.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findFiles: async ctx => {
|
||||
// Retrieve the list of images with the Article or Product entries related to them.
|
||||
const images = Images.find().populate('related');
|
||||
|
||||
/*
|
||||
[{
|
||||
"_id": "5a81b0fa8c063a53298a934a",
|
||||
"url": "http://....",
|
||||
"name": "john_doe_avatar.png",
|
||||
"related": [{
|
||||
"_id": "5a81b0fa8c063a5393qj934a",
|
||||
"title": "John Doe is awesome",
|
||||
"description": "..."
|
||||
}, {
|
||||
"_id": "5a81jei389ns5abd75f79c",
|
||||
"name": "A simple chair",
|
||||
"description": "..."
|
||||
}]
|
||||
}]
|
||||
*/
|
||||
|
||||
// Send the list of files.
|
||||
ctx.body = images;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/article/controllers/Article.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findArticlesWithAvatar: async ctx => {
|
||||
// Retrieve the list of articles with the avatar (image).
|
||||
const articles = Article.find().populate('avatar');
|
||||
|
||||
/*
|
||||
[{
|
||||
"_id": "5a81b0fa8c063a5393qj934a",
|
||||
"title": "John Doe is awesome",
|
||||
"description": "...",
|
||||
"avatar": {
|
||||
"_id": "5a81b0fa8c063a53298a934a",
|
||||
"url": "http://....",
|
||||
"name": "john_doe_avatar.png"
|
||||
}
|
||||
}]
|
||||
*/
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = articles;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/product/controllers/Product.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findProductWithPictures: async ctx => {
|
||||
// Retrieve the list of products with the pictures (images).
|
||||
const products = Product.find().populate('pictures');
|
||||
|
||||
/*
|
||||
[{
|
||||
"_id": "5a81jei389ns5abd75f79c",
|
||||
"name": "A simple chair",
|
||||
"description": "...",
|
||||
"pictures": [{
|
||||
"_id": "5a81b0fa8c063a53298a934a",
|
||||
"url": "http://....",
|
||||
"name": "chair_position_1.png"
|
||||
}, {
|
||||
"_id": "5a81d22bee1ad45abd75f79c",
|
||||
"url": "http://....",
|
||||
"name": "chair_position_2.png"
|
||||
}, {
|
||||
"_id": "5a81d232ee1ad45abd75f79e",
|
||||
"url": "http://....",
|
||||
"name": "chair_position_3.png"
|
||||
}]
|
||||
}]
|
||||
*/
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = products;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
#### Database implementation
|
||||
|
||||
If you're using MongoDB as a database, you don't need to do anything. Everything is natively handled by Strapi. However, to implement a polymorphic relationship with SQL databases, you need to create two tables.
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
# API Endpoints
|
||||
|
||||
When you create a `Content Type` you will have a certain number of REST API endpoints available to interact with it.
|
||||
When you create a `Content Type` you will have a certain number of **REST API endpoints** available to interact with it.
|
||||
|
||||
As an example let's consider the `Restaurant` Content Type for the next steps.
|
||||
As an **example** let's consider the `Restaurant` as a **Content Type** and `Openning_hours` as a **Group** for the next steps.
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Content Type" id="content-type"
|
||||
|
||||
### `Restaurant` Content Type
|
||||
|
||||
@ -12,6 +16,10 @@ As an example let's consider the `Restaurant` Content Type for the next steps.
|
||||
| cover | media | Restaurant's cover image | |
|
||||
| opening_hours | group | Restaurant's opening hours group | `repeatable` |
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Group" id="group"
|
||||
|
||||
### `Opening_hours` Group
|
||||
|
||||
| Fields | Type | Description |
|
||||
@ -20,10 +28,14 @@ As an example let's consider the `Restaurant` Content Type for the next steps.
|
||||
| opening_hour | string | Meta's opening hour |
|
||||
| closing_hour | string | Meta's closing hour |
|
||||
|
||||
---
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Endpoints
|
||||
|
||||
Here is the list of endpoints generated for each of your **Content Types**
|
||||
|
||||
<style lang="stylus">
|
||||
#endpoint-table
|
||||
table
|
||||
@ -51,20 +63,121 @@ As an example let's consider the `Restaurant` Content Type for the next steps.
|
||||
|
||||
<div id="endpoint-table">
|
||||
|
||||
| Method | Path | Description |
|
||||
| :----- | :------------------------------------------- | :------------------------- |
|
||||
| GET | [/restaurants](#get-restaurants) | Get a list of restaurants |
|
||||
| GET | [/restaurants/count](#get-restaurants-count) | Count restaurants |
|
||||
| POST | [/restaurants](#post-restaurants) | Create a restaurant |
|
||||
| GET | [/restaurants/:id](#get-restaurants-id) | Get a specific restraurant |
|
||||
| DELETE | [/restaurants/:id](#delete-restaurants-id) | Delete a restaurant |
|
||||
| PUT | [/restaurants/:id](#put-restaurants-id) | Update a restaurant |
|
||||
| Method | Path | Description |
|
||||
| :----- | :---------------------------------------------- | :----------------------------------- |
|
||||
| GET | [/{content-type}](#get-restaurants) | Get a list of {content-type} entries |
|
||||
| GET | [/{content-type}/count](#get-restaurants-count) | Count {content-type} entries |
|
||||
| POST | [/{content-type}](#post-restaurants) | Create a {content-type} entry |
|
||||
| GET | [/{content-type}/:id](#get-restaurants-id) | Get a specific {content-type} entry |
|
||||
| DELETE | [/{content-type}/:id](#delete-restaurants-id) | Delete a {content-type} entry |
|
||||
| PUT | [/{content-type}/:id](#put-restaurants-id) | Update a {content-type} entry |
|
||||
|
||||
</div>
|
||||
|
||||
## GET `/restaurants`
|
||||
### Here some Content Type examples
|
||||
|
||||
Returns the restaurants matching the query filters. You can read more about parameters [here](./parameters.md).
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Restaurant" id="restaurant"
|
||||
|
||||
`Restaurant` **Content Type**
|
||||
|
||||
<div id="endpoint-table">
|
||||
|
||||
| Method | Path | Description |
|
||||
| :----- | :----------------- | :------------------------ |
|
||||
| GET | /restaurants | Get a list of restaurants |
|
||||
| GET | /restaurants/count | Count restaurants |
|
||||
| POST | /restaurants | Create a restaurant |
|
||||
| GET | /restaurants/:id | Get a specific restaurant |
|
||||
| DELETE | /restaurants/:id | Delete a restaurant |
|
||||
| PUT | /restaurants/:id | Update a restaurant |
|
||||
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Article" id="article"
|
||||
|
||||
`Article` **Content Type**
|
||||
|
||||
<div id="endpoint-table">
|
||||
|
||||
| Method | Path | Description |
|
||||
| :----- | :-------------- | :--------------------- |
|
||||
| GET | /articles | Get a list of articles |
|
||||
| GET | /articles/count | Count articles |
|
||||
| POST | /articles | Create a article |
|
||||
| GET | /articles/:id | Get a specific article |
|
||||
| DELETE | /articles/:id | Delete a article |
|
||||
| PUT | /articles/:id | Update a article |
|
||||
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Product" id="product"
|
||||
|
||||
`Product` **Content Type**
|
||||
|
||||
<div id="endpoint-table">
|
||||
|
||||
| Method | Path | Description |
|
||||
| :----- | :-------------- | :--------------------- |
|
||||
| GET | /products | Get a list of products |
|
||||
| GET | /products/count | Count products |
|
||||
| POST | /products | Create a product |
|
||||
| GET | /products/:id | Get a specific product |
|
||||
| DELETE | /products/:id | Delete a product |
|
||||
| PUT | /products/:id | Update a product |
|
||||
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Category" id="category"
|
||||
|
||||
`Category` **Content Type**
|
||||
|
||||
<div id="endpoint-table">
|
||||
|
||||
| Method | Path | Description |
|
||||
| :----- | :---------------- | :----------------------- |
|
||||
| GET | /categories | Get a list of categories |
|
||||
| GET | /categories/count | Count categories |
|
||||
| POST | /categories | Create a category |
|
||||
| GET | /categories/:id | Get a specific category |
|
||||
| DELETE | /categories/:id | Delete a category |
|
||||
| PUT | /categories/:id | Update a category |
|
||||
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Tag" id="tag"
|
||||
|
||||
`Tag` **Content Type**
|
||||
|
||||
<div id="endpoint-table">
|
||||
|
||||
| Method | Path | Description |
|
||||
| :----- | :---------- | :----------------- |
|
||||
| GET | /tags | Get a list of tags |
|
||||
| GET | /tags/count | Count tags |
|
||||
| POST | /tags | Create a tag |
|
||||
| GET | /tags/:id | Get a specific tag |
|
||||
| DELETE | /tags/:id | Delete a tag |
|
||||
| PUT | /tags/:id | Update a tag |
|
||||
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Get entries
|
||||
|
||||
Returns entries matching the query filters. You can read more about parameters [here](./parameters.md).
|
||||
|
||||
**Example request**
|
||||
|
||||
@ -97,9 +210,15 @@ GET http://localhost:1337/restaurants
|
||||
]
|
||||
```
|
||||
|
||||
## GET `/restaurants/count`
|
||||
## Count entries
|
||||
|
||||
Returns the count of restaurants matching the query filters. You can read more about parameters [here](./parameters.md).
|
||||
Returns the count of entries matching the query filters. You can read more about parameters [here](./parameters.md).
|
||||
|
||||
**Example request**
|
||||
|
||||
```js
|
||||
GET http://localhost:1337/restaurants/count
|
||||
```
|
||||
|
||||
**Example response**
|
||||
|
||||
@ -107,9 +226,9 @@ Returns the count of restaurants matching the query filters. You can read more a
|
||||
1
|
||||
```
|
||||
|
||||
## POST `/restaurants`
|
||||
## Create an entry
|
||||
|
||||
Creates a restaurant and returns its value.
|
||||
Creates an entry and returns its value.
|
||||
|
||||
**Example request**
|
||||
|
||||
@ -153,9 +272,9 @@ POST http://localhost:1337/restaurants
|
||||
}
|
||||
```
|
||||
|
||||
## GET `/restaurants/:id`
|
||||
## Get an entry
|
||||
|
||||
Returns a restaurant by id.
|
||||
Returns an entry by id.
|
||||
|
||||
**Example request**
|
||||
|
||||
@ -185,9 +304,9 @@ GET http://localhost:1337/restaurants/1
|
||||
}
|
||||
```
|
||||
|
||||
## PUT `/restaurants/:id`
|
||||
## Update an entry
|
||||
|
||||
Partially updates a restaurant by id and returns its value.
|
||||
Partially updates an entry by id and returns its value.
|
||||
Fields that aren't sent in the query are not changed in the db. Send a `null` value if you want to clear them.
|
||||
|
||||
**Example request**
|
||||
@ -245,9 +364,9 @@ PUT http://localhost:1337/restaurants/1
|
||||
}
|
||||
```
|
||||
|
||||
## DELETE `/restaurants/:id`
|
||||
## Delete an entry
|
||||
|
||||
Deletes a restaurant by id and returns its value.
|
||||
Deletes an entry by id and returns its value.
|
||||
|
||||
**Example request**
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# Parameters
|
||||
|
||||
See the [parameters' concepts](../concepts/concepts.md#parameters) for details.
|
||||
See the [parameters' concepts](../concepts/parameters.md) for details.
|
||||
|
||||
::: warning
|
||||
By default, the filters can only be used from `find` endpoints generated by the Content Type Builder and the [CLI](../cli/CLI.md). If you need to implement a filters system somewhere else, read the [programmatic usage](../guides/parameters.md) section.
|
||||
By default, the filters can only be used from `find` endpoints generated by the Content Type Builder and the [CLI](../cli/CLI.md). If you need to implement a filter system somewhere else, read the [programmatic usage](../concepts/parameters.md) section.
|
||||
:::
|
||||
|
||||
## Available operators
|
||||
|
||||
@ -130,5 +130,5 @@ npm -v
|
||||
You can also use yarn if you want [here](https://yarnpkg.com/en/docs/getting-started) are the instructions to get started with it.
|
||||
|
||||
::: tip NEXT STEPS
|
||||
👏 Congrats, you are all set! Now that Node.js is installed you can continue with the [Quick start guide](/3.0.0-beta.x/getting-started/quick-start.html).
|
||||
👏 Congrats, you are all set! Now that Node.js is installed you can continue with the [Quick start guide](quick-start.md).
|
||||
:::
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Introduction
|
||||
# Introduction
|
||||
|
||||
Welcome to the open source [headless CMS](https://strapi.io) developers love.
|
||||
|
||||
@ -6,15 +6,13 @@ Welcome to the open source [headless CMS](https://strapi.io) developers love.
|
||||
|
||||
### 👋 Welcome onboard!
|
||||
|
||||
Users love Strapi because it is open source, MIT licensed, fully customizable and based on Node.js. Strapi lets you manage your content and distribute it anywhere. Strapi allows you to securely and privately serve your database of choice from your hosting and server of choice.
|
||||
Users love Strapi because it is open source, MIT licensed, fully customizable and based on Node.js. Strapi lets you manage your content and distribute it anywhere. Strapi allows you to securely and privately serve your database from your hosting and server of choice.
|
||||
|
||||
### Get Started
|
||||
|
||||
You are invited to get started using Strapi. You may explore Strapi by:
|
||||
|
||||
1. A [Quick Start Guide](../getting-started/quick-start.html) for more intermediate to advanced developers.
|
||||
2. A [Tutorial](../getting-started/quick-start-tutorial.html) for those who prefer a step-by-step introduction.
|
||||
|
||||
When you're done getting started, we invite you to join our [community](https://strapi.io/community).
|
||||
|
||||
1. A [Quick Start Guide](quick-start.md) for more intermediate to advanced developers.
|
||||
2. A [Tutorial](quick-start-tutorial.md) for those who prefer a step-by-step introduction.
|
||||
|
||||
When you're done getting started, we invite you to join our [community](https://strapi.io/community).
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Tutorial
|
||||
|
||||
This **tutorial** is written for developers to **teach and explain** a step-by-step introduction to Strapi. (The [Quick Start Guide](/3.0.0-beta.x/getting-started/quick-start.html) is a more concise **How-to** version.) This tutorial takes you through the beginning steps of how you start a project like **"FoodAdvisor"** ([Github](https://github.com/strapi/foodadvisor/))([Demo](https://foodadvisor.strapi.io/)).
|
||||
This **tutorial** is written for developers to **teach and explain** a step-by-step introduction to Strapi. (The [Quick Start Guide](quick-start.md) is a more concise **How-to** version.) This tutorial takes you through the beginning steps of how you start a project like **"FoodAdvisor"** ([Github](https://github.com/strapi/foodadvisor/))([Demo](https://foodadvisor.strapi.io/)).
|
||||
|
||||
You get a good overview of the features developers love found in Strapi.
|
||||
|
||||
@ -10,20 +10,13 @@ By following this tutorial, you install and create your first Strapi project.
|
||||
|
||||
::: tip NOTE
|
||||
|
||||
You need to have **_Node.js and npm_** installed on your system before following these steps. If you do not have Node.js and npm installed (or are not sure), please visit our [Installation Requirements](/3.0.0-beta.x/getting-started/install-requirements.html).
|
||||
You need to have **_Node.js and npm_** installed on your system before following these steps. If you do not have Node.js and npm installed (or are not sure), please visit our [Installation Requirements](install-requirements.md).
|
||||
|
||||
:::
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
1. [Install Strapi and create project](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_1-install-strapi-and-create-a-project)
|
||||
2. [Create an Administrator and front-end User](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_2-create-an-adminstrator-and-front-end-user)
|
||||
3. [Create a new Content Type called, "Restaurant"](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_3-create-a-new-content-type-called-restaurant)
|
||||
4. [Create a new Content Type called, "Category"](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_4-create-a-new-content-type-called-category)
|
||||
5. [Create a new Group and Repeatable Field called, "Hours of Operations"](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_5-create-a-new-group-and-repeatable-field-called-hours-of-operation)
|
||||
6. [Manage and add content to the "Restaurant" Content Type](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_6-manage-and-add-content-to-a-restaurant-content-type)
|
||||
7. [Set Roles and Permissions](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_7-set-roles-and-permissions)
|
||||
8. [Consume the Content Type API](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_8-consume-the-content-type-api)
|
||||
[[toc]]
|
||||
|
||||
## 1. Install Strapi and create a project
|
||||
|
||||
@ -140,7 +133,7 @@ Using the `--quickstart` flag installs Strapi using an [SQLite](https://www.sqli
|
||||
|
||||
**Note:** An **SQLite** database is an excellent database to use for prototyping and _developing_ Strapi projects. **SQLite** is a light database that ports effortlessly to the other relational databases (**MySQL**, **PostgreSQL**, and **MariaDB**). It is recommended to **develop** with SQLite and to use another relational database (MySQL, PostgreSQL or MariaDB) in production.
|
||||
|
||||
**Note:** If you would like to use **MongoDB** in production, you need to [install, run, and use MongoDB to develop your Strapi project (in development)](/3.0.0-beta.x/guides/databases.html#mongodb-installation).
|
||||
**Note:** If you would like to use **MongoDB** in production, you need to [install, run, and use MongoDB to develop your Strapi project (in development)](../guides/databases.md#mongodb-installation).
|
||||
:::
|
||||
|
||||
You are now ready to create a new **Administrator** and new front-end **User**.
|
||||
@ -626,7 +619,7 @@ If you would like to see the route of any specific **Content Type**, you need to
|
||||
👏 Congratulations, you have now completed the **Strapi Getting Started Tutorial**. Where to go next?
|
||||
|
||||
- Learn how to use Strapi with React ([Gatsby](https://blog.strapi.io/building-a-static-website-using-gatsby-and-strapi) or [Next.js](https://blog.strapi.io/strapi-next-setup/)) or Vue.js ([Nuxt.js](https://blog.strapi.io/cooking-a-deliveroo-clone-with-nuxt-vue-js-graphql-strapi-and-stripe-setup-part-1-7/)).
|
||||
- Read the [concepts](../concepts/concepts.html) to deep dive into Strapi
|
||||
- Read the **concepts** to deep dive into Strapi
|
||||
- Get help on [StackOverflow](https://stackoverflow.com/questions/tagged/strapi)
|
||||
- Read the [source code](https://github.com/strapi/strapi), [contribute](https://github.com/strapi/strapi/blob/master/CONTRIBUTING.md) or [give a star](https://github.com/strapi/strapi) on GitHub
|
||||
- Follow us on [Twitter](https://twitter.com/strapijs) to get the latest news
|
||||
|
||||
@ -6,9 +6,9 @@ Get ready to get Strapi up and running in **less than 5 minutes** 🚀.
|
||||
<iframe width="853" height="480" src="https://www.youtube.com/embed/4m1wKzzfs-M" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
_For a step-by-step guide, please take a look at the [detailed tutorial](quick-start-tutorial.html)._
|
||||
_For a step-by-step guide, please take a look at the [detailed tutorial](quick-start-tutorial.md)._
|
||||
|
||||
(Before continuing, please make sure [Node.js and npm are properly installed](install-requirements.html) on your machine. You can [install the Yarn v1.2.0+ package here](https://yarnpkg.com/en/).)
|
||||
(Before continuing, please make sure [Node.js and npm are properly installed](install-requirements.md) on your machine. You can [install the Yarn v1.2.0+ package here](https://yarnpkg.com/en/).)
|
||||
|
||||
## 1. Install Strapi and Create a new project
|
||||
|
||||
@ -111,7 +111,7 @@ Here we are! The list of **restaurants** is accessible at [`http://localhost:133
|
||||
👏 Congratulations, you have now completed the **Strapi Quick Start**. Where to go next?
|
||||
|
||||
- Learn how to use Strapi with React ([Gatsby](https://blog.strapi.io/building-a-static-website-using-gatsby-and-strapi) or [Next.js](https://blog.strapi.io/strapi-next-setup/)) or Vue.js ([Nuxt.js](https://blog.strapi.io/cooking-a-deliveroo-clone-with-nuxt-vue-js-graphql-strapi-and-stripe-setup-part-1-7/)).
|
||||
- Read the [concepts](../concepts/concepts.html) and do the [Tutorial](/3.0.0-beta.x/getting-started/quick-start-tutorial.html) to deep dive into Strapi.
|
||||
- Read the **concepts** and do the [Tutorial](quick-start-tutorial.md) to deep dive into Strapi.
|
||||
- Get help on [StackOverflow](https://stackoverflow.com/questions/tagged/strapi).
|
||||
- Read the [source code](https://github.com/strapi/strapi), [contribute](https://github.com/strapi/strapi/blob/master/CONTRIBUTING.md) or [give a star](https://github.com/strapi/strapi) on GitHub.
|
||||
- Follow us on [Twitter](https://twitter.com/strapijs) to get the latest news.
|
||||
|
||||
@ -4,12 +4,12 @@ Strapi gives you the option to choose the most appropriate database for your pro
|
||||
**MariaDB**. The following documentation covers how to install these databases locally (for development purposes) and on various hosted or cloud server solutions (for staging or production purposes).
|
||||
|
||||
:::note
|
||||
Deploying **Strapi** itself is covered in the [Deployment Guide](/3.0.0-beta.x/guides/deployment.html).
|
||||
Deploying **Strapi** itself is covered in the [Deployment Guide](deployment.md).
|
||||
:::
|
||||
|
||||
## SQLite Installation
|
||||
|
||||
SQLite is the default ([Quick Start](/3.0.0-beta.x/getting-started/quick-start.html)) and recommended database to quickly create an app locally.
|
||||
SQLite is the default ([Quick Start](../getting-started/quick-start.md)) and recommended database to quickly create an app locally.
|
||||
|
||||
### Install SQLite locally
|
||||
|
||||
@ -38,7 +38,7 @@ npx create-strapi-app my-project --quickstart
|
||||
This will create a new project and launch it in the browser.
|
||||
|
||||
::: note
|
||||
The [Quick Start Guide](/3.0.0-beta.x/getting-started/quick-start.html) is a complete step-by-step tutorial
|
||||
The [Quick Start Guide](../getting-started/quick-start.md) is a complete step-by-step tutorial
|
||||
:::
|
||||
|
||||
## MongoDB Installation
|
||||
@ -240,7 +240,7 @@ $ strapi develop
|
||||
|
||||
```
|
||||
|
||||
You have successfully installed Strapi with MongoDB on your local development environment. You are now ready to [create your first user](/3.0.0-beta.x/getting-started/quick-start.html#_3-create-an-admin-user).
|
||||
You have successfully installed Strapi with MongoDB on your local development environment. You are now ready to [create your first user](../getting-started/quick-start.md#_3-create-an-admin-user).
|
||||
|
||||
---
|
||||
|
||||
@ -248,7 +248,7 @@ You have successfully installed Strapi with MongoDB on your local development en
|
||||
|
||||
Follow these steps to configure a local Strapi project to use a [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) free 512 MB account in production. (Please see [MongoDB Atlas Documentation](https://docs.atlas.mongodb.com/getting-started/) if you have any questions.)
|
||||
|
||||
- You must have already [created your Strapi project using MongoDB](/3.0.0-beta.x/guides/databases.html#install-strapi-locally-with-mongodb).
|
||||
- You must have already [created your Strapi project using MongoDB](databases.md#install-strapi-locally-with-mongodb).
|
||||
- You must have already created a [free MongoDB Atlas account](https://www.mongodb.com/cloud/atlas).
|
||||
|
||||
#### 1. Log in to your account to create a **Project** and a **Cluster**
|
||||
@ -342,7 +342,7 @@ The above configuration will create a database called `strapi`, the _default dat
|
||||
:::
|
||||
|
||||
::: danger WARNING
|
||||
We recommend replacing sensitive (eg. "URI string" above) information in your database.json files before uploading your project to a public repository such as GitHub. For more information about using environment variables, please read [dynamic configurations](/3.0.0-beta.x/configurations/configurations.html#dynamic-configurations).
|
||||
We recommend replacing sensitive (eg. "URI string" above) information in your database.json files before uploading your project to a public repository such as GitHub. For more information about using environment variables, please read [dynamic configurations](../concepts/configurations.md#dynamic-configurations).
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
Strapi gives you many possible deployment options for your project or application. Strapi can be deployed on traditional hosting servers or services such as Heroku, AWS, Azure and others. The following documentation covers how to develop locally with Strapi and deploy Strapi with various hosting options.
|
||||
|
||||
::: note
|
||||
Deploying **databases** along with Strapi is covered in the [Databases Guide](/3.0.0-beta.x/guides/databases.html).
|
||||
Deploying **databases** along with Strapi is covered in the [Databases Guide](../guides/databases.md).
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
@ -24,7 +24,7 @@ Update the `production` settings with the IP and domain name where the project w
|
||||
In case your database is not running on the same server, make sure that the environment of your production
|
||||
database (`./config/environments/production/database.json`) is set properly.
|
||||
|
||||
If you are passing a number of configuration item values via environment variables which is always encouraged for production environment, read the section for [Dynamic Configuration](../configurations/configurations.md#dynamic-configurations). Here is an example:
|
||||
If you are passing a number of configuration item values via environment variables which is always encouraged for production environment, read the section for [Dynamic Configuration](../concepts/configurations.md#dynamic-configurations). Here is an example:
|
||||
|
||||
**Path —** `./config/environments/production/server.json`.
|
||||
|
||||
@ -95,11 +95,11 @@ strapi(/* {...} */).start();
|
||||
|
||||
### Advanced configurations
|
||||
|
||||
If you want to host the administration on another server than the API, [please take a look at this dedicated section](../advanced/customize-admin.md#deployment).
|
||||
If you want to host the administration on another server than the API, [please take a look at this dedicated section](../admin-panel/deploy.md).
|
||||
|
||||
## Amazon AWS
|
||||
|
||||
This is a step-by-step guide for deploying a Strapi project to [Amazon AWS EC2](https://aws.amazon.com/ec2/). This guide will connect to an [Amazon AWS RDS](https://aws.amazon.com/rds/) for managing and hosting the database. Optionally, this guide will show you how to connect host and serve images on [Amazon AWS S3](https://aws.amazon.com/s3/). Prior to starting this guide, you should have created a [Strapi project](/3.0.0-beta.x/getting-started/quick-start.html), to use for deploying on AWS.
|
||||
This is a step-by-step guide for deploying a Strapi project to [Amazon AWS EC2](https://aws.amazon.com/ec2/). This guide will connect to an [Amazon AWS RDS](https://aws.amazon.com/rds/) for managing and hosting the database. Optionally, this guide will show you how to connect host and serve images on [Amazon AWS S3](https://aws.amazon.com/s3/). Prior to starting this guide, you should have created a [Strapi project](../getting-started/quick-start.md), to use for deploying on AWS.
|
||||
|
||||
### Amazon AWS Install Requirement and creating an IAM non-root user
|
||||
|
||||
@ -748,7 +748,7 @@ Your `Strapi` project has been installed on an **AWS EC2 instance** using **Ubun
|
||||
|
||||
## Digital Ocean
|
||||
|
||||
This is a step-by-step guide for deploying a Strapi project to [Digital Ocean](https://www.digitalocean.com/). Databases can be on a [Digital Ocean Droplet](https://www.digitalocean.com/docs/droplets/) or hosted externally as a service. Prior to starting this guide, you should have created a [Strapi project](/3.0.0-beta.x/getting-started/quick-start.html).
|
||||
This is a step-by-step guide for deploying a Strapi project to [Digital Ocean](https://www.digitalocean.com/). Databases can be on a [Digital Ocean Droplet](https://www.digitalocean.com/docs/droplets/) or hosted externally as a service. Prior to starting this guide, you should have created a [Strapi project](../getting-started/quick-start.md).
|
||||
|
||||
### Digital Ocean Install Requirements
|
||||
|
||||
@ -979,7 +979,7 @@ Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
|
||||
Firewall is active and enabled on system startup
|
||||
```
|
||||
|
||||
Your Strapi project is now installed on your **Droplet**. You have a few more steps prior to being able to access Strapi and [create your first user](https://strapi.io/documentation/3.0.0-beta.x/getting-started/quick-start.html#_3-create-an-admin-user).
|
||||
Your Strapi project is now installed on your **Droplet**. You have a few more steps prior to being able to access Strapi and [create your first user](../getting-started/quick-start.md#_3-create-an-admin-user).
|
||||
|
||||
You will next need to [install and configure PM2 Runtime](#install-and-configure-pm2-runtime).
|
||||
|
||||
@ -1037,7 +1037,7 @@ pm2 start ecosystem.config.js
|
||||
|
||||
`pm2` is now set-up to use an `ecosystem.config.js` to manage restarting your application upon changes. This is a recommended best practice.
|
||||
|
||||
**OPTIONAL:** You may see your project and set-up your first administrator user, by [creating an admin user](https://strapi.io/documentation/3.0.0-beta.x/getting-started/quick-start.html#_3-create-an-admin-user).
|
||||
**OPTIONAL:** You may see your project and set-up your first administrator user, by [creating an admin user](../getting-started/quick-start.md#_3-create-an-admin-user).
|
||||
|
||||
::: note
|
||||
Earlier, `Port 1337` was allowed access for **testing and setup** purposes. After setting up **NGINX**, the **Port 1337** needs to have access **denied**.
|
||||
@ -1298,11 +1298,11 @@ Follow the instructions and return to your command line.
|
||||
|
||||
#### 3. Create a new project (or use an existing one)
|
||||
|
||||
Create a [new Strapi project](/3.0.0-beta.x/getting-started/quick-start.html) (if you want to deploy an existing project go to step 4).
|
||||
Create a [new Strapi project](../getting-started/quick-start.md) (if you want to deploy an existing project go to step 4).
|
||||
|
||||
::: warning NOTE
|
||||
|
||||
If you plan to use **MongoDB** with your project, [refer to the create a Strapi project with MongoDB section of the documentation](/3.0.0-beta.x/guides/databases.html#install-mongodb-locally) then, jump to step 4.
|
||||
If you plan to use **MongoDB** with your project, [refer to the create a Strapi project with MongoDB section of the documentation](../guides/databases.md#install-mongodb-locally) then, jump to step 4.
|
||||
|
||||
:::
|
||||
|
||||
@ -1463,11 +1463,11 @@ npm install pg --save
|
||||
|
||||
Please follow these steps the **deploy a Strapi app with MongoDB on Heroku**.
|
||||
|
||||
You must have completed the [steps to use Strapi with MongoDB Atlas](/3.0.0-beta.x/guides/databases.html#install-on-atlas-mongodb-atlas) - through **4. Retrieve database credentials**.
|
||||
You must have completed the [steps to use Strapi with MongoDB Atlas](../guides/databases.md#install-on-atlas-mongodb-atlas) - through **4. Retrieve database credentials**.
|
||||
|
||||
#### 1. Set environment variables
|
||||
|
||||
When you [set-up your MongoDB Atlas database](/3.0.0-beta.x/guides/databases.html#install-on-atlas-mongodb-atlas) you noted a connection string. Similar to this:
|
||||
When you [set-up your MongoDB Atlas database](../guides/databases.md#install-on-atlas-mongodb-atlas) you noted a connection string. Similar to this:
|
||||
|
||||
```bash
|
||||
mongodb://paulbocuse:<password>@strapidatabase-shard-00-00-fxxx6c.mongodb.net:27017,strapidatabase-shard-00-01-fxxxc.mongodb.net:27017,strapidatabase-shard-00-02-fxxxc.mongodb.net:27017/test?ssl=true&replicaSet=strapidatabase-shard-0&authSource=admin&retryWrites=true&w=majority
|
||||
@ -1538,14 +1538,12 @@ heroku open
|
||||
|
||||
If you see the Strapi Welcome page, you have correctly set-up, configured and deployed your Strapi project on Heroku. You will now need to set-up your `admin user` as the production database is brand-new (and empty).
|
||||
|
||||
You can now continue with the [Tutorial - Creating an Admin User](/3.0.0-beta.x/getting-started/quick-start-tutorial.html#_3-create-an-admin-user), if you have any questions on how to proceed.
|
||||
You can now continue with the [Tutorial - Creating an Admin User](../getting-started/quick-start-tutorial.md#_3-create-an-admin-user), if you have any questions on how to proceed.
|
||||
|
||||
::: warning
|
||||
For security reasons, the Content Type Builder plugin is disabled in production. To update content structure, please make your changes locally and deploy again.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
### Project updates
|
||||
|
||||
When Strapi is deployed to Heroku, Heroku sets the environment variable to `NODE_ENV=production`. In `production mode` Strapi disables the content-type builder (for security reasons). Additionally, if you wanted to change the default production mode in Heroku, it wouldn't work as the file system is temporary. Strapi writes files to the server when you update the content-types and these updates would disappear when Heroku restarts the server.
|
||||
@ -1562,3 +1560,9 @@ git commit -am "Changes to my-project noted"
|
||||
git push heroku master
|
||||
heroku open
|
||||
```
|
||||
|
||||
### File Uploads
|
||||
|
||||
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](../plugins/upload.md#install-providers) 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).
|
||||
|
||||
89
docs/3.0.0-beta.x/guides/error-catching.md
Normal file
89
docs/3.0.0-beta.x/guides/error-catching.md
Normal file
@ -0,0 +1,89 @@
|
||||
# Error catching
|
||||
|
||||
In this guide we will see how you can catch errors and send them to the Application Monitoring / Error Tracking Software you want.
|
||||
|
||||
::: note
|
||||
In this example we will use [Sentry](https://sentry.io).
|
||||
:::
|
||||
|
||||
## Create a middleware
|
||||
|
||||
A [middleware](../concepts/middlewares.md) will be used in order to catch the errors which will then be sent to Sentry.
|
||||
|
||||
- Create a `./middlewares/sentry/index.js` file.
|
||||
|
||||
**Path —** `./middlewares/sentry/index.js`
|
||||
|
||||
```js
|
||||
module.exports = strapi => {
|
||||
return {
|
||||
initialize() {
|
||||
strapi.app.use(async (ctx, next) => {
|
||||
await next();
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
## Handle errors
|
||||
|
||||
Here is the [Node.js client documentation](https://docs.sentry.io/platforms/node/)
|
||||
|
||||
- Now add the logic that will catch errors.
|
||||
|
||||
**Path —** `./middlewares/sentry/index.js`
|
||||
|
||||
```js
|
||||
const Sentry = require('@sentry/node');
|
||||
Sentry.init({ dsn: 'https://<key>@sentry.io/<project>' });
|
||||
|
||||
module.exports = strapi => {
|
||||
return {
|
||||
initialize() {
|
||||
strapi.app.use(async (ctx, next) => {
|
||||
try {
|
||||
await next();
|
||||
} catch (error) {
|
||||
Sentry.captureException(error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
::: warning
|
||||
It's important to call `throw(error);` to avoid stopping the middleware stack. If you don't re-throw the error, it won't be handled by the Strapi's error formatter and the api will never respond to the client.
|
||||
:::
|
||||
|
||||
## Configure the middleware
|
||||
|
||||
Make sure your middleware is added at the end of the middleware stack.
|
||||
|
||||
**Path —** `./config/middleware.json`
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"after": [
|
||||
"parser",
|
||||
"router",
|
||||
"sentry"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And finally you have to enable the middleware.
|
||||
|
||||
**Path —** `./config/environments/**/middleware.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"sentry": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
103
docs/3.0.0-beta.x/guides/jwt-validation.md
Normal file
103
docs/3.0.0-beta.x/guides/jwt-validation.md
Normal file
@ -0,0 +1,103 @@
|
||||
# JWT validation
|
||||
|
||||
In this guide we will see how to validate a `JWT` (JSON Web Token) with a third party service.
|
||||
|
||||
When you sign in with the authentication route `POST /auth/local`, Strapi generates a `JWT` which lets your users request your API as an authenticated one.
|
||||
|
||||
```json
|
||||
{
|
||||
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNTcxODIyMDAzLCJleHAiOjE1NzQ0MTQwMDN9.T5XQGSDZ6TjgM5NYaVDbYJt84qHZTrtBqWu1Q3ShINw",
|
||||
"user": {
|
||||
"email": "admin@strapi.io",
|
||||
"id": 1,
|
||||
"username": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These users are managed in the application's database and can be managed via the admin dashboard.
|
||||
|
||||
We can now imagine you have a `JWT` that comes from [Auth0](https://auth0.com) and you want to make sure the `JWT` is correct before allowing the user to use the Strapi API endpoints.
|
||||
|
||||
## Customize the JWT validation function
|
||||
|
||||
We have to use the [customization concept](../concepts/customization.md) to update the function that validates the `JWT`. This feature is powered by the **Users & Permissions** plugin.
|
||||
|
||||
Here is the file we will have to customize: [permission.js](https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/config/policies/permissions.js)
|
||||
|
||||
- We have to create a file that follows this path `./extensions/users-permissions/config/policies/permissions.js`.
|
||||
- You will have to add in this new file, the same content of the original one.
|
||||
|
||||
Now we are ready to create our custom validation code.
|
||||
|
||||
## Write our own logic
|
||||
|
||||
First we have to define where write our code.
|
||||
|
||||
```js
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
let role;
|
||||
|
||||
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
||||
try {
|
||||
const { id, isAdmin = false } = await strapi.plugins[
|
||||
'users-permissions'
|
||||
].services.jwt.getToken(ctx);
|
||||
|
||||
...
|
||||
|
||||
} catch (err) {
|
||||
// It will be there!
|
||||
|
||||
return handleErrors(ctx, err, 'unauthorized');
|
||||
}
|
||||
```
|
||||
|
||||
The `jwt.getToken` will throw an error if the token doesn't come from Strapi. So if it's not a Strapi `JWT` token, let's test if it's an Auth0 one.
|
||||
|
||||
We will have to write our validation code before throwing an error.
|
||||
|
||||
By using the [Auth0 get user profile](https://auth0.com/docs/api/authentication?http#get-user-info) documentation, you will verify a valid user matches with the current `JWT`
|
||||
|
||||
```js
|
||||
const _ = require('lodash');
|
||||
const axios = require('axios');
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
let role;
|
||||
|
||||
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
||||
try {
|
||||
const { id, isAdmin = false } = await strapi.plugins[
|
||||
'users-permissions'
|
||||
].services.jwt.getToken(ctx);
|
||||
|
||||
...
|
||||
|
||||
} catch (err) {
|
||||
try {
|
||||
const data = await axios({
|
||||
method: 'post',
|
||||
url: 'http://YOUR_DOMAIN/userinfo',
|
||||
headers: {
|
||||
Authorization: ctx.request.header.authorization
|
||||
}
|
||||
});
|
||||
|
||||
// if you want do more validation test
|
||||
// feel free to add your code here.
|
||||
|
||||
return await next();
|
||||
} catch (error) {
|
||||
return handleErrors(ctx, new Error('Invalid token: Token did not match with Strapi and Auth0'), 'unauthorized');
|
||||
}
|
||||
|
||||
return handleErrors(ctx, err, 'unauthorized');
|
||||
}
|
||||
```
|
||||
|
||||
::: warning
|
||||
In the code example we use `axios` you will have to install the dependency to make it work. You can choose another library if you prefer.
|
||||
:::
|
||||
107
docs/3.0.0-beta.x/guides/slug.md
Normal file
107
docs/3.0.0-beta.x/guides/slug.md
Normal file
@ -0,0 +1,107 @@
|
||||
# Create a slug system
|
||||
|
||||
This guide will explain how to create a slug system for a Post, Article or any Content Type you want.
|
||||
|
||||
## Create attributes
|
||||
|
||||
To start building your slug system you need a `string` field as a **base** for your slug, in this example we will use `title`.
|
||||
|
||||
You will also need another `string` field that contains the slugified value of your `title`, in this case we will use `slug`.
|
||||
|
||||

|
||||
|
||||
## Configure the layout for the content editor
|
||||
|
||||
Let's configure the layout of the **edit page** to make it more user friendly for the content editor.
|
||||
|
||||
- Click on the **Content Manager** link in the left menu.
|
||||
- Then on the `Article` Content Type.
|
||||
- And finally on the **Edit View** tab.
|
||||
|
||||
Here we will be able to setup the `slug` field.
|
||||
|
||||
- Click on the `slug` field.
|
||||
- At the bottom of the page, edit the **placeholder** value to `Generated automatically based on the title`.
|
||||
- And click **OFF** for **Editable field** option.
|
||||
- Don't forget to save your updates.
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Edit View before" id="before"
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::: tab "Edit View after" id="after"
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::: tab "Edit View configuration" id="config"
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Auto create/update the `slug` attribute
|
||||
|
||||
For that you will have to install `slugify` node module in your application.
|
||||
|
||||
When it's done, you have to update the life cycle of the **Article** Content Type to auto complete the `slug` field.
|
||||
|
||||
**Path —** `./api/article/models/Article.js`
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Mongoose" id="mongoose"
|
||||
|
||||
```js
|
||||
const slugify = require('slugify');
|
||||
|
||||
module.exports = {
|
||||
beforeSave: async model => {
|
||||
if (model.title) {
|
||||
model.slug = slugify(model.title);
|
||||
}
|
||||
},
|
||||
beforeUpdate: async model => {
|
||||
if (model.getUpdate().title) {
|
||||
model.update({
|
||||
slug: slugify(model.getUpdate().title),
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Bookshelf" id="bookshelf"
|
||||
|
||||
```js
|
||||
const slugify = require('slugify');
|
||||
|
||||
module.exports = {
|
||||
beforeSave: async (model, attrs, options) => {
|
||||
if (options.method === 'insert' && attrs.title) {
|
||||
model.set('slug', slugify(attrs.title));
|
||||
} else if (options.method === 'update' && attrs.title) {
|
||||
attrs.slug = slugify(attrs.title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Fetch article by `slug`
|
||||
|
||||
Then you will have to be able to fetch your **Articles** by this slug.
|
||||
|
||||
You will be able to find your articles by slug with this request `GET /articles?slug=my-article-slug`
|
||||
```
|
||||
97
docs/3.0.0-beta.x/guides/update-version.md
Normal file
97
docs/3.0.0-beta.x/guides/update-version.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Update Strapi version
|
||||
|
||||
How to upgrade your application to the latest version of Strapi.
|
||||
|
||||
## Upgrading your dependencies
|
||||
|
||||
Start by upgrading all your strapi package version.
|
||||
|
||||
For example moving from `3.0.0-beta.16` to `3.0.0-beta.17`
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Before - 3.0.0-beta.16" id="3.0.0-beta.16"
|
||||
|
||||
```json
|
||||
{
|
||||
//...
|
||||
"dependencies": {
|
||||
"strapi": "3.0.0-beta.16",
|
||||
"strapi-admin": "3.0.0-beta.16",
|
||||
"strapi-hook-bookshelf": "3.0.0-beta.16",
|
||||
"strapi-hook-knex": "3.0.0-beta.16",
|
||||
"strapi-plugin-content-manager": "3.0.0-beta.16",
|
||||
"strapi-plugin-content-type-builder": "3.0.0-beta.16",
|
||||
"strapi-plugin-email": "3.0.0-beta.16",
|
||||
"strapi-plugin-graphql": "3.0.0-beta.16",
|
||||
"strapi-plugin-settings-manager": "3.0.0-beta.16",
|
||||
"strapi-plugin-upload": "3.0.0-beta.16",
|
||||
"strapi-plugin-users-permissions": "3.0.0-beta.16",
|
||||
"strapi-utils": "3.0.0-beta.16"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: tab "After - 3.0.0-beta.17" id="3.0.0-beta.17"
|
||||
|
||||
```json
|
||||
{
|
||||
//...
|
||||
"dependencies": {
|
||||
"strapi": "3.0.0-beta.17",
|
||||
"strapi-admin": "3.0.0-beta.17",
|
||||
"strapi-hook-bookshelf": "3.0.0-beta.17",
|
||||
"strapi-hook-knex": "3.0.0-beta.17",
|
||||
"strapi-plugin-content-manager": "3.0.0-beta.17",
|
||||
"strapi-plugin-content-type-builder": "3.0.0-beta.17",
|
||||
"strapi-plugin-email": "3.0.0-beta.17",
|
||||
"strapi-plugin-graphql": "3.0.0-beta.17",
|
||||
"strapi-plugin-settings-manager": "3.0.0-beta.17",
|
||||
"strapi-plugin-upload": "3.0.0-beta.17",
|
||||
"strapi-plugin-users-permissions": "3.0.0-beta.17",
|
||||
"strapi-utils": "3.0.0-beta.17"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
Then run either `yarn install` or `npm install` to install the specified version.
|
||||
|
||||
::: note
|
||||
If the operation doesn't work, you should probably remove your `yarn.lock` or `package-lock.json`. And if it still not work let's run the hard mode `rm -Rf node_modules`
|
||||
:::
|
||||
|
||||
## Building your administration panel
|
||||
|
||||
New release can introduces changes to the administration panel that require a rebuild.
|
||||
|
||||
Start by deleting your current build:
|
||||
|
||||
```bash
|
||||
rm -rf build
|
||||
```
|
||||
|
||||
Build the administration panel:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
# or
|
||||
npm run build
|
||||
```
|
||||
|
||||
::: note
|
||||
If the operation doesn't work, you should probably remove the `.cache` folder too.
|
||||
:::
|
||||
|
||||
## Migration guides
|
||||
|
||||
Sometimes Strapi introduces changes that need more than just the previous updates.
|
||||
|
||||
That is the reason of the [Migration Guide](../migration-guide/README.md) page.
|
||||
|
||||
Just make sure when you update your version that a migration guide exist or not.
|
||||
@ -196,7 +196,7 @@ You can leave all your files in `./config` unchanged but remove the `server.auto
|
||||
|
||||
One of our main objectives for the `beta` is to make it easier and quicker to upgrade to more recent versions of Strapi. This is why moving forward, plugins will be located in the `node_modules` folder.
|
||||
|
||||
[Read more](https://strapi.io/documentation/3.0.0-beta.x/concepts/concepts.html#files-structure)
|
||||
[Read more](../concepts/file-structure.md)
|
||||
|
||||
Let's start by creating a new folder called `./extensions`. This folder needs to exist even if it's empty. You may use a `.gitkeep` file to ensure the folder isn't deleted from the repository (if it's empty) when cloning. [More details](https://davidwalsh.name/git-empty-directory).
|
||||
|
||||
@ -495,7 +495,7 @@ The only difference is that the admin of a local plugin is ignored for the momen
|
||||
In the `beta`, we are introducing the `Core API`, which is replacing the templates that were generated before.
|
||||
|
||||
Now when you create a new model your `controller` and `service` will be empty modules and will be used to override the default behaviors.
|
||||
Read more about [controllers](https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html) or [services](https://strapi.io/documentation/3.0.0-beta.x/guides/services.html)
|
||||
Read more about [controllers](../concepts/controllers.md) or [services](../concepts/services.md)
|
||||
|
||||
To migrate, you will only have to delete the methods you haven't modified or created from your `controllers` and `services`
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ To make sure a Wysiwyg field stays the same when deploying, we introduced the `r
|
||||
|
||||
### Custom controllers and services
|
||||
|
||||
If you are using [core services](../guides/services.md), you previously needed to call `result.toJSON()` or `result.toObject()` to get a plain javascript object. This is not the case anymore, you will now receive a simple object directly.
|
||||
If you are using [core services](../concepts/services.md), you previously needed to call `result.toJSON()` or `result.toObject()` to get a plain javascript object. This is not the case anymore, you will now receive a simple object directly.
|
||||
|
||||
**Before**:
|
||||
|
||||
@ -113,9 +113,9 @@ module.exports = {
|
||||
};
|
||||
```
|
||||
|
||||
The same modification was made to `strapi.query()`. Read more about **Queries** [here](../guides/queries.md).
|
||||
The same modification was made to `strapi.query()`. Read more about **Queries** [here](../concepts/queries.md).
|
||||
|
||||
Keep in mind that if you are running custom ORM queries with Bookshelf or Mongoose you will still have to call `toJSON` or `toObject`. Check out this section about [custom queries](../guides/queries.html#api-reference).
|
||||
Keep in mind that if you are running custom ORM queries with Bookshelf or Mongoose you will still have to call `toJSON` or `toObject`. Check out this section about [custom queries](../concepts/queries.md#api-reference).
|
||||
|
||||
### Bootstrap function
|
||||
|
||||
@ -167,7 +167,7 @@ module.exports = () => {};
|
||||
|
||||
### Custom hooks
|
||||
|
||||
If you have custom [hooks](../advanced/hooks.md) in your project, the `initialize` function will not receive a callback anymore. You can either use an async function, return a promise or simply run a synchronous function.
|
||||
If you have custom [hooks](../concepts/hooks.md) in your project, the `initialize` function will not receive a callback anymore. You can either use an async function, return a promise or simply run a synchronous function.
|
||||
|
||||
**Before**
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ This section explains how the 'back-end part' of your plugin works.
|
||||
The plugin API routes are defined in the `./plugins/**/config/routes.json` file.
|
||||
|
||||
::: note
|
||||
Please refer to [router documentation](../guides/routing.md) for information.
|
||||
Please refer to [router documentation](../concepts/routing.md) for information.
|
||||
:::
|
||||
|
||||
**Route prefix**
|
||||
@ -38,7 +38,7 @@ Please refer to the [CLI documentation](../cli/CLI.md) for more information.
|
||||
|
||||
Controllers contain functions executed according to the requested route.
|
||||
|
||||
Please refer to the [Controllers documentation](../guides/controllers.md) for more information.
|
||||
Please refer to the [Controllers documentation](../concepts/controllers.md) for more information.
|
||||
|
||||
## Models
|
||||
|
||||
@ -61,7 +61,7 @@ module.exports = {
|
||||
|
||||
Also, the table/collection name won't be `users` because you already have a `User` model. That's why, the framework will automatically prefix the table/collection name for this model with the name of the plugin. Which means in our example, the table/collection name of the `User` model of our plugin `Users & Permissions` will be `users-permissions_users`. If you want to force the table/collection name of the plugin's model, you can add the `collectionName` attribute in your model.
|
||||
|
||||
Please refer to the [Models documentation](../guides/models.md) for more information.
|
||||
Please refer to the [Models documentation](../concepts/models.md) for more information.
|
||||
|
||||
## Policies
|
||||
|
||||
@ -103,7 +103,7 @@ A plugin can have its own policies, such as adding security rules. For instance,
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to the [Policies documentation](../guides/policies.md) for more information.
|
||||
Please refer to the [Policies documentation](../concepts/policies.md) for more information.
|
||||
|
||||
## ORM queries
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
This feature is currently not available (coming soon).
|
||||
:::
|
||||
|
||||
<!--
|
||||
<!--
|
||||
|
||||
## Admin panel
|
||||
|
||||
@ -313,5 +313,5 @@ const Foo = props => (
|
||||
export default Foo;
|
||||
```
|
||||
|
||||
See [the documentation](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) for more extensive usage.
|
||||
See [the documentation](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) for more extensive usage.
|
||||
-->
|
||||
|
||||
@ -88,3 +88,26 @@ In the `send` function you will have access to:
|
||||
|
||||
- `config` that contain configuration you setup in your admin panel
|
||||
- `options` that contain option your send when you called the `send` function from the email plugin service
|
||||
|
||||
To use it you will have to publish it on **npm**.
|
||||
|
||||
### Create a local provider
|
||||
|
||||
If you want to create your own provider without publishing it on **npm** you can follow these steps:
|
||||
|
||||
- Create a `providers` folder in your application.
|
||||
- Create your provider as explained in the documentation eg. `./providers/strapi-provider-email-[...]/...`
|
||||
- Then update your `package.json` to link your `strapi-provider-email-[...]` dependency to the [local path](https://docs.npmjs.com/files/package.json#local-paths) of your new provider.
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"dependencies": {
|
||||
...
|
||||
"strapi-provider-email-[...]": "file:providers/strapi-provider-email-[...]",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Finally, run `yarn install` or `npm install` to install your new custom provider.
|
||||
|
||||
@ -293,3 +293,26 @@ Then, visit [http://localhost:1337/admin/plugins/upload/configurations/developme
|
||||
## Create providers
|
||||
|
||||
If you want to create your own, make sure the name starts with `strapi-provider-upload-` (duplicating an existing one will be easier to create), modify the `auth` config object and customize the `upload` and `delete` functions.
|
||||
|
||||
To use it you will have to publish it on **npm**.
|
||||
|
||||
### Create a local provider
|
||||
|
||||
If you want to create your own provider without publishing it on **npm** you can follow these steps:
|
||||
|
||||
- Create a `providers` folder in your application.
|
||||
- Create your provider as explained in the documentation eg. `./providers/strapi-provider-upload-[...]/...`
|
||||
- Then update your `package.json` to link your `strapi-provider-upload-[...]` dependency to the [local path](https://docs.npmjs.com/files/package.json#local-paths) of your new provider.
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"dependencies": {
|
||||
...
|
||||
"strapi-provider-upload-[...]": "file:providers/strapi-provider-upload-[...]",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Finally, run `yarn install` or `npm install` to install your new custom provider.
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
"Analytics": "Analityka",
|
||||
"Content Manager": "Treści",
|
||||
"Content Type Builder": "Modele",
|
||||
"Documentation": "Dokumentacja",
|
||||
"Email": "Email",
|
||||
"Files Upload": "Upload plików",
|
||||
"HomePage.notification.newsLetter.success": "Pomyślnie zapisano do biuletynu",
|
||||
@ -52,6 +53,8 @@
|
||||
"app.components.InputFileDetails.originalName": "Oryginalna nazwa:",
|
||||
"app.components.InputFileDetails.remove": "Usuń ten plik",
|
||||
"app.components.InputFileDetails.size": "Rozmiar:",
|
||||
"app.components.InstallPluginPage.Download.title": "Pobieranie...",
|
||||
"app.components.InstallPluginPage.Download.description": "Pobranie i instalacja wtyczki może zająć kilka sekund.",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "Wyszukaj wtyczkę... (np: authentication)",
|
||||
"app.components.InstallPluginPage.description": "Rozszerz swoją aplikację bez wysiłku",
|
||||
@ -65,6 +68,8 @@
|
||||
"app.components.InstallPluginPopup.navLink.faq": "faq",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "Zrzuty ekranu",
|
||||
"app.components.InstallPluginPopup.noDescription": "Brak dostępnego opisu",
|
||||
"app.components.LeftMenuFooter.documentation": "Dokumentacja",
|
||||
"app.components.LeftMenuFooter.help": "Pomoc",
|
||||
"app.components.LeftMenuFooter.poweredBy": "Dumnie wspierane przez ",
|
||||
"app.components.LeftMenuLinkContainer.configuration": "Konfiguracje",
|
||||
"app.components.LeftMenuLinkContainer.general": "Ogólne",
|
||||
@ -75,18 +80,26 @@
|
||||
"app.components.ListPluginsPage.description": "Lista zainstalowanych wtyczek w projekcie.",
|
||||
"app.components.ListPluginsPage.helmet.title": "Lista wtyczek",
|
||||
"app.components.ListPluginsPage.title": "Wtyczki",
|
||||
"app.components.Logout.admin": "Zarządzaj administratorami",
|
||||
"app.components.Logout.profile": "Profil",
|
||||
"app.components.Logout.logout": "Wyloguj",
|
||||
"app.components.NotFoundPage.back": "Powrót do strony głównej",
|
||||
"app.components.NotFoundPage.description": "Nie znaleziono",
|
||||
"app.components.Official": "Oficjalna",
|
||||
"app.components.Onboarding.label.completed": "% ukończono",
|
||||
"app.components.Onboarding.title": "Filmy 'Jak Zacząć'",
|
||||
"app.components.PluginCard.Button.label.download": "Pobierz",
|
||||
"app.components.PluginCard.Button.label.install": "Zainstalowana",
|
||||
"app.components.PluginCard.Button.label.support": "Wesprzyj nas",
|
||||
"app.components.PluginCard.compatible": "Kompatybilna z twoją aplikacją",
|
||||
"app.components.PluginCard.compatibleCommunity": "Kompatybilna ze społecznością",
|
||||
"app.components.PluginCard.more-details": "Więcej szczegółów",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.autoReload.needed": "Funkcja autoReload musi być włączona. Uruchom aplikację używając polecenia `yarn develop`.",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.environment": "Z powodów bezpieczeństwa wtyczka może być pobrana tylko w środowisku developerskim.",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.confirm": "Zrozumiałem!",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.title": "Pobieranie jest niemożliwe",
|
||||
"app.components.PluginCard.price.free": "Darmowa",
|
||||
"app.components.PluginCard.settings": "Ustawienia",
|
||||
"app.components.listPlugins.button": "Dodaj nową wtyczkę",
|
||||
"app.components.listPlugins.title.none": "Żadna wtyczka nie jest zainstalowana",
|
||||
"app.components.listPlugins.title.plural": "{number} wtyczek jest zainstalowanych",
|
||||
@ -95,6 +108,7 @@
|
||||
"app.utils.SelectOption.defaultMessage": " ",
|
||||
"app.utils.defaultMessage": " ",
|
||||
"app.utils.placeholder.defaultMessage": " ",
|
||||
"components.AutoReloadBlocker.description": "Uruchom Strapi z jedną z poniższych komend:",
|
||||
"components.AutoReloadBlocker.header": "Do tej wtyczki wymagana jest funkcja przeładowania.",
|
||||
"components.ErrorBoundary.title": "Coś poszło nie tak...",
|
||||
"components.Input.error.attribute.key.taken": "Ta wartość już istnieje",
|
||||
@ -111,9 +125,12 @@
|
||||
"components.Input.error.validation.minSupMax": "Nie może być większa",
|
||||
"components.Input.error.validation.regex": "Wartość nie jest zgodna z wymaganym wzorcem.",
|
||||
"components.Input.error.validation.required": "Wpisanie wartości dla tego atrybutu jest wymagane.",
|
||||
"components.InputSelect.option.placeholder": "Wybierz tutaj",
|
||||
"components.ListRow.empty": "Nie ma żadnych danych do wyświetlenia.",
|
||||
"components.OverlayBlocker.description": "Używasz funkcjonalności która wymaga ponownego uruchomienia serwera. Poczekaj proszę aż aplikacja znów będzie aktywna.",
|
||||
"components.OverlayBlocker.description.serverError": "Serwer powinien zostać zrestartowany, sprawdź swoje logi w terminalu.",
|
||||
"components.OverlayBlocker.title": "Oczekiwanie na ponowne uruchomienie...",
|
||||
"components.OverlayBlocker.title.serverError": "Ponowne uruchomienie trwa dłużej niż oczekiwano",
|
||||
"components.PageFooter.select": "elementów na stronę",
|
||||
"components.ProductionBlocker.description": "Ze względów bezpieczeństwa wtyczka jest wyłączona w innych środowiskach.",
|
||||
"components.ProductionBlocker.header": "Ta wtyczka jest dostępna tylko w wersji deweloperskiej.",
|
||||
@ -138,7 +155,18 @@
|
||||
"notification.error": "Wystąpił błąd",
|
||||
"notification.error.layout": "Nie można pobrać układu",
|
||||
"request.error.model.unknown": "Ten model nie istnieje",
|
||||
"app.utils.delete": "Usuń",
|
||||
"HomePage.helmet.title": "Strona Główna",
|
||||
"HomePage.welcome.congrats": "Gratulacje!",
|
||||
"HomePage.welcome.congrats.content": "Jesteś zalogowany jako pierwszy administrator. Aby odkryć zaawansowane funkcje oferowane przez Strapi,",
|
||||
"HomePage.welcome.congrats.content.bold": "zalecamy utworzenie pierwszego Modelu.",
|
||||
"HomePage.community": "Dołącz do społeczności",
|
||||
"HomePage.roadmap": "Zobacz harmonogram",
|
||||
"HomePage.greetings": "Cześć {name}!",
|
||||
|
||||
"Auth.advanced.allow_register": "",
|
||||
"Auth.privacy-policy-agreement.terms": "warunki",
|
||||
"Auth.privacy-policy-agreement.policy": "polityka prywatności",
|
||||
"Auth.form.button.forgot-password": "Wyślij e-mail",
|
||||
"Auth.form.button.forgot-password.success": "Wyślij ponownie",
|
||||
"Auth.form.button.login": "Zaloguj się",
|
||||
@ -164,7 +192,6 @@
|
||||
"Auth.form.forgot-password.email.label": "Email",
|
||||
"Auth.form.forgot-password.email.label.success": "E-mail wysłany z powodzeniem do",
|
||||
"Auth.form.forgot-password.email.placeholder": "jannowak@gmail.com",
|
||||
|
||||
"Auth.form.header.forgot-password": "strapi",
|
||||
"Auth.form.header.login": "strapi",
|
||||
"Auth.form.header.register": "Witaj!",
|
||||
@ -178,11 +205,15 @@
|
||||
"Auth.form.register.confirmPassword.label": "Potwierdzenie hasła",
|
||||
"Auth.form.register.email.label": "Email",
|
||||
"Auth.form.register.email.placeholder": "jannowak@gmail.com",
|
||||
"Auth.form.register.news.label": "Informuj mnie na bieżąco o nowych funkcjach i nadchodzących ulepszeniach (wybór oznacza akceptację {terms} i {policy}).",
|
||||
"Auth.form.register.password.label": "Hasło",
|
||||
"Auth.form.register.username.label": "Użytkownik",
|
||||
"Auth.form.register.username.placeholder": "Jan Nowak",
|
||||
"Auth.header.register.description": "Aby zakończyć konfigurację i zabezpieczyć swoją aplikację, utwórz pierwszego użytkownika (administratora root), wypełniając poniższe informacje.",
|
||||
"Auth.link.forgot-password": "Nie pamiętasz hasła?",
|
||||
"Auth.link.ready": "Zaczynamy?",
|
||||
"components.Input.error.password.noMatch": "Hasło nie pasuje"
|
||||
"app.containers.App.notification.error.init": "Wystąpił błąd podczas wykonywania żądania do API",
|
||||
"components.Input.error.password.noMatch": "Hasło nie pasuje",
|
||||
"form.button.done": "Gotowe",
|
||||
"notification.form.error.fields": "Formularz zawiera błędy"
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html#core-controllers)
|
||||
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers)
|
||||
* to customize this controller
|
||||
*/
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/services.html#core-services)
|
||||
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/services.html#core-services)
|
||||
* to customize this service
|
||||
*/
|
||||
|
||||
|
||||
@ -105,7 +105,26 @@ module.exports = async function createProject(
|
||||
|
||||
await captureStderr('didNotInstallProjectDependencies', error);
|
||||
|
||||
stopProcess('Stopping installation');
|
||||
console.log(chalk.black.bgWhite(' Keep trying! '));
|
||||
console.log();
|
||||
console.log(
|
||||
chalk.bold(
|
||||
'Oh, it seems that you encountered errors while installing dependencies in your project.'
|
||||
)
|
||||
);
|
||||
console.log(`Don't give up, your project was created correctly.`);
|
||||
console.log(
|
||||
`Fix the issues mentionned in the installation errors and try to run the following command:`
|
||||
);
|
||||
console.log();
|
||||
console.log(
|
||||
`cd ${chalk.green(rootPath)} && ${chalk.cyan(
|
||||
scope.useYarn ? 'yarn' : 'npm'
|
||||
)} install`
|
||||
);
|
||||
console.log();
|
||||
|
||||
stopProcess();
|
||||
}
|
||||
|
||||
await trackUsage({ event: 'didCreateProject', scope });
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function stopProcess(message) {
|
||||
console.error(message);
|
||||
if (message) console.error(message);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/node": "^5.7.1",
|
||||
"chalk": "^2.4.2",
|
||||
"execa": "^1.0.0",
|
||||
"fs-extra": "^8.0.1",
|
||||
"inquirer": "^6.3.1",
|
||||
|
||||
@ -740,6 +740,8 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
options.withRelated = []
|
||||
.concat(createGroupsPopulate())
|
||||
.concat(createAssociationPopulate());
|
||||
} else if (_.isEmpty(options.withRelated)) {
|
||||
options.withRelated = createGroupsPopulate();
|
||||
} else {
|
||||
options.withRelated = formatPopulateOptions(options.withRelated);
|
||||
}
|
||||
|
||||
@ -128,11 +128,9 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const fn = preLifecycle[key];
|
||||
|
||||
if (_.isFunction(target[model.toLowerCase()][fn])) {
|
||||
schema.pre(key, function(next) {
|
||||
target[model.toLowerCase()]
|
||||
[fn](this)
|
||||
.then(next)
|
||||
.catch(err => strapi.log.error(err));
|
||||
schema.pre(key, function() {
|
||||
return target[model.toLowerCase()]
|
||||
[fn](this);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -157,7 +157,7 @@ export const mapDataKeysToFilesToUpload = (filesMap, data) => {
|
||||
const groupData = get(data, [key], []);
|
||||
const groupFiles = groupData.reduce((acc1, current, index) => {
|
||||
const files = isMultiple
|
||||
? getFileToUpload([key, index, targetKey])
|
||||
? getFilesToUpload([key, index, targetKey])
|
||||
: getFileToUpload([key, index, targetKey]);
|
||||
|
||||
if (!isEmpty(files)) {
|
||||
|
||||
@ -20,7 +20,7 @@ module.exports = async () => {
|
||||
strapi.plugins.email.config.providers = [];
|
||||
|
||||
const installedProviders = Object.keys(strapi.config.info.dependencies)
|
||||
.filter(d => d.startsWith('strapi-provider-email-'))
|
||||
.filter(d => d.includes('strapi-provider-email-'))
|
||||
.concat('strapi-provider-email-sendmail');
|
||||
|
||||
for (let installedProvider of _.uniq(installedProviders)) {
|
||||
|
||||
@ -20,7 +20,7 @@ module.exports = async () => {
|
||||
strapi.plugins.upload.config.providers = [];
|
||||
|
||||
const installedProviders = Object.keys(strapi.config.info.dependencies)
|
||||
.filter(d => d.startsWith('strapi-provider-upload-'))
|
||||
.filter(d => d.includes('strapi-provider-upload-'))
|
||||
.concat('strapi-provider-upload-local');
|
||||
|
||||
for (let installedProvider of _.uniq(installedProviders)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user