Skip to content

Commit 60d08e9

Browse files
1.0.0
0 parents  commit 60d08e9

22 files changed

Lines changed: 5988 additions & 0 deletions

.eslintrc.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = {
2+
parser: '@typescript-eslint/parser',
3+
env: {
4+
es2021: true,
5+
'jest/globals': true,
6+
},
7+
extends: ['plugin:@typescript-eslint/recommended'],
8+
parserOptions: {
9+
ecmaVersion: 2019,
10+
sourceType: 'module',
11+
},
12+
rules: {},
13+
};

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.yarn/*
2+
!.yarn/releases
3+
!.yarn/plugins
4+
!.yarn/versions
5+
.pnp.*
6+
node_modules
7+
.npmrc
8+
coverage
9+
merge-2.spec.ts

.prettierrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"printWidth": 80,
5+
"tabWidth": 2,
6+
"useTabs": false,
7+
"trailingComma": "es5",
8+
"bracketSpacing": true
9+
}

.yarn/releases/yarn-3.6.4.cjs

Lines changed: 874 additions & 0 deletions
Large diffs are not rendered by default.

.yarnrc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
nodeLinker: node-modules
2+
3+
yarnPath: .yarn/releases/yarn-3.6.4.cjs

dist/__tests__/merge-2.spec.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {};

dist/__tests__/merge-2.spec.js

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
const merge_1 = require("../merge");
4+
describe('mergeQueries', () => {
5+
test('should handle complex typegraphql-prisma queries', () => {
6+
const requestQuery = `query FindAdminTalentProfile($where: TalentProfileWhereUniqueInput!) {
7+
data: findAdminTalentProfile(where: $where) {
8+
id
9+
profileName
10+
description
11+
education
12+
email
13+
user {
14+
email
15+
phoneNumber
16+
lastVisit
17+
__typename
18+
}
19+
__typename
20+
}
21+
}`;
22+
const allowedQueries = [
23+
`query FindAdminTalentProfile($where: TalentProfileWhereUniqueInput!) {
24+
data: findAdminTalentProfile(where: $where) {
25+
id
26+
profileName
27+
description
28+
education
29+
email
30+
user {
31+
email
32+
phoneNumber
33+
lastVisit
34+
__typename
35+
}
36+
__typename
37+
}
38+
}`,
39+
`query groupByLocationsTalentProfiles($by: [TalentProfileScalarFieldEnum!]!, $orderBy: [TalentProfileOrderByWithAggregationInput!]) {
40+
data: groupByTalentProfiles(by: $by, orderBy: $orderBy) {
41+
location
42+
_count {
43+
location
44+
__typename
45+
}
46+
__typename
47+
}
48+
}`,
49+
`query FindUser($where: CompanyOnUserWhereInput) {
50+
data: findMe {
51+
redirect
52+
companies(where: $where) {
53+
company {
54+
id
55+
deletedAt
56+
address
57+
logo
58+
name
59+
verificationStatus
60+
__typename
61+
}
62+
__typename
63+
}
64+
profile {
65+
id
66+
userId
67+
jobTitle
68+
profileName
69+
profilePicture
70+
isAvailableForHire
71+
isInterestedInRelocation
72+
languages
73+
location
74+
rateCurrency
75+
skills
76+
totalExperience
77+
description
78+
experience
79+
education
80+
monthlyRate
81+
hourlyRate
82+
__typename
83+
}
84+
__typename
85+
}
86+
}`,
87+
];
88+
const expected = `query FindAdminTalentProfile($where: TalentProfileWhereUniqueInput!) {
89+
data: findAdminTalentProfile(where: $where) {
90+
id
91+
profileName
92+
description
93+
education
94+
email
95+
user {
96+
email
97+
phoneNumber
98+
lastVisit
99+
__typename
100+
}
101+
__typename
102+
}
103+
}`;
104+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
105+
});
106+
test('should handle request trying to query much more than allowed', () => {
107+
const requestQuery = `query {
108+
user {
109+
id
110+
name
111+
email
112+
profile {
113+
bio
114+
address
115+
phoneNumber
116+
website
117+
skills
118+
experiences {
119+
title
120+
company
121+
startDate
122+
endDate
123+
}
124+
}
125+
}
126+
}`;
127+
const allowedQueries = [
128+
`{
129+
user {
130+
id
131+
name
132+
}
133+
}`,
134+
];
135+
const expected = `{
136+
user {
137+
id
138+
name
139+
}
140+
}`;
141+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
142+
});
143+
});

dist/__tests__/merge.spec.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {};

dist/__tests__/merge.spec.js

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
const merge_1 = require("../merge");
4+
describe('mergeQueries', () => {
5+
test('should allow fields present in allowed queries', () => {
6+
const requestQuery = `{ user { id, name, email } }`;
7+
const allowedQueries = [`{ user { id, name } }`];
8+
const expected = `{
9+
user {
10+
id
11+
name
12+
}
13+
}`;
14+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
15+
});
16+
test('should exclude fields not present in allowed queries', () => {
17+
const requestQuery = `{ user { id, name, email } }`;
18+
const allowedQueries = [`{ user { id } }`];
19+
const expected = `{
20+
user {
21+
id
22+
}
23+
}`;
24+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
25+
});
26+
test('should handle nested queries', () => {
27+
const requestQuery = `{ user { id, profile { name, age } } }`;
28+
const allowedQueries = [`{ user { profile { name } } }`];
29+
const expected = `{
30+
user {
31+
profile {
32+
name
33+
}
34+
}
35+
}`;
36+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
37+
});
38+
test('should handle queries with arguments', () => {
39+
const requestQuery = `{ users(age: 30) { id, name } }`;
40+
const allowedQueries = [`{ users { name } }`];
41+
const expected = `{
42+
users(age: 30) {
43+
name
44+
}
45+
}`;
46+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
47+
});
48+
test('should strictly follow allowed queries with aliases', () => {
49+
const requestQuery = `{ user: users { id, name } }`;
50+
const allowedQueries = [`{ user: users { name } }`];
51+
const expected = `{
52+
user: users {
53+
name
54+
}
55+
}`;
56+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
57+
});
58+
test('should strictly follow allowed queries without aliases', () => {
59+
const requestQuery = `{ users { id, name } }`;
60+
const allowedQueries = [`{ users { name } }`];
61+
const expected = `{
62+
users {
63+
name
64+
}
65+
}`;
66+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
67+
});
68+
test('should handle mutations', () => {
69+
const requestQuery = `mutation { updateUser(id: 1, data: { name: "New Name" }) { id, name } }`;
70+
const allowedQueries = [
71+
`mutation { updateUser(id: 1, data: { name: "New Name" }) { name } }`,
72+
];
73+
const expected = `mutation {
74+
updateUser(id: 1, data: {name: "New Name"}) {
75+
name
76+
}
77+
}`;
78+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
79+
});
80+
test('should handle multiple allowed queries', () => {
81+
const requestQuery = `{ user { id, name, email } }`;
82+
const allowedQueries = [`{ user { id } }`, `{ user { name } }`];
83+
const expected = `{
84+
user {
85+
id
86+
name
87+
}
88+
}`;
89+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
90+
});
91+
test('should handle empty requestQuery', () => {
92+
const requestQuery = '';
93+
const allowedQueries = [`{ user { id, name } }`];
94+
const expected = '';
95+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
96+
});
97+
test('should handle empty allowedQueries', () => {
98+
const requestQuery = `{ user { id, name, email } }`;
99+
const allowedQueries = [];
100+
const expected = '';
101+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
102+
});
103+
test('should handle mutations', () => {
104+
const requestQuery = `mutation { updateUser(id: 1, data: { name: "New Name" }) { id, name } }`;
105+
const allowedQueries = [
106+
`mutation { updateUser(id: 1, data: { name: "New Name" }) { name } }`,
107+
];
108+
const expected = `mutation {
109+
updateUser(id: 1, data: {name: "New Name"}) {
110+
name
111+
}
112+
}`;
113+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
114+
});
115+
test('should handle deeply nested queries', () => {
116+
const requestQuery = `{ user { id, profile { name, address { street, city } } } }`;
117+
const allowedQueries = [`{ user { profile { address { street } } } }`];
118+
const expected = `{
119+
user {
120+
profile {
121+
address {
122+
street
123+
}
124+
}
125+
}
126+
}`;
127+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
128+
});
129+
test('should handle nested mutations', () => {
130+
const requestQuery = `mutation { updateUser(id: 1, data: { profile: { name: "New Name" } }) { id } }`;
131+
const allowedQueries = [
132+
`mutation { updateUser(id: 1, data: { profile: { name: "New Name" } }) { id } }`,
133+
];
134+
const expected = `mutation {
135+
updateUser(id: 1, data: {profile: {name: "New Name"}}) {
136+
id
137+
}
138+
}`;
139+
expect((0, merge_1.mergeQueries)(requestQuery, allowedQueries)).toBe(expected);
140+
});
141+
});

dist/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NextFunction, Request, Response } from 'express';
2+
export declare class GraphQLQueryPurifier {
3+
private gqlPath;
4+
private queryMap;
5+
constructor(gqlPath: string);
6+
private loadQueries;
7+
customGraphQLMiddleware: (req: Request, res: Response, next: NextFunction) => void;
8+
}

0 commit comments

Comments
 (0)