import config from 'config'; import { format } from 'date-fns'; import { graphql, buildSchema, GraphQLScalarType, } from 'graphql'; import { JSONDefinition, JSONResolver, } from 'graphql-scalars'; import { scenesSchema, fetchScenesGraphql, fetchScenesByIdGraphql, } from './scenes.js'; import { moviesSchema, fetchMoviesGraphql, fetchMoviesByIdGraphql, } from './movies.js'; import { entitiesSchema, fetchEntitiesGraphql, fetchEntitiesByIdGraphql, } from './entities.js'; import { actorsSchema, fetchActorsGraphql, fetchActorsByIdGraphql, } from './actors.js'; import { stashesSchema, fetchUserStashesGraphql, fetchStashGraphql, createStashGraphql, updateStashGraphql, removeStashGraphql, stashSceneGraphql, unstashSceneGraphql, stashActorGraphql, unstashActorGraphql, stashMovieGraphql, unstashMovieGraphql, } from './stashes.js'; import { alertsSchema, fetchAlertsGraphql, createAlertGraphql, removeAlertGraphql, fetchNotificationsGraphql, updateNotificationGraphql, updateNotificationsGraphql, } from './alerts.js'; import { verifyKey } from '../auth.js'; const schema = buildSchema(` type Query { _: Boolean } type Mutation { _: Boolean } scalar Date ${JSONDefinition} ${scenesSchema} ${moviesSchema} ${actorsSchema} ${entitiesSchema} ${stashesSchema} ${alertsSchema} `); const DateTimeScalar = new GraphQLScalarType({ name: 'DateTime', serialize(value) { if (value instanceof Date) { return value.toISOString(); } return value; }, }); const DateScalar = new GraphQLScalarType({ name: 'Date', serialize(value) { if (value instanceof Date) { return format(value, 'yyyy-MM-dd'); } return value; }, }); export async function graphqlApi(req, res) { if (!config.apiAccess.graphqlEnabled) { res.status(404).send(); return; } await verifyKey(req.headers['api-user'], req.headers['api-key'], req); req.user = { // eslint-disable-line no-param-reassign id: Number(req.headers['api-user']), }; const data = await graphql({ schema, source: req.body.query, variableValues: req.body.variables, resolvers: { DateTimeScalar, DateScalar, JSON: JSONResolver, }, rootValue: { // queries scenes: async (query) => fetchScenesGraphql(query, req), scene: async (query) => fetchScenesByIdGraphql(query, req), scenesById: async (query) => fetchScenesByIdGraphql(query, req), movies: async (query) => fetchMoviesGraphql(query, req), movie: async (query) => fetchMoviesByIdGraphql(query, req), moviesById: async (query) => fetchMoviesByIdGraphql(query, req), actors: async (query) => fetchActorsGraphql(query, req), actor: async (query, args, info) => fetchActorsByIdGraphql(query, req, info), actorsById: async (query, args, info) => fetchActorsByIdGraphql(query, req, info), entities: async (query) => fetchEntitiesGraphql(query, req), entity: async (query, args, info) => fetchEntitiesByIdGraphql(query, req, info), entitiesBySlug: async (query, args, info) => fetchEntitiesByIdGraphql(query, req, info), entitiesById: async (query, args, info) => fetchEntitiesByIdGraphql(query, req, info), stashes: async (query) => fetchUserStashesGraphql(query, req), stash: async (query) => fetchStashGraphql(query, req), alerts: async (query) => fetchAlertsGraphql(query, req), notifications: async (query) => fetchNotificationsGraphql(query, req), // stash mutation createStash: async (query) => createStashGraphql(query, req), updateStash: async (query) => updateStashGraphql(query, req), removeStash: async (query) => removeStashGraphql(query, req), stashScene: async (query) => stashSceneGraphql(query, req), unstashScene: async (query) => unstashSceneGraphql(query, req), stashActor: async (query) => stashActorGraphql(query, req), unstashActor: async (query) => unstashActorGraphql(query, req), stashMovie: async (query) => stashMovieGraphql(query, req), unstashMovie: async (query) => unstashMovieGraphql(query, req), // alert mutation createAlert: async (query) => createAlertGraphql(query, req), removeAlert: async (query) => removeAlertGraphql(query, req), updateNotification: async (query) => updateNotificationGraphql(query, req), updateNotifications: async (query) => updateNotificationsGraphql(query, req), }, }); const statusCode = data.errors?.[0]?.originalError?.httpCode || 200; res.status(statusCode).send(data); }