GraphQL Plugin
Usage
下載graphql套件到strapi project
yarn strapi install graphql
playground網址預設在/graphql
graphql playground http://localhost:1337/graphql
Config
set playgroundAlways: true at config/plugins.ts
# config/plugins.ts
export default {
//
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
playgroundAlways: false,
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
};
Shadow CRUD
Shadow CRUD會根據model自動生成(type definitions, queries, mutations and resolvers),在playground有docs可以參考
Customization
Strapi provides a programmatic API to customize GraphQL, which allows:
- disabling some operations for the Shadow CRUD
- using getters to return information about allowed operations
- registering and using an
extension
object to extend the existing schema (e.g. extend types or define custom resolvers, policies and middlewares)
Example
客製化的內容加在src/index.ts的register中才會生效 目前已知有兩種方法可以擴充graphql
- Nexus-based type definitions (官方好像叫推薦這個)
- GraphQL SDL
./src/index.ts
export default {
/**
* An asynchronous register function that runs before
* your application is initialized.
*
* This gives you an opportunity to extend code.
*/
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
// 關閉shadow crud某些api
extensionService.shadowCRUD('api::restaurant.restaurant').disable();
extensionService.shadowCRUD('api::category.category').disableQueries();
extensionService.shadowCRUD('api::address.address').disableMutations();
extensionService.shadowCRUD('api::document.document').field('locked').disable();
extensionService.shadowCRUD('api::like.like').disableActions(['create', 'update', 'delete']);
const extension = ({ nexus }) => ({
// Nexus (新增object、擴充object、新增query)
types: [
// 新增object book,含有field title
nexus.objectType(Creator),
// extend exist object type
nexus.extendType(extendProduct),
// 新增query
nexus.extendType(getproductsByCreatorId),
],
// qeury不驗證的話要在這裡把auth改成false
resolversConfig: {
'Query.address': {
auth: false,
},
},
});
// 加載設定
extensionService.use(extension);
},
};
Nexus-based type definitions
Object Type
// new object
const Creator = {
type: 'Creator',
name: 'Creator',
definition(t) {
t.int('id');
t.string('firstname');
t.string('lastname');
t.string('username');
}
}
Extend Object Type
//Extend exist object type
const extendProduct = {
type: 'Product',
definition(t) {
// we want to know who is the creator
t.field('createdBy', {
type: 'Creator',
async resolve(root, args, ctx) {
// when we use query, we can populate createdBy
const query = strapi.db.query('api::product.product');
const product = await query.findOne({
where: {
id: root.id,
},
populate: ['createdBy'],
});
return {
id: product.createdBy.id,
firstname: product.createdBy.firstname,
lastname: product.createdBy.lastname,
username: product.createdBy.username
};
},
})
}
}
Query
//New query
const getproductsByCreatorId = {
type: 'Query',
definition(t) {
// productsByCreatorId definition
t.field('getProductsByCreatorId', {
// Response type
type: list('Product'),
// Argument
args: { id: idArg() },
// Resolver definition: Filte products by createdById
async resolve(root, args, ctx) {
const query = strapi.db.query('api::product.product');
const product = await query.findMany({
populate: ['createdBy'],
where: {
$and: [
{
createdBy: {
id: args.id
}
},
{
// caution: this will return only published data but draft!
$not: {
publishedAt: null
}
}
]
}
});
return product;
}
});
}
}