second version of GraphQL CMSIn my previous article, “
Well, Russian .
Original ”, I told you how to cut your code and time in half if you use GraphQL with Mongoose.
')
Today we will also talk about GraphQL technology and if you work with it, this article will be able to help you save a decent amount of development time. The original article in English can be found on the
link .
"Link to the module itself:
graphql-auto-generating-cms .
As you may have guessed, this module uses your ready-made GraphQL scheme to generate a full-featured CMS. You will not need to spend a lot of time developing an administrative panel, and you will be able to concentrate more on the business processes of your project and on its architecture.
An important advantage of this module is that it does not require any changes from you in your ready-made code or project architecture, which makes its integration as simple as possible even on ready-made projects.
You have two ways to use this module.
- The first is as fast as possible and is suitable for a new project. All you need is a GraphQL scheme and a simple pattern following the name of GraphQL methods and types.
- And the second method that does not require you to follow any patterns, and can be easily integrated into an already finished project. All you need to do is provide the configuration object along with the GraphQL schema.
At the moment, the module does not support GraphQLList, nested objects and file downloads, their support will be implemented in future versions. At the moment, you can easily get around these limitations using self-written functions and components that you can add to the CMS, we will look at how to do this in this article.
Based on all the above, let's divide the current article into several points:
- General rules
- Preparation for work
- The first method of use, with a pattern
- The second method of use, with a configuration object
- Addition of CMS with its components and functions.
General rules
The module will use the graphQL type as an entity that will be available in the sidebar of the CMS.
To exclude types that are used only as nested objects. Accordingly, only those types that have one “Query” method and at least one “Mutation” method will be taken as an entity.
Each type can have only one “Query” [find], which will be used to get an array of objects, or to get one object using the “id” or “_id” argument depending on which type of database you use. A type can also have one or more of the following “Mutation” methods [create, update, remove].
Query method must support the following arguments:
{ offset: number, limit: number, id: number || _id: string
The arguments “offset” and “limit” will be used for pagination and to get data from the server in batches, and not to say to get 50t at once. objects because of what your application just hangs.
On the server side, this might look like this:
let {offset, limit} = args; return new Promise((resolve, reject) => { Ingredients.find(query).skip(offset).limit(limit).exec((err, res) => err ? reject(err) : resolve(res)); });
And the “id” argument will be used to get one instance. If you use a method like “findOne” to return one element using “id”, make sure that you return it inside the array, since the graphQL will expect exactly the array, even if it is one element.
Preparation for work
Installation:
npm i -S graphql-auto-generating-cms
On the server side, we need to run the middleware through which we will process the GrpahQL scheme, in the example below we will use the URL "/ graphql_cms_endpoint" as the end point:
… import express from 'express'; import graphqlCMS from 'graphql-auto-generating-cms/lib/middleware'; import schema from '../schema'; const printSchema = require('graphql/utilities/schemaPrinter').printSchema; let app = express(); let config = {schema: printSchema(schema)} app.use('/graphql_cms_endpoint', graphqlCMS(config)); … app.listen(port)
After that we can use our React component on the client side. You can download it from a separate link or as a normal React component.
Inside the router:
... import GraphqlCMS from 'graphql-auto-generating-cms'; export default ( <Router onUpdate={() => window.scrollTo(0, 0)} history={browserHistory}> <Route path='/graphql-cms' endpoint='/graphql_cms_endpoint' graphql='/graphql' components={GraphqlCMS} /> … </Router>
Or as a component:
<GraphqlCMS endpoint='/graphql_cms_endpoint' graphql='/graphql' />
In the endpoint property we specify the same URL that we used on the server side.
In the property "graphql" link to your GraphQL API.
The second option is well suited if you say you want to supplement CMS with authorization functions and so on. You simply paste it as a child component into the Layout with a navigation bar, authorization system and so on.
The first method of use, with a pattern
To use the quick way to generate your CMS, without additional configurations, you need to follow the following simple patterns in the GrpahQL name “Query” and “Mutation” methods.
[graphql Type name]_[action]
example:
productType_find productType_create productType_update productType_remove
Sorting menu items and input fields in the CMS will be identical to the order of the properties in the object.
For example, if in our scheme the following order of types:
{ productType: {}, userType: {}, categoryType: {}, ... }
Then in the sidebar, the menu items will have the same order:
productType userType categoryType
The same applies to the order of type fields, their order will be taken as the basis for constructing a UI for a page viewing one instance of an element, or for adding a new element:
let productType = new GraphQLObjectType({ name: 'productType', fields: { _id: {type: GraphQLString}, title: {type: GraphQLString}, shortDescription: {type: GraphQLString}, price: {type: GraphQLString}, isPublished: {type: GraphQLBoolean}, createdAt: {type: GraphQLString}, updatedAt: {type: GraphQLString}, bulletPoints: {type: GraphQLString}, scienceShort: {type: GraphQLString}, scienceFull: {type: GraphQLString}, } });
Accordingly, if you want to change the order of the items in the sidebar, or change the order of the input fields, you just have to swap the properties in the GrpahQL scheme.
The second method of use, with a configuration object
The advantages of the second method:
- You do not need to make any changes to the current code and / or architecture.
- It is not necessary to use the naming pattern.
- You can disable any “Mutation” methods for each type.
- You can change the sorting of the fields and the side menu, without changing the scheme, simply by changing the order of the rules in the "rules" property
- You can specify an arbitrary name for the side menu items and all fields. Initially, the names of graphQL types will be used as the names of the menu items, and the names of the type properties will be used as the names of the fields.
- You can disable editing any fields.
- You can freely specify which properties will be used inside the table with the list of documents. Initially, the “id” or “_id” type property will be used for the [# / ID] field, and the second GraphQL type property will be used as [title]
- You can change which field to use for a specific property, for example, use input or textarea, change the input type, say to “date” and so on.
Let's take a look at how it works, all you need to do is expand the configuration object on the server side. All fields except the “schema” are optional.
let config = {schema: printSchema(schema)} app.use('/graphql_cms_endpoint', graphqlCMS(config));
let config = { schema: printSchema(schema),
Addition of CMS with its components and functions.
You can also add CMS menu items with your React components with additional features, say for some custom solutions, such as statistics or a general dashboard.
All you need to do is simply add another property 'newMenuItems' on the client side, to the component:
<Route path='/graphql-cms' endpoint='/graphql_cms_endpoint' graphql='/graphql' newMenuItems={customPages} components={GraphqlCMS} />
Through which we send an array with additional menu items and components, the structure of the objects in the array is below:
let customPages = [ { label: 'Custom Page', secret: 'uniqeForEachComponentSecret', view: { secret: 'sameUniqeComponentSecret', component: CustomDashboard
The code above will look like this:

Thank you for your attention, I hope this module will be useful to you.
I am currently working on a new version of the module if you want to keep abreast of the “star” project on GitHub.
What will be included in the new version:
- support of nested objects of any depth for graphQL types
- graphQLList support
- Routing
- File upload support
With the next update, the auto-generated CMS will satisfy 90% of your requirements for any CMS just using your GraphQL scheme!"
Example code»
GithubSeveral screenshots of the working version:




