@apollo/utils.stripsensitiveliterals
Advanced tools
Comparing version
@@ -1,3 +0,5 @@ | ||
import { DocumentNode } from "graphql"; | ||
export declare function stripSensitiveLiterals(ast: DocumentNode): DocumentNode; | ||
import type { DocumentNode } from "graphql"; | ||
export declare function stripSensitiveLiterals(ast: DocumentNode, options?: { | ||
hideListAndObjectLiterals?: boolean; | ||
}): DocumentNode; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -5,3 +5,15 @@ "use strict"; | ||
const graphql_1 = require("graphql"); | ||
function stripSensitiveLiterals(ast) { | ||
function stripSensitiveLiterals(ast, options = { | ||
hideListAndObjectLiterals: false, | ||
}) { | ||
const listAndObjectVisitorIfEnabled = options.hideListAndObjectLiterals | ||
? { | ||
ListValue(node) { | ||
return { ...node, values: [] }; | ||
}, | ||
ObjectValue(node) { | ||
return { ...node, fields: [] }; | ||
}, | ||
} | ||
: {}; | ||
return (0, graphql_1.visit)(ast, { | ||
@@ -17,2 +29,3 @@ IntValue(node) { | ||
}, | ||
...listAndObjectVisitorIfEnabled, | ||
}); | ||
@@ -19,0 +32,0 @@ } |
{ | ||
"name": "@apollo/utils.stripsensitiveliterals", | ||
"version": "1.1.0", | ||
"description": "Remove literals from an AST which might contain PII (strings and numbers)", | ||
"version": "1.2.0", | ||
"description": "Remove literals from an AST which might contain PII (strings and numbers, and optionally lists and objects)", | ||
"main": "dist/index.js", | ||
@@ -6,0 +6,0 @@ "types": "dist/index.d.ts", |
import gql from "graphql-tag"; | ||
import { printWithReducedWhitespace } from "@apollo/utils.printwithreducedwhitespace"; | ||
import { stripSensitiveLiterals } from ".."; | ||
import graphQLASTSerializer from "@apollo/utils.jest-graphql-ast-serializer"; | ||
expect.addSnapshotSerializer(graphQLASTSerializer); | ||
const document = gql` | ||
query Foo($b: Int, $a: Boolean) { | ||
user( | ||
name: "hello" | ||
age: 5 | ||
pct: 0.4 | ||
lst: ["a", "b", "c"] | ||
obj: { a: "a", b: 1 } | ||
) { | ||
...Bar | ||
... on User { | ||
hello | ||
bee | ||
} | ||
tz | ||
aliased: name | ||
withInputs( | ||
str: "hi" | ||
int: 2 | ||
flt: 0.3 | ||
lst: ["", "", ""] | ||
obj: { q: "", s: 0 } | ||
) | ||
} | ||
} | ||
fragment Bar on User { | ||
age @skip(if: $a) | ||
...Nested | ||
} | ||
fragment Nested on User { | ||
blah | ||
} | ||
`; | ||
describe("stripSensitiveLiterals", () => { | ||
const cases = [ | ||
{ | ||
name: "full test", | ||
input: gql` | ||
query Foo($b: Int, $a: Boolean) { | ||
user( | ||
name: "hello" | ||
age: 5 | ||
pct: 0.4 | ||
lst: ["a", "b", "c"] | ||
obj: { a: "a", b: 1 } | ||
) { | ||
...Bar | ||
... on User { | ||
hello | ||
bee | ||
} | ||
tz | ||
aliased: name | ||
withInputs( | ||
str: "hi" | ||
int: 2 | ||
flt: 0.3 | ||
lst: ["", "", ""] | ||
obj: { q: "", s: 0 } | ||
) | ||
it("strips only numeric and string literals with default configuration", () => { | ||
expect(stripSensitiveLiterals(document)).toMatchInlineSnapshot(` | ||
query Foo($b: Int, $a: Boolean) { | ||
user(name: "", age: 0, pct: 0, lst: ["", "", ""], obj: {a: "", b: 0}) { | ||
...Bar | ||
... on User { | ||
hello | ||
bee | ||
} | ||
tz | ||
aliased: name | ||
withInputs(str: "", int: 0, flt: 0, lst: ["", "", ""], obj: {q: "", s: 0}) | ||
} | ||
} | ||
fragment Bar on User { | ||
age @skip(if: $a) | ||
...Nested | ||
fragment Bar on User { | ||
age @skip(if: $a) | ||
...Nested | ||
} | ||
fragment Nested on User { | ||
blah | ||
} | ||
`); | ||
}); | ||
it("strips only numeric and string literals with empty (but defined) configuration", () => { | ||
expect(stripSensitiveLiterals(document, {})).toMatchInlineSnapshot(` | ||
query Foo($b: Int, $a: Boolean) { | ||
user(name: "", age: 0, pct: 0, lst: ["", "", ""], obj: {a: "", b: 0}) { | ||
...Bar | ||
... on User { | ||
hello | ||
bee | ||
} | ||
tz | ||
aliased: name | ||
withInputs(str: "", int: 0, flt: 0, lst: ["", "", ""], obj: {q: "", s: 0}) | ||
} | ||
} | ||
fragment Nested on User { | ||
blah | ||
fragment Bar on User { | ||
age @skip(if: $a) | ||
...Nested | ||
} | ||
fragment Nested on User { | ||
blah | ||
} | ||
`); | ||
}); | ||
it("strips only numeric and string literals with hideListAndObjectLiterals: false", () => { | ||
expect( | ||
stripSensitiveLiterals(document, { hideListAndObjectLiterals: false }), | ||
).toMatchInlineSnapshot(` | ||
query Foo($b: Int, $a: Boolean) { | ||
user(name: "", age: 0, pct: 0, lst: ["", "", ""], obj: {a: "", b: 0}) { | ||
...Bar | ||
... on User { | ||
hello | ||
bee | ||
} | ||
tz | ||
aliased: name | ||
withInputs(str: "", int: 0, flt: 0, lst: ["", "", ""], obj: {q: "", s: 0}) | ||
} | ||
`, | ||
output: | ||
'query Foo($b:Int,$a:Boolean){user(name:"",age:0,pct:0,lst:["","",""],obj:{a:"",b:0}){...Bar...on User{hello bee}tz aliased:name ' + | ||
'withInputs(str:"",int:0,flt:0,lst:["","",""],obj:{q:"",s:0})}}' + | ||
"fragment Bar on User{age@skip(if:$a)...Nested}fragment Nested on User{blah}", | ||
}, | ||
]; | ||
cases.forEach(({ name, input, output }) => { | ||
test(name, () => { | ||
expect(printWithReducedWhitespace(stripSensitiveLiterals(input))).toEqual( | ||
output, | ||
); | ||
}); | ||
} | ||
fragment Bar on User { | ||
age @skip(if: $a) | ||
...Nested | ||
} | ||
fragment Nested on User { | ||
blah | ||
} | ||
`); | ||
}); | ||
it("strips all literals with hideListAndObjectLiterals: true", () => { | ||
expect( | ||
stripSensitiveLiterals(document, { hideListAndObjectLiterals: true }), | ||
).toMatchInlineSnapshot(` | ||
query Foo($b: Int, $a: Boolean) { | ||
user(name: "", age: 0, pct: 0, lst: [], obj: {}) { | ||
...Bar | ||
... on User { | ||
hello | ||
bee | ||
} | ||
tz | ||
aliased: name | ||
withInputs(str: "", int: 0, flt: 0, lst: [], obj: {}) | ||
} | ||
} | ||
fragment Bar on User { | ||
age @skip(if: $a) | ||
...Nested | ||
} | ||
fragment Nested on User { | ||
blah | ||
} | ||
`); | ||
}); | ||
}); |
{ | ||
"extends": "../../../../tsconfig.test.base", | ||
"include": ["**/*"], | ||
"references": [{ "path": "../../" }] | ||
"references": [ | ||
{ | ||
"path": "../../" | ||
}, | ||
{ | ||
"path": "../../../jestGraphQLASTSerializer" | ||
} | ||
] | ||
} |
@@ -1,11 +0,31 @@ | ||
import { | ||
import type { | ||
ASTVisitor, | ||
DocumentNode, | ||
FloatValueNode, | ||
IntValueNode, | ||
ListValueNode, | ||
ObjectValueNode, | ||
StringValueNode, | ||
visit, | ||
} from "graphql"; | ||
// In the same spirit as the similarly named `hideLiterals` function, only | ||
// hide sensitive (string and numeric) literals. | ||
export function stripSensitiveLiterals(ast: DocumentNode): DocumentNode { | ||
import { visit } from "graphql"; | ||
// Hide sensitive string and numeric literals. Optionally hide list and object literals with the option `hideListAndObjectLiterals: true`. | ||
export function stripSensitiveLiterals( | ||
ast: DocumentNode, | ||
options: { hideListAndObjectLiterals?: boolean } = { | ||
hideListAndObjectLiterals: false, | ||
}, | ||
): DocumentNode { | ||
const listAndObjectVisitorIfEnabled: ASTVisitor = | ||
options.hideListAndObjectLiterals | ||
? { | ||
ListValue(node: ListValueNode): ListValueNode { | ||
return { ...node, values: [] }; | ||
}, | ||
ObjectValue(node: ObjectValueNode): ObjectValueNode { | ||
return { ...node, fields: [] }; | ||
}, | ||
} | ||
: {}; | ||
return visit(ast, { | ||
@@ -21,3 +41,4 @@ IntValue(node): IntValueNode { | ||
}, | ||
...listAndObjectVisitorIfEnabled, | ||
}); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
8969
64.48%223
120.79%