@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 +2 -2
- package/dist/bin/gqm.cjs +4 -4
- package/dist/cjs/index.cjs +53 -31
- package/dist/esm/api/execute.d.ts +2 -1
- package/dist/esm/api/execute.js +9 -3
- package/dist/esm/api/execute.js.map +1 -1
- package/dist/esm/utils/rules.d.ts +4 -0
- package/dist/esm/utils/rules.js +10 -0
- package/dist/esm/utils/rules.js.map +1 -0
- package/docs/package-lock.json +4 -4
- package/docs/package.json +1 -1
- package/package.json +5 -5
- package/src/api/execute.ts +17 -2
- package/src/utils/rules.ts +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# [19.
|
|
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
|
-
*
|
|
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
|
|
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);
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -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
|
|
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,
|
|
267
|
+
const result = await (0, import_graphql2.execute)({
|
|
218
268
|
schema,
|
|
219
|
-
document:
|
|
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>>>;
|
package/dist/esm/api/execute.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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;
|
|
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,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"}
|
package/docs/package-lock.json
CHANGED
|
@@ -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.
|
|
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.
|
|
16016
|
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.
|
|
16017
|
-
"integrity": "sha512-
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartive/graphql-magic",
|
|
3
|
-
"version": "19.
|
|
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.
|
|
78
|
-
"eslint": "9.
|
|
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.
|
|
82
|
+
"ts-jest": "29.4.1",
|
|
83
83
|
"ts-node": "10.9.2",
|
|
84
|
-
"typescript": "5.
|
|
84
|
+
"typescript": "5.9.2"
|
|
85
85
|
}
|
|
86
86
|
}
|
package/src/api/execute.ts
CHANGED
|
@@ -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:
|
|
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
|
+
});
|