Coko Server
@coko/server
is meant to cover all the server-side common functionality between
our apps that is not a devDependency
(eg. testing libraries).
If you have ideas or bugs to report, use its gitlab repo.
Get started
# Make sure you remove all these from your dependencies, as this package provides them all
yarn remove \
pubsweet \
pubsweet-server \
@pubsweet/base-model \
@pubsweet/component-send-email \
@pubsweet/db-manager \
@pubsweet/logger \
uuid
yarn add @coko/server
Add a central server file to your app:
// server/app.js
// This is the express app your app will use
const { app } = require("@coko/server");
// You can modify the app or ensure other things are imported here
module.exports = app;
If you place this file in server/app.js, starting the server should work automatically. If you wish to have a custom location for this file, you can declare that in your config.
// config/default.js
{
'pubsweet-server': {
// replace helpers/customApp.js with your file's location
app: path.resolve(__dirname, 'helpers', 'customApp.js'),
}
}
Usage guide
Authorization middleware
The server provides authorization checks through using graphql-shield. You can access all of shield's exports (eg. rule, and, or etc.) through @coko/server/authorization. The only exception is shield, which is used internally by the server. Besides shield's exports, two helpers, isAdmin and isAuthenticated are provided.
To get started, declare your permissions in any file you want:
// myPermissions.js
const { rule } = require("@coko/server/authorization");
const permissions = {
Query: {
myQuery: rule()(async (parent, args, ctx, info) => {
// my auth logic here
}),
// using provided helpers
anotherQuery: isAdmin,
yetAnotherQuery: isAuthenticated,
},
Mutation: {
myMutation: rule()(async (parent, args, ctx, info) => {
// my other auth logic here
}),
},
};
module.exports = permissions;
For the server to access your permissions, simply add them to the config:
// config/default.js
const permissions = require("../path/to/myPermissions.js");
{
permissions: permissions;
}
Please refer to shield's documentation for more details.
Email middleware
Email notifications get sent out as a side effect of a mutation in your schema.
Create a file wherever you like:
const myFunc = async (resolve, parent, args, ctx, info) => {
// do some stuff before the resolver
const result = await resolve(parent, args, ctx, info);
// do some stuff after the resolver
// send your email
return result;
};
module.exports = {
// myMutation needs to match a mutation name in your schema
myMutation: myFunc,
};
Now in your config:
// config/default.js
const emailService = require("path/to/your/email/file");
{
emailMiddleware: {
service: emailService;
}
}
This middleware uses graphql-middleware to provide its functionality, so make sure to read its documentation and understand its function signature. -->
Cron support
All you need for cron-based scheduled tasks to run is to provide the path to your cron jobs.
// config/default.js
{
'pubsweet-server': {
// replace server/services/cron with your folder's or file's location
cron: {
path: path.join(__dirname, '..', 'server', 'services', 'cron'),
},
}
}
A simple cronjob could look like this:
const { cron } = require("@coko/server");
// Log this every second
cron.schedule("* * * * * *", () => {
console.log("this is the simplest thing");
});
The library that enables this is node-cron. Be sure to check its documentation for further details.
Queue manager
We use pg-boss
to handle queues. This package exposes an instance of pg-boss, so you don't have
to initiate it yourself. In other words, there's no need to use the start
and stop
functions. These are handled.
The following SQL code needs to have run on your database, either via a database init script or as part of a migration:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
Use the queue manager as follows:
const { boss } = require("@coko/server");
await boss.publish("my-job", { and: "how" });
The above method is recommended, but if you already use pubsweet's connectToJobQueue
and want a low-overhead way to switch to @coko/server
, we also expose the same
function for backwards compatibility.
// Replace this
const { connectToJobQueue } = require("pubsweet-server");
// With this
const { connectToJobQueue } = require("@coko/server");
You can also disable the queue manager altogether with the following config option:
// config/default.js
module.exports = {
"pubsweet-server": {
useJobQueue: false,
},
};
Disable GraphQL
There are cases where you might not want a graphql server at all. eg. If you are building a sevice with a single REST api endpoint with coko server.
To disable graphql on the server, change the following value in your config:
// config/default.js
module.exports = {
"pubsweet-server": {
useGraphQLServer: false,
},
};
CORS support for the client
If you run your client on a different host/port than the server, you might run into issues where cross-origin requests are rejected. If that happens, make sure the following entries exist in your config. The server should take care of it once these are defined.
// replace values with the ones you are using
{
'pubsweet-client': {
protocol: 'http'
host: 'localhost',
port: 4000,
}
}
Other exports from included packages
startServer
Returns function to start pubsweet server. Useful for when you want to avoid using any cli wrapper (eg. for production docker images).
const { startServer } = require("@coko/server");
logger
Returns pubsweet's logger
const { logger } = require("@coko/server");
BaseModel
Returns pubsweet's base model
const { BaseModel } = require("@coko/server");
useTransaction
Helper that abstract's objection's transactions for you.
const { useTransaction } = require("@coko/server");
await useTransaction(async (trx) => {
// await MyModel.query(trx).insert({})
});
pubsubManager
Exposes pubsweet's pubsubManager for use with graphql subscriptions.
const { pubsubManager } = require("@coko/server");
sendEmail
Reads your mailer config and sends an email.
const { sendEmail } = require("@coko/server");
sendEmail({
from: "noreply@me.com",
html: `<p>Hello</p>`,
subject: `The hello message`,
text: "Hello",
to: "someone@email.com",
});
db
The database singleton, as initialized by knex.
You probably don't need this, but it can be useful. (eg. to run some sql with db.raw('some sql here')
).
const { db } = require("@coko/server");
createJWT
createJWT
is an export of a function in pubsweet-server
that does just that.
Useful if you have custom login resolvers.
uuid
Generates a valid v4 uuid.
const { uuid } = require("@coko/server");
console.log("my generated id", uuid);
Future features
- Include more pubsweet packages into the bundle