@smartive/graphql-magic 19.5.0 → 19.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- # [19.5.0](https://github.com/smartive/graphql-magic/compare/v19.4.0...v19.5.0) (2025-07-30)
1
+ # [19.6.0](https://github.com/smartive/graphql-magic/compare/v19.5.0...v19.6.0) (2025-08-18)
2
2
 
3
3
 
4
4
  ### Features
5
5
 
6
- * Union types ([#331](https://github.com/smartive/graphql-magic/issues/331)) ([da9d23c](https://github.com/smartive/graphql-magic/commit/da9d23c7b767961dd7740f4e689522d0d4231713))
6
+ * disable introspection by default ([#335](https://github.com/smartive/graphql-magic/issues/335)) ([d3ad3b4](https://github.com/smartive/graphql-magic/commit/d3ad3b49ec4b5bd046549cb280b6a7b6324ecf2f))
package/dist/bin/gqm.cjs CHANGED
@@ -30,9 +30,12 @@ var import_simple_git = require("simple-git");
30
30
 
31
31
  // src/api/execute.ts
32
32
  var import_schema = require("@graphql-tools/schema");
33
- var import_graphql = require("graphql");
33
+ var import_graphql2 = require("graphql");
34
34
  var import_merge = __toESM(require("lodash/merge"), 1);
35
35
 
36
+ // src/errors.ts
37
+ var import_graphql = require("graphql");
38
+
36
39
  // src/client/mutations.ts
37
40
  var import_upperCase = __toESM(require("lodash/upperCase"), 1);
38
41
  var constantCase = (str) => (0, import_upperCase.default)(str).replace(/ /g, "_");
@@ -1273,9 +1276,6 @@ var getMigrationDate = () => {
1273
1276
  return `${year}${month}${day}${hours}${minutes}${seconds}`;
1274
1277
  };
1275
1278
 
1276
- // src/errors.ts
1277
- var import_graphql2 = require("graphql");
1278
-
1279
1279
  // src/resolvers/utils.ts
1280
1280
  var import_graphql3 = require("graphql");
1281
1281
  var import_isEqual = __toESM(require("lodash/isEqual"), 1);
@@ -197,11 +197,52 @@ module.exports = __toCommonJS(index_exports);
197
197
 
198
198
  // src/api/execute.ts
199
199
  var import_schema = require("@graphql-tools/schema");
200
- var import_graphql = require("graphql");
200
+ var import_graphql2 = require("graphql");
201
201
  var import_merge = __toESM(require("lodash/merge"), 1);
202
+
203
+ // src/errors.ts
204
+ var import_graphql = require("graphql");
205
+ var GraphQLError = class extends import_graphql.GraphQLError {
206
+ constructor(message, extensions) {
207
+ super(message, void 0, void 0, void 0, void 0, void 0, extensions);
208
+ }
209
+ };
210
+ var ForbiddenError = class extends GraphQLError {
211
+ constructor(what) {
212
+ super(what, { code: "FORBIDDEN" });
213
+ }
214
+ };
215
+ var NotFoundError = class extends GraphQLError {
216
+ constructor(what) {
217
+ super(what, { code: "NOT_FOUND" });
218
+ }
219
+ };
220
+ var UserInputError = class extends GraphQLError {
221
+ constructor(what) {
222
+ super(what, { code: "BAD_USER_INPUT" });
223
+ }
224
+ };
225
+ var PermissionError = class extends ForbiddenError {
226
+ constructor(role, action, what, why) {
227
+ super(`Role ${role} does not have sufficient permissions to ${action.toLowerCase()} ${what} (${why}).`);
228
+ }
229
+ };
230
+
231
+ // src/utils/rules.ts
232
+ var noIntrospection = (context) => ({
233
+ Field(node) {
234
+ const name2 = node.name.value;
235
+ if (name2 === "__schema" || name2 === "__type") {
236
+ context.reportError(new ForbiddenError("GraphQL introspection is disabled"));
237
+ }
238
+ }
239
+ });
240
+
241
+ // src/api/execute.ts
202
242
  var execute = async ({
203
243
  additionalResolvers,
204
244
  body,
245
+ introspection = false,
205
246
  ...ctx
206
247
  }) => {
207
248
  const document2 = generate(ctx.models);
@@ -210,13 +251,22 @@ var execute = async ({
210
251
  typeDefs: document2,
211
252
  resolvers: (0, import_merge.default)(generatedResolvers, additionalResolvers)
212
253
  });
254
+ const parsedDocument = (0, import_graphql2.parse)(new import_graphql2.Source(body.query, "GraphQL request"));
255
+ const validationErrors = (0, import_graphql2.validate)(
256
+ schema,
257
+ parsedDocument,
258
+ introspection ? import_graphql2.specifiedRules : [...import_graphql2.specifiedRules, noIntrospection]
259
+ );
260
+ if (validationErrors.length > 0) {
261
+ return { errors: validationErrors };
262
+ }
213
263
  const contextValue = {
214
264
  document: document2,
215
265
  ...ctx
216
266
  };
217
- const result = await (0, import_graphql.execute)({
267
+ const result = await (0, import_graphql2.execute)({
218
268
  schema,
219
- document: (0, import_graphql.parse)(new import_graphql.Source(body.query, "GraphQL request")),
269
+ document: parsedDocument,
220
270
  contextValue,
221
271
  variableValues: body.variables,
222
272
  operationName: body.operationName,
@@ -1679,34 +1729,6 @@ var getMigrationDate = () => {
1679
1729
  return `${year}${month}${day}${hours}${minutes}${seconds}`;
1680
1730
  };
1681
1731
 
1682
- // src/errors.ts
1683
- var import_graphql2 = require("graphql");
1684
- var GraphQLError = class extends import_graphql2.GraphQLError {
1685
- constructor(message, extensions) {
1686
- super(message, void 0, void 0, void 0, void 0, void 0, extensions);
1687
- }
1688
- };
1689
- var ForbiddenError = class extends GraphQLError {
1690
- constructor(what) {
1691
- super(what, { code: "FORBIDDEN" });
1692
- }
1693
- };
1694
- var NotFoundError = class extends GraphQLError {
1695
- constructor(what) {
1696
- super(what, { code: "NOT_FOUND" });
1697
- }
1698
- };
1699
- var UserInputError = class extends GraphQLError {
1700
- constructor(what) {
1701
- super(what, { code: "BAD_USER_INPUT" });
1702
- }
1703
- };
1704
- var PermissionError = class extends ForbiddenError {
1705
- constructor(role, action, what, why) {
1706
- super(`Role ${role} does not have sufficient permissions to ${action.toLowerCase()} ${what} (${why}).`);
1707
- }
1708
- };
1709
-
1710
1732
  // src/resolvers/utils.ts
1711
1733
  var import_crypto = require("crypto");
1712
1734
  var import_graphql3 = require("graphql");
@@ -1,6 +1,7 @@
1
1
  import { IResolvers } from '@graphql-tools/utils';
2
2
  import { Context } from '..';
3
- export declare const execute: ({ additionalResolvers, body, ...ctx }: {
3
+ export declare const execute: ({ additionalResolvers, body, introspection, ...ctx }: {
4
4
  additionalResolvers?: IResolvers<any, any>;
5
+ introspection?: boolean;
5
6
  body: any;
6
7
  } & Omit<Context, "document">) => Promise<import("graphql").ExecutionResult<import("graphql/jsutils/ObjMap").ObjMap<unknown>, import("graphql/jsutils/ObjMap").ObjMap<unknown>>>;
@@ -1,21 +1,27 @@
1
1
  import { makeExecutableSchema } from '@graphql-tools/schema';
2
- import { Source, execute as graphqlExecute, parse } from 'graphql';
2
+ import { Source, execute as graphqlExecute, parse, specifiedRules, validate } from 'graphql';
3
3
  import merge from 'lodash/merge';
4
4
  import { generate, get, getResolvers } from '..';
5
- export const execute = async ({ additionalResolvers, body, ...ctx }) => {
5
+ import { noIntrospection } from '../utils/rules';
6
+ export const execute = async ({ additionalResolvers, body, introspection = false, ...ctx }) => {
6
7
  const document = generate(ctx.models);
7
8
  const generatedResolvers = getResolvers(ctx.models);
8
9
  const schema = makeExecutableSchema({
9
10
  typeDefs: document,
10
11
  resolvers: merge(generatedResolvers, additionalResolvers),
11
12
  });
13
+ const parsedDocument = parse(new Source(body.query, 'GraphQL request'));
14
+ const validationErrors = validate(schema, parsedDocument, introspection ? specifiedRules : [...specifiedRules, noIntrospection]);
15
+ if (validationErrors.length > 0) {
16
+ return { errors: validationErrors };
17
+ }
12
18
  const contextValue = {
13
19
  document,
14
20
  ...ctx,
15
21
  };
16
22
  const result = await graphqlExecute({
17
23
  schema,
18
- document: parse(new Source(body.query, 'GraphQL request')),
24
+ document: parsedDocument,
19
25
  contextValue,
20
26
  variableValues: body.variables,
21
27
  operationName: body.operationName,
@@ -1 +1 @@
1
- {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/api/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAsB,MAAM,EAAE,OAAO,IAAI,cAAc,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAW,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAE1D,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,EAC5B,mBAAmB,EACnB,IAAI,EACJ,GAAG,GAAG,EAIqB,EAAE,EAAE;IAC/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,kBAAkB,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,oBAAoB,CAAC;QAClC,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,KAAK,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;KAC1D,CAAC,CAAC;IAEH,MAAM,YAAY,GAAY;QAC5B,QAAQ;QACR,GAAG,GAAG;KACP,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,MAAM;QACN,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAC1D,YAAY;QACZ,cAAc,EAAE,IAAI,CAAC,SAAS;QAC9B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,aAAa,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAwB,EAAE,EAAE;YAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YAEzB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/api/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAsB,MAAM,EAAE,OAAO,IAAI,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAW,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,EAC5B,mBAAmB,EACnB,IAAI,EACJ,aAAa,GAAG,KAAK,EACrB,GAAG,GAAG,EAKqB,EAAE,EAAE;IAC/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,kBAAkB,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,oBAAoB,CAAC;QAClC,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,KAAK,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;KAC1D,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAExE,MAAM,gBAAgB,GAAG,QAAQ,CAC/B,MAAM,EACN,cAAc,EACd,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,eAAe,CAAC,CACtE,CAAC;IAEF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,YAAY,GAAY;QAC5B,QAAQ;QACR,GAAG,GAAG;KACP,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,MAAM;QACN,QAAQ,EAAE,cAAc;QACxB,YAAY;QACZ,cAAc,EAAE,IAAI,CAAC,SAAS;QAC9B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,aAAa,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAwB,EAAE,EAAE;YAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YAEzB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ValidationContext } from 'graphql';
2
+ export declare const noIntrospection: (context: ValidationContext) => {
3
+ Field(node: any): void;
4
+ };
@@ -0,0 +1,10 @@
1
+ import { ForbiddenError } from '../errors';
2
+ export const noIntrospection = (context) => ({
3
+ Field(node) {
4
+ const name = node.name.value;
5
+ if (name === '__schema' || name === '__type') {
6
+ context.reportError(new ForbiddenError('GraphQL introspection is disabled'));
7
+ }
8
+ },
9
+ });
10
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/utils/rules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAA0B,EAAE,EAAE,CAAC,CAAC;IAC9D,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC7B,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7C,OAAO,CAAC,WAAW,CAAC,IAAI,cAAc,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -20,7 +20,7 @@
20
20
  "@docusaurus/module-type-aliases": "3.8.1",
21
21
  "@docusaurus/tsconfig": "3.8.1",
22
22
  "@docusaurus/types": "3.8.1",
23
- "typescript": "5.8.3"
23
+ "typescript": "5.9.2"
24
24
  },
25
25
  "engines": {
26
26
  "node": ">=22.0"
@@ -16012,9 +16012,9 @@
16012
16012
  }
16013
16013
  },
16014
16014
  "node_modules/typescript": {
16015
- "version": "5.8.3",
16016
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
16017
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
16015
+ "version": "5.9.2",
16016
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
16017
+ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
16018
16018
  "devOptional": true,
16019
16019
  "license": "Apache-2.0",
16020
16020
  "bin": {
package/docs/package.json CHANGED
@@ -27,7 +27,7 @@
27
27
  "@docusaurus/module-type-aliases": "3.8.1",
28
28
  "@docusaurus/tsconfig": "3.8.1",
29
29
  "@docusaurus/types": "3.8.1",
30
- "typescript": "5.8.3"
30
+ "typescript": "5.9.2"
31
31
  },
32
32
  "browserslist": {
33
33
  "production": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartive/graphql-magic",
3
- "version": "19.5.0",
3
+ "version": "19.6.0",
4
4
  "description": "",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
@@ -74,13 +74,13 @@
74
74
  "@types/uuid": "10.0.0",
75
75
  "create-ts-index": "1.14.0",
76
76
  "del-cli": "6.0.0",
77
- "esbuild": "0.25.8",
78
- "eslint": "9.32.0",
77
+ "esbuild": "0.25.9",
78
+ "eslint": "9.33.0",
79
79
  "jest": "29.7.0",
80
80
  "mock-knex": "0.4.13",
81
81
  "prettier": "3.6.2",
82
- "ts-jest": "29.4.0",
82
+ "ts-jest": "29.4.1",
83
83
  "ts-node": "10.9.2",
84
- "typescript": "5.8.3"
84
+ "typescript": "5.9.2"
85
85
  }
86
86
  }
@@ -1,15 +1,18 @@
1
1
  import { makeExecutableSchema } from '@graphql-tools/schema';
2
2
  import { IResolvers } from '@graphql-tools/utils';
3
- import { GraphQLResolveInfo, Source, execute as graphqlExecute, parse } from 'graphql';
3
+ import { GraphQLResolveInfo, Source, execute as graphqlExecute, parse, specifiedRules, validate } from 'graphql';
4
4
  import merge from 'lodash/merge';
5
5
  import { Context, generate, get, getResolvers } from '..';
6
+ import { noIntrospection } from '../utils/rules';
6
7
 
7
8
  export const execute = async ({
8
9
  additionalResolvers,
9
10
  body,
11
+ introspection = false,
10
12
  ...ctx
11
13
  }: {
12
14
  additionalResolvers?: IResolvers<any, any>;
15
+ introspection?: boolean;
13
16
  body: any;
14
17
  } & Omit<Context, 'document'>) => {
15
18
  const document = generate(ctx.models);
@@ -21,6 +24,18 @@ export const execute = async ({
21
24
  resolvers: merge(generatedResolvers, additionalResolvers),
22
25
  });
23
26
 
27
+ const parsedDocument = parse(new Source(body.query, 'GraphQL request'));
28
+
29
+ const validationErrors = validate(
30
+ schema,
31
+ parsedDocument,
32
+ introspection ? specifiedRules : [...specifiedRules, noIntrospection],
33
+ );
34
+
35
+ if (validationErrors.length > 0) {
36
+ return { errors: validationErrors };
37
+ }
38
+
24
39
  const contextValue: Context = {
25
40
  document,
26
41
  ...ctx,
@@ -28,7 +43,7 @@ export const execute = async ({
28
43
 
29
44
  const result = await graphqlExecute({
30
45
  schema,
31
- document: parse(new Source(body.query, 'GraphQL request')),
46
+ document: parsedDocument,
32
47
  contextValue,
33
48
  variableValues: body.variables,
34
49
  operationName: body.operationName,
@@ -0,0 +1,11 @@
1
+ import { ValidationContext } from 'graphql';
2
+ import { ForbiddenError } from '../errors';
3
+
4
+ export const noIntrospection = (context: ValidationContext) => ({
5
+ Field(node) {
6
+ const name = node.name.value;
7
+ if (name === '__schema' || name === '__type') {
8
+ context.reportError(new ForbiddenError('GraphQL introspection is disabled'));
9
+ }
10
+ },
11
+ });