mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 03:44:29 +03:00
b83232bf0c
refs #10461 - do not break the existing webhooks by keeping both payload formats for subscribers events - refactored webhooks service to run models through target API version - added new events described in the target issue reference - this refactoring & enhancement is undocumented, further breaking changes will happen because we are actively working on: https://github.com/TryGhost/Ghost/issues/10438 |
||
---|---|---|
.. | ||
shared | ||
v0.1 | ||
v2 | ||
index.js | ||
README.md |
API Versioning
Ghost supports multiple API versions. Each version lives in a separate folder e.g. api/v0.1, api/v2. Next to the API folders there is a shared folder, which the API versions use.
NOTE: v0.1 is deprecated and we won't touch this folder at all. The v0.1 folder contains the API layer which we have used since Ghost was born.
Stages
Each request goes through the following stages:
- validation
- input serialisation
- permissions
- query
- output serialisation
The framework we are building pipes a request through these stages depending on the API controller implementation.
Frame
Is a class, which holds all the information for API processing. We pass this instance per reference. The target function can modify the original instance. No need to return the class instance.
Structure
{
original: Object,
options: Object,
data: Object,
user: Object,
file: Object,
files: Array
}
Example
{
original: {
include: 'tags'
},
options: {
withRelated: ['tags']
},
data: {
posts: []
}
}
API Controller
A controller is no longer just a function, it's a set of configurations.
Structure
edit: function || object
edit: {
headers: object,
options: Array,
data: Array,
validation: object | function,
permissions: boolean | object | function,
query: function
}
Examples
edit: {
headers: {
cacheInvalidate: true
},
options: ['include']
validation: {
options: {
include: {
required: true,
values: ['tags']
}
}
},
permissions: true,
query(frame) {
return models.Post.edit(frame.data, frame.options);
}
}
read: {
data: ['slug']
validation: {
data: {
slug: {
values: ['eins']
}
}
},
permissions: true,
query(frame) {
return models.Post.findOne(frame.data, frame.options);
}
}
edit: {
validation() {
// custom validation, skip framework
},
permissions: {
unsafeAttrs: ['author']
},
query(frame) {
return models.Post.edit(frame.data, frame.options);
}
}