New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

graphql-fields-list

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-fields-list - npm Package Compare versions

Comparing version 2.0.0 to 2.1.1

debug.d.ts

32

index.d.ts

@@ -41,5 +41,37 @@ /*!

export interface FieldsListOptions {
/**
* Path to a tree branch which should be mapped during fields extraction
* @type {string}
*/
path?: string;
/**
* Transformation rules which should be used to re-name field names
* @type {FieldNamesMap}
*/
transform?: FieldNamesMap;
/**
* Flag which turns on/off GraphQL directives checks on a fields
* and take them into account during fields analysis
* @type {boolean}
*/
withDirectives?: boolean;
/**
* Fields skip rule patterns. Usually used to ignore part of request field
* subtree. For example if query looks like:
* profiles {
* id
* users {
* name
* email
* password
* }
* }
* and you doo n not care about users, it can be done like:
* fieldsList(info, { skip: ['users'] }); // or
* fieldsProjection(info, { skip: ['users.*'] }); // more obvious notation
*
* If you want to skip only exact fields, it can be done as:
* fieldsMap(info, { skip: ['users.email', 'users.password'] })
*/
skip?: string[];
}

@@ -46,0 +78,0 @@ /**

79

index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Pre-compiled wildcard replacement regexp
*
* @type {RegExp}
*/
const RX_AST = /\*/g;
/**
* Retrieves a list of nodes from a given selection (either fragment or

@@ -96,8 +102,9 @@ * selection node)

* @param {*} root
* @param {*} skip
* @param {TraverseOptions} opts
*/
function verifyInlineFragment(node, root, opts) {
function verifyInlineFragment(node, root, opts, skip) {
if (node.kind === 'InlineFragment') {
const nodes = getNodes(node);
nodes.length && traverse(nodes, root, opts);
nodes.length && traverse(nodes, root, opts, skip);
return true;

@@ -108,2 +115,51 @@ }

/**
* Builds skip rules tree from a given skip option argument
*
* @param {string[]} skip - skip option arguments
* @return {any} - skip rules tree
*/
function skipTree(skip) {
const tree = {};
for (const pattern of skip) {
const props = pattern.split('.');
let propTree = tree;
for (let i = 0, s = props.length; i < s; i++) {
const prop = props[i];
const all = props[i + 1] === '*';
if (!propTree[prop]) {
propTree[prop] = i === s - 1 || all ? true : {};
all && i++;
}
propTree = propTree[prop];
}
}
return tree;
}
/**
*
* @param node
* @param skip
*/
function verifySkip(node, skip) {
if (!skip) {
return false;
}
if (skip[node]) {
return skip[node];
}
// lookup through wildcard patterns
let nodeTree = false;
const patterns = Object.keys(skip).filter(pattern => ~pattern.indexOf('*'));
for (const pattern of patterns) {
const rx = new RegExp(pattern.replace(RX_AST, '.*'));
if (rx.test(node)) {
nodeTree = skip[pattern];
if (nodeTree === true) {
break;
}
}
}
return nodeTree;
}
/**
* Traverses recursively given nodes and fills-up given root tree with

@@ -115,6 +171,7 @@ * a requested field names

* @param {TraverseOptions} opts
* @param {*} skip
* @return {*}
* @access private
*/
function traverse(nodes, root, opts) {
function traverse(nodes, root, opts, skip) {
for (const node of nodes) {

@@ -124,3 +181,3 @@ if (opts.withVars && !verifyDirectives(node.directives, opts.vars)) {

}
if (verifyInlineFragment(node, root, opts)) {
if (verifyInlineFragment(node, root, opts, skip)) {
continue;

@@ -130,8 +187,11 @@ }

if (opts.fragments[name]) {
traverse(getNodes(opts.fragments[name]), root, opts);
traverse(getNodes(opts.fragments[name]), root, opts, skip);
continue;
}
const nodes = getNodes(node);
root[name] = root[name] || (nodes.length ? {} : false);
nodes.length && traverse(nodes, root[name], opts);
const nodeSkip = verifySkip(name, skip);
if (nodeSkip !== true) {
root[name] = root[name] || (nodes.length ? {} : false);
nodes.length && traverse(nodes, root[name], opts, nodeSkip);
}
}

@@ -222,3 +282,3 @@ return root;

}
const { path, withDirectives } = parseOptions(options);
const { path, withDirectives, skip } = parseOptions(options);
const tree = traverse(getNodes(fieldNode), {}, {

@@ -228,3 +288,3 @@ fragments: info.fragments,

withVars: withDirectives,
});
}, skipTree(skip || []));
return getBranch(tree, path);

@@ -310,2 +370,3 @@ }

verifyInlineFragment,
verifySkip,
parseOptions,

@@ -312,0 +373,0 @@ toDotNotation,

26

package.json
{
"name": "graphql-fields-list",
"version": "2.0.0",
"version": "2.1.1",
"description": "Extracts and returns list of fields requested from graphql resolver info object",

@@ -42,21 +42,21 @@ "scripts": {

"devDependencies": {
"@types/chai": "^4.1.6",
"@types/graphql": "^14.0.3",
"@types/graphql-relay": "^0.4.8",
"@types/chai": "^4.1.7",
"@types/graphql": "^14.0.5",
"@types/graphql-relay": "^0.4.9",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.0",
"@types/sinon": "^5.0.5",
"@types/node": "^11.9.0",
"@types/sinon": "^7.0.5",
"@types/uuid": "^3.4.4",
"chai": "^4.2.0",
"coveralls": "^3.0.2",
"graphql": "^14.0.2",
"graphql-relay": "^0.5.5",
"graphql": "^14.1.1",
"graphql-relay": "^0.6.0",
"mocha": "^5.2.0",
"npm-scripts-help": "^0.8.0",
"nyc": "^13.1.0",
"nyc": "^13.2.0",
"opn": "^5.4.0",
"sinon": "^7.0.0",
"ts-node": "^7.0.1",
"typedoc": "^0.13.0",
"typescript": "^3.1.3",
"sinon": "^7.2.3",
"ts-node": "^8.0.2",
"typedoc": "^0.14.2",
"typescript": "^3.3.3",
"uuid": "^3.3.2"

@@ -63,0 +63,0 @@ },

@@ -286,4 +286,58 @@ # graphql-fields-list

**Since version 2.1.0**
It supports `skip` option to filter output of `fieldsList()`, `fieldsMap()` and
`fieldsProjection()` functions.
[See motivation](https://github.com/Mikhus/graphql-fields-list/issues/4)
Skip option accepts an array of field projections to skip. It allows usage
of wildcard symbol `*` within field names. Please, note, that skip occurs
before transformations, so it should reflect original field names,
transformations would be applied after skip is done.
Typical usage as:
```javascript
const map = fieldsMap(info, { skip: [
'users.pageInfo.*',
'users.edges.node.email',
'users.edges.node.address',
'users.edges.node.*Name',
]});
/*
RESULT:
map = {
users: {
edges: {
node: {
id: false,
phoneNumber: false,
},
},
},
}
*/
const projection = fieldsProjection(info, {
skip: [
'users.pageInfo.*',
'users.edges.node.email',
'users.edges.node.address',
'users.edges.node.*Name',
],
transform: {
'users.edges.node.id': 'users.edges.node._id',
},
});
/*
RESULT:
projection = {
'users.edges.node._id': 1,
'users.edges.node.phoneNumber': 1,
};
*/
```
## License
[ISC Licence](LICENSE)
[ISC Licence](LICENSE)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc