@netlify/content-engine
Version:
136 lines • 5.53 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startServer = startServer;
const express_1 = __importDefault(require("express"));
const compression_1 = __importDefault(require("compression"));
const express_2 = require("graphql-http/lib/use/express");
const content_engine_graphiql_explorer_1 = __importDefault(require("@netlify/content-engine-graphiql-explorer"));
const graphql_1 = require("graphql");
const uuid_1 = require("../core-utils/uuid");
const http_1 = __importDefault(require("http"));
const https_1 = __importDefault(require("https"));
const cors_1 = __importDefault(require("cors"));
// import telemetry from "gatsby-telemetry"
const redux_1 = require("../redux");
const context_1 = __importDefault(require("../schema/context"));
const api_runner_node_1 = __importDefault(require("./api-runner-node"));
const polyfill_remote_file_1 = require("../plugin-utils/polyfill-remote-file");
async function startServer(program, app) {
/**
* Set up the express app.
**/
app.use((0, compression_1.default)());
// app.use(telemetry.expressMiddleware(`DEVELOP`))
app.use((0, cors_1.default)());
/**
* Pattern matching all endpoints with graphql or graphiql with 1 or more leading underscores
*/
const graphqlEndpoint = `/_+graphi?ql`;
(0, content_engine_graphiql_explorer_1.default)(app, {
graphqlEndpoint,
getFragments: function getFragments() {
const fragments = [];
for (const def of redux_1.store.getState().definitions.values()) {
if (def.def.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
fragments.push(def.def);
}
}
return fragments;
},
});
app.use(graphqlEndpoint, (0, express_2.createHandler)({
schema() {
return redux_1.store.getState().schema;
},
context() {
return (0, context_1.default)({
schema: redux_1.store.getState().schema,
schemaComposer: redux_1.store.getState().schemaCustomization.composer,
context: { cacheTags: new Set() },
customContext: redux_1.store.getState().schemaCustomization.context,
});
},
onOperation(_req, args, result) {
if (result.errors) {
result.errors = result.errors.map((err) => ({
...err.toJSON(),
extensions: {
stack: err.stack ? err.stack.split(`\n`) : [],
},
}));
}
result.extensions = {
enableRefresh: process.env.ENABLE_GATSBY_REFRESH_ENDPOINT,
refreshToken: process.env.GATSBY_REFRESH_TOKEN,
};
// this is for the dev/preview gql API
if (process.env.DEBUG_CACHE_TAGS) {
result.extensions.cacheTags = Array.from(
// TODO: why does TS think contextValue can be a string?
args.contextValue?.cacheTags);
}
return result;
},
}));
/**
* Refresh external data sources.
* If no GATSBY_REFRESH_TOKEN env var is available, then no Authorization header is required
**/
const REFRESH_ENDPOINT = `/__refresh`;
const refresh = async (req, pluginName) => {
global.__GATSBY.buildId = uuid_1.uuid.v4();
redux_1.emitter.emit(`WEBHOOK_RECEIVED`, {
webhookBody: req.body,
pluginName,
});
};
app.post(`${REFRESH_ENDPOINT}/:plugin_name?`, express_1.default.json(), (req, res) => {
const pluginName = req.params[`plugin_name`];
const refreshToken = process.env.GATSBY_REFRESH_TOKEN;
const authorizedRefresh = !refreshToken || req.headers.authorization === refreshToken;
if (authorizedRefresh) {
refresh(req, pluginName);
res.status(200);
res.setHeader(`content-type`, `application/json`);
}
else {
res.status(authorizedRefresh ? 404 : 403);
res.json({
error: `Authorization failed. Make sure you add authorization header to your refresh requests`,
});
}
res.end();
});
(0, polyfill_remote_file_1.addImageRoutes)(app,
// @ts-ignore todo should this be Store or GatsbyStore?
redux_1.store);
// Expose access to app for advanced use cases
const { developMiddleware } = redux_1.store.getState().config;
if (developMiddleware) {
developMiddleware(app, program);
}
await (0, api_runner_node_1.default)(`onCreateDevServer`, { app, deferNodeMutation: true });
app.use(async (req, res) => {
// in this catch-all block we don't support POST so we should 404
if (req.method === `POST`) {
res.status(404).end();
return;
}
res.sendStatus(404);
});
return new Promise((res) => {
/**
* Set up the HTTP server and socket.io.
**/
const server = program.ssl
? new https_1.default.Server(program.ssl, app)
: new http_1.default.Server(app);
const listener = server.listen(program.port, program.host, () => {
res({ listener });
});
});
}
//# sourceMappingURL=start-server.js.map
;