feat: graphql schema output (#730)
* chore: refactor graphql initialization * feat: generate graphql schema script * feat: script commands are case insenstive
This commit is contained in:
26
src/bin/generateGraphQLSchema.ts
Normal file
26
src/bin/generateGraphQLSchema.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import fs from 'fs';
|
||||
import { printSchema } from 'graphql';
|
||||
import Logger from '../utilities/logger';
|
||||
import loadConfig from '../config/load';
|
||||
import payload from '..';
|
||||
|
||||
export function generateGraphQLSchema(): void {
|
||||
const logger = Logger();
|
||||
const config = loadConfig();
|
||||
|
||||
payload.init({
|
||||
secret: '--unused--',
|
||||
mongoURL: false,
|
||||
local: true,
|
||||
});
|
||||
|
||||
logger.info('Compiling GraphQL schema...');
|
||||
fs.writeFileSync(config.graphQL.schemaOutputFile, printSchema(payload.schema));
|
||||
logger.info(`GraphQL written to ${config.typescript.outputFile}`);
|
||||
}
|
||||
|
||||
// when generateGraphQLSchema.js is launched directly
|
||||
if (module.id === require.main.id) {
|
||||
generateGraphQLSchema();
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import minimist from 'minimist';
|
||||
import { generateTypes } from './generateTypes';
|
||||
import { generateGraphQLSchema } from './generateGraphQLSchema';
|
||||
import babelConfig from '../babel.config';
|
||||
|
||||
require('@babel/register')({
|
||||
@@ -18,7 +19,7 @@ const scriptIndex = args._.findIndex(
|
||||
|
||||
const script = scriptIndex === -1 ? args._[0] : args._[scriptIndex];
|
||||
|
||||
switch (script) {
|
||||
switch (script.toLowerCase()) {
|
||||
case 'build': {
|
||||
build();
|
||||
break;
|
||||
@@ -29,6 +30,10 @@ switch (script) {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'generate:graphqlschema': {
|
||||
generateGraphQLSchema();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
console.log(`Unknown script "${script}".`);
|
||||
|
||||
@@ -28,6 +28,7 @@ export const defaults: Config = {
|
||||
graphQL: {
|
||||
maxComplexity: 1000,
|
||||
disablePlaygroundInProduction: true,
|
||||
schemaOutputFile: `${typeof process?.cwd === 'function' ? process.cwd() : ''}/schema.graphql`,
|
||||
},
|
||||
routes: {
|
||||
admin: '/admin',
|
||||
|
||||
@@ -116,6 +116,7 @@ export default joi.object({
|
||||
maxComplexity: joi.number(),
|
||||
disablePlaygroundInProduction: joi.boolean(),
|
||||
disable: joi.boolean(),
|
||||
schemaOutputFile: joi.string(),
|
||||
}),
|
||||
localization: joi.alternatives()
|
||||
.try(
|
||||
|
||||
@@ -62,7 +62,7 @@ export function hasTransportOptions(emailConfig: EmailOptions): emailConfig is E
|
||||
|
||||
export type InitOptions = {
|
||||
express?: Express;
|
||||
mongoURL: string;
|
||||
mongoURL: string | false;
|
||||
mongoOptions?: ConnectOptions;
|
||||
secret: string;
|
||||
email?: EmailOptions;
|
||||
@@ -181,6 +181,7 @@ export type Config = {
|
||||
maxComplexity?: number;
|
||||
disablePlaygroundInProduction?: boolean;
|
||||
disable?: boolean;
|
||||
schemaOutputFile?: string;
|
||||
};
|
||||
components?: { [key: string]: JSX.Element | (() => JSX.Element) };
|
||||
hooks?: {
|
||||
|
||||
21
src/graphql/graphQLHandler.ts
Normal file
21
src/graphql/graphQLHandler.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { graphqlHTTP } from 'express-graphql';
|
||||
import { Response } from 'express';
|
||||
import { PayloadRequest } from '../express/types';
|
||||
|
||||
const graphQLHandler = (req: PayloadRequest, res: Response) => {
|
||||
const { payload } = req;
|
||||
|
||||
payload.errorResponses = null;
|
||||
|
||||
return graphqlHTTP(
|
||||
async (request, response, { variables }) => ({
|
||||
schema: payload.schema,
|
||||
customFormatErrorFn: payload.customFormatErrorFn,
|
||||
extensions: payload.extensions,
|
||||
context: { req, res },
|
||||
validationRules: payload.validationRules(variables),
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
export default graphQLHandler;
|
||||
@@ -1,19 +1,18 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import * as GraphQL from 'graphql';
|
||||
import { GraphQLObjectType, GraphQLSchema } from 'graphql';
|
||||
import { graphqlHTTP } from 'express-graphql';
|
||||
import queryComplexity, { fieldExtensionsEstimator, simpleEstimator } from 'graphql-query-complexity';
|
||||
import errorHandler from './errorHandler';
|
||||
import buildPoliciesType from './schema/buildPoliciesType';
|
||||
import { Payload } from '..';
|
||||
import buildLocaleInputType from './schema/buildLocaleInputType';
|
||||
import buildFallbackLocaleInputType from './schema/buildFallbackLocaleInputType';
|
||||
import initCollections from '../collections/graphql/init';
|
||||
import initGlobals from '../globals/graphql/init';
|
||||
import initPreferences from '../preferences/graphql/init';
|
||||
import buildPoliciesType from './schema/buildPoliciesType';
|
||||
import accessResolver from '../auth/graphql/resolvers/access';
|
||||
import errorHandler from './errorHandler';
|
||||
|
||||
const initializeGraphQL = (req, res) => {
|
||||
const { payload } = req;
|
||||
|
||||
export default function registerSchema(payload: Payload): void {
|
||||
payload.types = {
|
||||
blockTypes: {},
|
||||
blockInputTypes: {},
|
||||
@@ -106,18 +105,4 @@ const initializeGraphQL = (req, res) => {
|
||||
// onComplete: (complexity) => { console.log('Query Complexity:', complexity); },
|
||||
}),
|
||||
]);
|
||||
|
||||
payload.errorResponses = null;
|
||||
|
||||
return graphqlHTTP(
|
||||
async (request, response, { variables }) => ({
|
||||
schema: payload.schema,
|
||||
customFormatErrorFn: payload.customFormatErrorFn,
|
||||
extensions: payload.extensions,
|
||||
context: { req, res },
|
||||
validationRules: payload.validationRules(variables),
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
export default initializeGraphQL;
|
||||
}
|
||||
22
src/index.ts
22
src/index.ts
@@ -1,4 +1,4 @@
|
||||
import express, { Express, Router } from 'express';
|
||||
import express, { Express, Response, Router } from 'express';
|
||||
import pino from 'pino';
|
||||
import crypto from 'crypto';
|
||||
import { GraphQLError, GraphQLFormattedError, GraphQLSchema } from 'graphql';
|
||||
@@ -29,7 +29,8 @@ import initGlobals from './globals/init';
|
||||
import { Globals, TypeWithID as GlobalTypeWithID } from './globals/config/types';
|
||||
import initGraphQLPlayground from './graphql/initPlayground';
|
||||
import initStatic from './express/static';
|
||||
import initializeGraphQL from './graphql';
|
||||
import registerSchema from './graphql/registerSchema';
|
||||
import graphQLHandler from './graphql/graphQLHandler';
|
||||
import buildEmail from './email/build';
|
||||
import identifyAPI from './express/middleware/identifyAPI';
|
||||
import errorHandler, { ErrorHandler } from './express/middleware/errorHandler';
|
||||
@@ -98,7 +99,7 @@ export class Payload {
|
||||
|
||||
secret: string;
|
||||
|
||||
mongoURL: string;
|
||||
mongoURL: string | false;
|
||||
|
||||
local: boolean;
|
||||
|
||||
@@ -113,8 +114,8 @@ export class Payload {
|
||||
types: {
|
||||
blockTypes: any;
|
||||
blockInputTypes: any;
|
||||
localeInputType: any;
|
||||
fallbackLocaleInputType: any;
|
||||
localeInputType?: any;
|
||||
fallbackLocaleInputType?: any;
|
||||
};
|
||||
|
||||
Query: { name: string; fields: { [key: string]: any } } = { name: 'Query', fields: {} };
|
||||
@@ -146,7 +147,7 @@ export class Payload {
|
||||
);
|
||||
}
|
||||
|
||||
if (!options.mongoURL) {
|
||||
if (options.mongoURL !== false && typeof options.mongoURL !== 'string') {
|
||||
throw new Error('Error: missing MongoDB connection URL.');
|
||||
}
|
||||
|
||||
@@ -178,8 +179,13 @@ export class Payload {
|
||||
initGlobals(this);
|
||||
|
||||
// Connect to database
|
||||
connectMongoose(this.mongoURL, options.mongoOptions, options.local, this.logger);
|
||||
if (this.mongoURL) {
|
||||
connectMongoose(this.mongoURL, options.mongoOptions, options.local, this.logger);
|
||||
}
|
||||
|
||||
if (!this.config.graphQL.disable) {
|
||||
registerSchema(this);
|
||||
}
|
||||
// If not initializing locally, set up HTTP routing
|
||||
if (!this.local) {
|
||||
options.express.use((req: PayloadRequest, res, next) => {
|
||||
@@ -202,7 +208,7 @@ export class Payload {
|
||||
this.router.use(
|
||||
this.config.routes.graphQL,
|
||||
identifyAPI('GraphQL'),
|
||||
(req, res) => initializeGraphQL(req, res)(req, res),
|
||||
(req: PayloadRequest, res: Response) => graphQLHandler(req, res)(req, res),
|
||||
);
|
||||
initGraphQLPlayground(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user