You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP
Socket
Sign inDemoInstall
Socket

@freshsqueezed/mammothgql

Package Overview
Dependencies
Maintainers
0
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@freshsqueezed/mammothgql - npm Package Compare versions

Comparing version

to
1.0.5

8

CHANGELOG.md

@@ -0,1 +1,9 @@

## [1.0.5](https://github.com/freshsqueezed/mammothgql/compare/v1.0.4...v1.0.5) (2024-12-18)
### Bug Fixes
* **mammoth:** release updated graphiql ([2663dfe](https://github.com/freshsqueezed/mammothgql/commit/2663dfe42d4caa0c0e9fecb5f1a13a45460ae695))
* **request:** update request pipeline ([#3](https://github.com/freshsqueezed/mammothgql/issues/3)) ([e2fe768](https://github.com/freshsqueezed/mammothgql/commit/e2fe76820d6f4fc1ba90dc17c0f3326d3a98e15d))
## [1.0.4](https://github.com/freshsqueezed/mammothgql/compare/v1.0.3...v1.0.4) (2024-12-18)

@@ -2,0 +10,0 @@

9

lib/html/graphiql.js

@@ -5,2 +5,7 @@ "use strict";

function graphiqlHtml(req, res) {
const protocol = req.protocol;
const host = req.get('host');
const path = req.path;
const fullUrl = `${protocol}://${host}${path}`;
const wsUrl = `${protocol === 'https' ? 'wss' : 'ws'}://${host}${path}`;
res.send(`

@@ -78,5 +83,5 @@ <!--

const fetcher = GraphiQL.createFetcher({
url: '${req.path}',
url: '${fullUrl}',
wsClient: graphqlWs.createClient({
url: '${req.path}',
url: '${wsUrl}',
}),

@@ -83,0 +88,0 @@ });

import { NextFunction, Request, Response } from 'express';
import { GraphQLError } from 'graphql';
import type { GraphQLSchema, GraphQLFormattedError, ValidationRule } from 'graphql';
export interface MammothOptions<TContext> {
import type { GraphQLSchema, ValidationRule } from 'graphql';
interface MammothOptions<TContext> {
schema: GraphQLSchema;

@@ -15,9 +14,3 @@ context: ({ req, res }: {

export declare function mammothGraphql<TContext>(options: MammothOptions<TContext>): (req: Request, res: Response, next: NextFunction) => Promise<void>;
export declare const errorMessages: (messages: string[], graphqlErrors?: readonly GraphQLError[] | readonly GraphQLFormattedError[]) => {
errors: readonly GraphQLError[] | readonly GraphQLFormattedError[];
} | {
errors: {
message: string;
}[];
};
export {};
//# sourceMappingURL=mammoth.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.errorMessages = void 0;
exports.mammothGraphql = mammothGraphql;
const graphql_1 = require("graphql");
const utils_1 = require("./utils");
const html_1 = require("./html");
function mammothGraphql(options) {
const schema = options.schema;
const pretty = options.pretty ?? false;
const validationRules = options.validationRules ?? [];
const showGraphiQL = options.graphiql ?? false;
const { schema, pretty = false, graphiql: showGraphiQL = false, validationRules = [], } = options;
return async (req, res, next) => {

@@ -17,19 +12,19 @@ if (req.method !== 'GET' && req.method !== 'POST') {

.status(405)
.json((0, exports.errorMessages)(['GraphQL only supports GET and POST requests.']));
.json(createErrorMessages(['GraphQL only supports GET and POST requests.']));
return;
}
const { query, variables, operationName } = req.body;
if (query == null) {
if (!query) {
if (showGraphiQL && req.method === 'GET') {
return (0, html_1.graphiqlHtml)(req, res);
(0, html_1.graphiqlHtml)(req, res);
return;
}
res.status(400).json((0, exports.errorMessages)(['Must provide query string.']));
res.status(400).json(createErrorMessages(['Must provide query string.']));
return;
}
const schemaValidationErrors = (0, graphql_1.validateSchema)(schema);
if (schemaValidationErrors.length > 0) {
// Return 500: Internal Server Error if invalid schema.
const schemaErrors = (0, graphql_1.validateSchema)(schema);
if (schemaErrors.length > 0) {
res
.status(500)
.json((0, exports.errorMessages)(['GraphQL schema validation error.'], schemaValidationErrors));
.json(createErrorMessages(['GraphQL schema validation error.'], schemaErrors));
return;

@@ -41,15 +36,12 @@ }

}
catch (syntaxError) {
// Return 400: Bad Request if any syntax errors errors exist.
if (syntaxError instanceof Error) {
console.error(`${syntaxError.stack || syntaxError.message}`);
const e = new graphql_1.GraphQLError(syntaxError.message, {
originalError: syntaxError,
});
res.status(400).json((0, exports.errorMessages)(['GraphQL syntax error.'], [e]));
return;
}
throw syntaxError;
catch (error) {
const syntaxError = error instanceof Error ? error : new Error('Unknown parsing error');
const graphQLError = new graphql_1.GraphQLError(syntaxError.message, {
originalError: syntaxError,
});
res
.status(400)
.json(createErrorMessages(['GraphQL syntax error.'], [graphQLError]));
return;
}
// Validate AST, reporting any errors.
const validationErrors = (0, graphql_1.validate)(schema, documentAST, [

@@ -60,17 +52,14 @@ ...graphql_1.specifiedRules,

if (validationErrors.length > 0) {
// Return 400: Bad Request if any validation errors exist.
res
.status(400)
.json((0, exports.errorMessages)(['GraphQL validation error.'], validationErrors));
.json(createErrorMessages(['GraphQL validation error.'], validationErrors));
return;
}
if (req.method === 'GET') {
// Determine if this GET request will perform a non-query.
const operationAST = (0, graphql_1.getOperationAST)(documentAST, operationName);
if (operationAST && operationAST.operation !== 'query') {
// Otherwise, report a 405: Method Not Allowed error.
if (operationAST?.operation !== 'query') {
res
.status(405)
.json((0, exports.errorMessages)([
`Can only perform a ${operationAST.operation} operation from a POST request.`,
.json(createErrorMessages([
`Can only perform ${operationAST?.operation} operations via POST.`,
]));

@@ -80,13 +69,4 @@ return;

}
let result;
try {
// Parse and validate the query
const source = new graphql_1.Source(query, 'Mammoth Request');
const document = (0, graphql_1.parse)(source);
const validationErrors = (0, graphql_1.validate)(schema, document, graphql_1.specifiedRules);
if (validationErrors.length > 0) {
return (0, utils_1.handleValidationErrors)(validationErrors, res);
}
// Prepare context and execute the query
result = await (0, graphql_1.execute)({
const result = await (0, graphql_1.execute)({
schema,

@@ -96,54 +76,29 @@ document: documentAST,

variableValues: variables,
operationName: operationName,
operationName,
});
}
catch (contextError) {
if (contextError instanceof Error) {
console.error(`${contextError.stack || contextError.message}`);
const e = new graphql_1.GraphQLError(contextError.message, {
originalError: contextError,
nodes: documentAST,
});
// Return 400: Bad Request if any execution context errors exist.
res
.status(400)
.json((0, exports.errorMessages)(['GraphQL execution context error.'], [e]));
if (!result.data && result.errors) {
res.status(500).json(createErrorMessages(result.errors.map((e) => e.message), result.errors));
return;
}
throw contextError;
const payload = pretty ? JSON.stringify(result, null, 2) : result;
res.status(200).json(payload);
}
if (!result.data) {
if (result.errors) {
res
.status(500)
.json((0, exports.errorMessages)([result.errors.toString()], result.errors));
return;
}
catch (error) {
const executionError = error instanceof Error ? error : new Error('Unknown execution error');
const graphQLError = new graphql_1.GraphQLError(executionError.message, {
originalError: executionError,
nodes: documentAST,
});
res
.status(400)
.json(createErrorMessages(['GraphQL execution context error.'], [graphQLError]));
}
if (pretty) {
const payload = JSON.stringify(result, null, pretty ? 2 : 0);
res.status(200).send(payload);
return;
finally {
next();
}
else {
res.json(result);
return;
}
};
}
const errorMessages = (messages, graphqlErrors) => {
if (graphqlErrors) {
return {
errors: graphqlErrors,
};
}
return {
errors: messages.map((message) => {
return {
message: message,
};
}),
};
};
exports.errorMessages = errorMessages;
const createErrorMessages = (messages, graphqlErrors) => ({
errors: graphqlErrors ?? messages.map((message) => ({ message })),
});
//# sourceMappingURL=mammoth.js.map

@@ -6,3 +6,3 @@ {

"types": "lib/index.d.ts",
"version": "1.0.4",
"version": "1.0.5",
"author": "Matt Gordon <matt@lemonade.tech>",

@@ -9,0 +9,0 @@ "license": "MIT",

import { Request, Response } from 'express';
export function graphiqlHtml(req: Request, res: Response) {
const protocol = req.protocol;
const host = req.get('host');
const path = req.path;
const fullUrl = `${protocol}://${host}${path}`;
const wsUrl = `${protocol === 'https' ? 'wss' : 'ws'}://${host}${path}`;
res.send(`

@@ -76,5 +82,5 @@ <!--

const fetcher = GraphiQL.createFetcher({
url: '${req.path}',
url: '${fullUrl}',
wsClient: graphqlWs.createClient({
url: '${req.path}',
url: '${wsUrl}',
}),

@@ -81,0 +87,0 @@ });

@@ -20,5 +20,5 @@ import { NextFunction, Request, Response } from 'express';

import { handleValidationErrors } from './utils';
import { customLandingHtml, disabledLandingPage, graphiqlHtml } from './html';
import { graphiqlHtml } from './html';
export interface MammothOptions<TContext> {
interface MammothOptions<TContext> {
schema: GraphQLSchema;

@@ -32,6 +32,8 @@ context: ({ req, res }: { req: Request; res: Response }) => TContext;

export function mammothGraphql<TContext>(options: MammothOptions<TContext>) {
const schema = options.schema;
const pretty = options.pretty ?? false;
const validationRules = options.validationRules ?? [];
const showGraphiQL = options.graphiql ?? false;
const {
schema,
pretty = false,
graphiql: showGraphiQL = false,
validationRules = [],
} = options;

@@ -46,3 +48,5 @@ return async (

.status(405)
.json(errorMessages(['GraphQL only supports GET and POST requests.']));
.json(
createErrorMessages(['GraphQL only supports GET and POST requests.']),
);
return;

@@ -53,19 +57,19 @@ }

if (query == null) {
if (!query) {
if (showGraphiQL && req.method === 'GET') {
return graphiqlHtml(req, res);
graphiqlHtml(req, res);
return;
}
res.status(400).json(errorMessages(['Must provide query string.']));
res.status(400).json(createErrorMessages(['Must provide query string.']));
return;
}
const schemaValidationErrors = validateSchema(schema);
if (schemaValidationErrors.length > 0) {
// Return 500: Internal Server Error if invalid schema.
const schemaErrors = validateSchema(schema);
if (schemaErrors.length > 0) {
res
.status(500)
.json(
errorMessages(
createErrorMessages(
['GraphQL schema validation error.'],
schemaValidationErrors,
schemaErrors,
),

@@ -79,16 +83,16 @@ );

documentAST = parse(new Source(query, 'GraphQL request'));
} catch (syntaxError: unknown) {
// Return 400: Bad Request if any syntax errors errors exist.
if (syntaxError instanceof Error) {
console.error(`${syntaxError.stack || syntaxError.message}`);
const e = new GraphQLError(syntaxError.message, {
originalError: syntaxError,
});
res.status(400).json(errorMessages(['GraphQL syntax error.'], [e]));
return;
}
throw syntaxError;
} catch (error: unknown) {
const syntaxError =
error instanceof Error ? error : new Error('Unknown parsing error');
const graphQLError = new GraphQLError(syntaxError.message, {
originalError: syntaxError,
});
res
.status(400)
.json(createErrorMessages(['GraphQL syntax error.'], [graphQLError]));
return;
}
// Validate AST, reporting any errors.
const validationErrors = validate(schema, documentAST, [

@@ -100,6 +104,7 @@ ...specifiedRules,

if (validationErrors.length > 0) {
// Return 400: Bad Request if any validation errors exist.
res
.status(400)
.json(errorMessages(['GraphQL validation error.'], validationErrors));
.json(
createErrorMessages(['GraphQL validation error.'], validationErrors),
);
return;

@@ -109,11 +114,9 @@ }

if (req.method === 'GET') {
// Determine if this GET request will perform a non-query.
const operationAST = getOperationAST(documentAST, operationName);
if (operationAST && operationAST.operation !== 'query') {
// Otherwise, report a 405: Method Not Allowed error.
if (operationAST?.operation !== 'query') {
res
.status(405)
.json(
errorMessages([
`Can only perform a ${operationAST.operation} operation from a POST request.`,
createErrorMessages([
`Can only perform ${operationAST?.operation} operations via POST.`,
]),

@@ -125,55 +128,40 @@ );

let result: FormattedExecutionResult;
try {
// Parse and validate the query
const source = new Source(query, 'Mammoth Request');
const document = parse(source);
const validationErrors = validate(schema, document, specifiedRules);
if (validationErrors.length > 0) {
return handleValidationErrors(validationErrors, res);
}
// Prepare context and execute the query
result = await execute({
const result = await execute({
schema,
document: documentAST,
contextValue: options.context({ req, res }) as TContext,
contextValue: options.context({ req, res }),
variableValues: variables,
operationName: operationName,
operationName,
});
} catch (contextError: unknown) {
if (contextError instanceof Error) {
console.error(`${contextError.stack || contextError.message}`);
const e = new GraphQLError(contextError.message, {
originalError: contextError,
nodes: documentAST,
});
// Return 400: Bad Request if any execution context errors exist.
res
.status(400)
.json(errorMessages(['GraphQL execution context error.'], [e]));
return;
}
throw contextError;
}
if (!result.data) {
if (result.errors) {
res
.status(500)
.json(errorMessages([result.errors.toString()], result.errors));
if (!result.data && result.errors) {
res.status(500).json(
createErrorMessages(
result.errors.map((e) => e.message),
result.errors,
),
);
return;
}
}
if (pretty) {
const payload = JSON.stringify(result, null, pretty ? 2 : 0);
res.status(200).send(payload);
return;
} else {
res.json(result);
return;
const payload = pretty ? JSON.stringify(result, null, 2) : result;
res.status(200).json(payload);
} catch (error: unknown) {
const executionError =
error instanceof Error ? error : new Error('Unknown execution error');
const graphQLError = new GraphQLError(executionError.message, {
originalError: executionError,
nodes: documentAST,
});
res
.status(400)
.json(
createErrorMessages(
['GraphQL execution context error.'],
[graphQLError],
),
);
} finally {
next();
}

@@ -183,19 +171,7 @@ };

export const errorMessages = (
const createErrorMessages = (
messages: string[],
graphqlErrors?: readonly GraphQLError[] | readonly GraphQLFormattedError[],
) => {
if (graphqlErrors) {
return {
errors: graphqlErrors,
};
}
return {
errors: messages.map((message) => {
return {
message: message,
};
}),
};
};
) => ({
errors: graphqlErrors ?? messages.map((message) => ({ message })),
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet