From 433b1766f9413113b91470b46c1fa815f9e8eb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivo=20Mei=C3=9Fner?= Date: Mon, 23 Sep 2019 07:36:22 +0200 Subject: [PATCH 1/2] Upgrade dependencies --- yarn.lock | 438 ++++++++++++++++++++++++------------------------------ 1 file changed, 192 insertions(+), 246 deletions(-) diff --git a/yarn.lock b/yarn.lock index c746d87..667c208 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,14 +3,14 @@ "@babel/code-frame@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" dependencies: "@babel/highlight" "^7.0.0" "@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -21,59 +21,57 @@ resolved "http://registry.npmjs.org/@types/assert/-/assert-0.0.31.tgz#d1f70595a72d02555b7ecd28eb4c68f1b6918d6d" "@types/chai@^4.1.4": - version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.6.tgz#1eb26c040e3a84205b1008ad55c800e5e8a94e34" + version "4.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.3.tgz#419477a3d5202bad19e14c787940a61dc9ea6407" "@types/graphql@^0.13.0 || ^14.0.0": version "14.0.2" resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-14.0.2.tgz#415e3779718c1e0805e418e3a798cb39dccc58ab" "@types/lodash.get@^4.4.4": - version "4.4.4" - resolved "https://registry.yarnpkg.com/@types/lodash.get/-/lodash.get-4.4.4.tgz#34b67841594e4ddc8853341d65e971a38cb4e2f0" + version "4.4.6" + resolved "https://registry.yarnpkg.com/@types/lodash.get/-/lodash.get-4.4.6.tgz#0c7ac56243dae0f9f09ab6f75b29471e2e777240" dependencies: "@types/lodash" "*" "@types/lodash@*": - version "4.14.116" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.116.tgz#5ccf215653e3e8c786a58390751033a9adca0eb9" + version "4.14.138" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.138.tgz#34f52640d7358230308344e579c15b378d91989e" "@types/mocha@^5.2.5": - version "5.2.5" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073" + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" -acorn-jsx@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" - dependencies: - acorn "^5.0.3" +acorn-jsx@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" -acorn@^5.0.3, acorn@^5.6.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - -ajv-keywords@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" +acorn@^6.0.7: + version "6.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" -ajv@^6.0.1, ajv@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" +ajv@^6.10.2, ajv@^6.9.1: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" -ansi-styles@^3.2.1: +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: @@ -85,16 +83,6 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -103,6 +91,10 @@ assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -122,15 +114,9 @@ buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" chai@^4.1.0: version "4.2.0" @@ -143,9 +129,9 @@ chai@^4.1.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.1.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -159,10 +145,6 @@ check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -208,8 +190,8 @@ debug@3.1.0: ms "2.0.0" debug@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" dependencies: ms "^2.1.1" @@ -223,28 +205,20 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - diff@3.5.0, diff@^3.1.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" dependencies: esutils "^2.0.2" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -255,70 +229,71 @@ eslint-plugin-typescript@^0.12.0: dependencies: requireindex "~1.1.0" -eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" eslint-utils@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" + version "1.4.2" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" + dependencies: + eslint-visitor-keys "^1.0.0" eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" eslint@^5.4.0: - version "5.6.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.6.1.tgz#348134e32ccc09abb2df1bf282b3f6eed8c7b480" + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.5.3" + ajv "^6.9.1" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" - doctrine "^2.1.0" - eslint-scope "^4.0.0" + doctrine "^3.0.0" + eslint-scope "^4.0.3" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^4.0.0" + espree "^5.0.1" esquery "^1.0.1" esutils "^2.0.2" - file-entry-cache "^2.0.0" + file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" glob "^7.1.2" globals "^11.7.0" ignore "^4.0.6" + import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.1.0" - is-resolvable "^1.1.0" - js-yaml "^3.12.0" + inquirer "^6.2.2" + js-yaml "^3.13.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.5" + lodash "^4.17.11" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^7.0.0" progress "^2.0.0" - regexpp "^2.0.0" - require-uncached "^1.0.3" + regexpp "^2.0.1" semver "^5.5.1" strip-ansi "^4.0.0" strip-json-comments "^2.0.1" - table "^4.0.3" + table "^5.2.3" text-table "^0.2.0" -espree@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" dependencies: - acorn "^5.6.0" - acorn-jsx "^4.1.1" + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" esprima@^4.0.0: version "4.0.1" @@ -337,16 +312,16 @@ esrecurse@^4.1.0: estraverse "^4.1.0" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" -external-editor@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -370,21 +345,23 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" + flat-cache "^2.0.1" -flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" fs.realpath@^1.0.0: version "1.0.0" @@ -409,9 +386,9 @@ glob@7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" +glob@^7.1.2, glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -421,23 +398,8 @@ glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: path-is-absolute "^1.0.0" globals@^11.7.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" "graphql@^0.13.0 || ^14.0.0": version "14.0.2" @@ -467,6 +429,13 @@ ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" +import-fresh@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -479,55 +448,35 @@ inflight@^1.0.4: wrappy "1" inherits@2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" -inquirer@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" + ansi-escapes "^3.2.0" + chalk "^2.4.2" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^3.0.0" + external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.10" + lodash "^4.17.12" mute-stream "0.0.7" run-async "^2.2.0" - rxjs "^6.1.0" + rxjs "^6.4.0" string-width "^2.1.0" - strip-ansi "^4.0.0" + strip-ansi "^5.1.0" through "^2.3.6" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - dependencies: - path-is-inside "^1.0.1" - is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -540,9 +489,9 @@ js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" -js-yaml@^3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" +js-yaml@^3.13.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -570,9 +519,9 @@ lodash.unescape@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" -lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" make-error@^1.1.1: version "1.3.5" @@ -590,7 +539,7 @@ minimatch@3.0.4, minimatch@^3.0.4: minimist@0.0.8: version "0.0.8" - resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" minimist@^1.2.0: version "1.2.0" @@ -623,8 +572,8 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" mute-stream@0.0.7: version "0.0.7" @@ -638,10 +587,6 @@ nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" -object-assign@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -669,11 +614,17 @@ os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + dependencies: + callsites "^3.0.0" + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -685,54 +636,29 @@ pathval@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" -regexpp@^2.0.0: +regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - requireindex@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162" -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" restore-cursor@^2.0.0: version "2.0.0" @@ -741,11 +667,17 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" -rimraf@^2.2.8, rimraf@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" dependencies: - glob "^7.0.5" + glob "^7.1.3" + +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + dependencies: + glob "^7.1.3" run-async@^2.2.0: version "2.3.0" @@ -753,9 +685,9 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" -rxjs@^6.1.0: - version "6.3.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" +rxjs@^6.4.0: + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" dependencies: tslib "^1.9.0" @@ -768,8 +700,8 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" semver@^5.5.0, semver@^5.5.1: - version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" shebang-command@^1.2.0: version "1.2.0" @@ -785,10 +717,12 @@ signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" source-map-support@^0.5.6: @@ -806,19 +740,33 @@ sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -string-width@^2.1.0, string-width@^2.1.1: +string-width@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + dependencies: + ansi-regex "^4.1.0" + strip-json-comments@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -835,16 +783,14 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -table@^4.0.3: - version "4.0.3" - resolved "http://registry.npmjs.org/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" dependencies: - ajv "^6.0.1" - ajv-keywords "^3.0.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" text-table@^0.2.0: version "0.2.0" @@ -852,7 +798,7 @@ text-table@^0.2.0: through@^2.3.6: version "2.3.8" - resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" tmp@^0.0.33: version "0.0.33" @@ -874,8 +820,8 @@ ts-node@^7.0.1: yn "^2.0.0" tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" type-check@~0.3.2: version "0.3.2" @@ -895,8 +841,8 @@ typescript-eslint-parser@^18.0.0: semver "5.5.0" typescript@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96" + version "3.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.3.tgz#fea942fabb20f7e1ca7164ff626f1a9f3f70b4da" uri-js@^4.2.2: version "4.2.2" @@ -918,9 +864,9 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" dependencies: mkdirp "^0.5.1" From 0ef07a47a620b0e045be69efa9945ce0e5f64c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivo=20Mei=C3=9Fner?= Date: Mon, 23 Sep 2019 08:42:36 +0200 Subject: [PATCH 2/2] Add fieldExtensionsEstimator, deprecate fieldConfigEstimator #19 --- README.md | 6 +- src/estimators/fieldConfig/index.ts | 7 + src/estimators/fieldExtensions/README.md | 97 ++++++ .../fieldExtensionsEstimator-test.ts | 313 ++++++++++++++++++ .../__tests__/fixtures/schema.ts | 151 +++++++++ src/estimators/fieldExtensions/index.ts | 14 + src/estimators/index.ts | 1 + yarn.lock | 12 +- 8 files changed, 594 insertions(+), 7 deletions(-) create mode 100644 src/estimators/fieldExtensions/README.md create mode 100644 src/estimators/fieldExtensions/__tests__/fieldExtensionsEstimator-test.ts create mode 100644 src/estimators/fieldExtensions/__tests__/fixtures/schema.ts create mode 100644 src/estimators/fieldExtensions/index.ts diff --git a/README.md b/README.md index c0e49f5..2707c29 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,11 @@ or write your own: last estimator in the chain for a default value. * **[`directiveEstimator`](src/estimators/directive/README.md):** Set the complexity via a directive in your schema definition (for example via GraphQL SDL) -* **[`fieldConfigEstimator`](src/estimators/fieldConfig/README.md):** The field config estimator lets you set a numeric value or a custom estimator +* **[`fieldExtensionsEstimator`](src/estimators/fieldExtensions/README.md):** The field extensions estimator lets you set a numeric value or a custom estimator + function in the field config extensions of your schema. +* **[`fieldConfigEstimator`](src/estimators/fieldConfig/README.md):** (DEPRECATED) The field config estimator lets you set a numeric value or a custom estimator function in the field config of your schema. -* **[`legacyEstimator`](src/estimators/legacy/README.md):** The legacy estimator implements the logic of previous versions. Can be used +* **[`legacyEstimator`](src/estimators/legacy/README.md):** (DEPRECATED) The legacy estimator implements the logic of previous versions. Can be used to gradually migrate your codebase to new estimators. * PRs welcome... diff --git a/src/estimators/fieldConfig/index.ts b/src/estimators/fieldConfig/index.ts index d48606f..407b9b8 100644 --- a/src/estimators/fieldConfig/index.ts +++ b/src/estimators/fieldConfig/index.ts @@ -1,6 +1,13 @@ import {ComplexityEstimator, ComplexityEstimatorArgs} from '../../QueryComplexity'; +/** + * @deprecated Use fieldExtensionsEstimator instead + */ export default function (): ComplexityEstimator { + console.warn( + 'DEPRECATION WARNING: fieldConfigEstimator is deprecated. Use fieldExtensionsEstimator instead' + ); + return (args: ComplexityEstimatorArgs) => { // Calculate complexity score if (typeof args.field.complexity === 'number') { diff --git a/src/estimators/fieldExtensions/README.md b/src/estimators/fieldExtensions/README.md new file mode 100644 index 0000000..89dead9 --- /dev/null +++ b/src/estimators/fieldExtensions/README.md @@ -0,0 +1,97 @@ +# Field Extensions Estimator + +The `fieldExtensionsEstimator` lets you define a numeric value or a custom estimator +in the field config extensions of your GraphQL schema. If no complexity is set in the field config, +the estimator does not return any value and the next estimator in the chain is executed. + +## Usage + +```typescript +import queryComplexity, { + fieldExtensionsEstimator, + simpleEstimator +} from 'graphql-query-complexity'; + +const rule = queryComplexity({ + estimators: [ + fieldExtensionsEstimator(), + + // We use the simpleEstimator as fallback so we only need to + // define the complexity for non 1 values (this is not required...) + simpleEstimator({defaultComplexity: 1}) + ] + // ... other config +}); +``` + +You can set a custom complexity as a numeric value in the field config: + +```javascript +const Post = new GraphQLObjectType({ + name: 'Post', + fields: () => ({ + title: { type: GraphQLString }, + text: { + type: GraphQLString, + extensions: { + complexity: 5 + }, + }, + }), +}); +``` + +**Example Query:** + +```graphql +query { + posts(count: 10) { + title + text + } +} +``` + +This query would result in a complexity of 7. +5 for the `text` field and 1 for each of the other fields. + +You can also pass an estimator in the field config to determine a custom complexity. +This function will provide the complexity of the child nodes as well as the field input arguments. + +The function signature is the same as for the main estimator which lets you reuse estimators: + +```typescript +type ComplexityEstimatorArgs = { + type: GraphQLCompositeType, + field: GraphQLField, + args: {[key: string]: any}, + childComplexity: number +} + +type ComplexityEstimator = (options: ComplexityEstimatorArgs) => number | void; +``` + +That way you can make a more realistic estimation of individual field complexity values: + +```javascript +const Query = new GraphQLObjectType({ + name: 'Query', + fields: () => ({ + posts: { + type: new GraphQLList(Post), + args: { + count: { + type: GraphQLInt, + defaultValue: 10 + } + }, + extensions: { + complexity: ({args, childComplexity}) => childComplexity * args.count, + }, + }, + }), +}); +``` + +This would result in a complexity of 60 since the `childComplexity` of posts (`text` 5, `title` 1) is multiplied by the +number of posts (`args.count`). diff --git a/src/estimators/fieldExtensions/__tests__/fieldExtensionsEstimator-test.ts b/src/estimators/fieldExtensions/__tests__/fieldExtensionsEstimator-test.ts new file mode 100644 index 0000000..7130bb9 --- /dev/null +++ b/src/estimators/fieldExtensions/__tests__/fieldExtensionsEstimator-test.ts @@ -0,0 +1,313 @@ +/** + * Created by Ivo Meißner on 28.07.17. + */ + +import { + parse, + TypeInfo, + ValidationContext, + visit, + visitWithTypeInfo, +} from 'graphql'; + +import {expect} from 'chai'; + +import schema from './fixtures/schema'; + +import ComplexityVisitor from '../../../QueryComplexity'; +import simpleEstimator from '../../simple'; +import fieldExtensionsEstimator from '../index'; + +describe('fieldExtensions estimator', () => { + const typeInfo = new TypeInfo(schema); + + it('should consider default scalar cost', () => { + const ast = parse(` + query { + scalar + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(1); + }); + + it('should consider custom scalar cost', () => { + const ast = parse(` + query { + complexScalar + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(20); + }); + + it('should consider variable scalar cost', () => { + const ast = parse(` + query { + variableScalar(count: 100) + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(1000); + }); + + it('should not allow negative cost', () => { + const ast = parse(` + query { + variableScalar(count: -100) + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(0); + }); + + it('should report error above threshold', () => { + const ast = parse(` + query { + variableScalar(count: 100) + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(1000); + expect(context.getErrors().length).to.equal(1); + expect(context.getErrors()[0].message).to.equal( + 'The query exceeds the maximum complexity of 100. Actual complexity is 1000' + ); + }); + + it('should add inline fragments', () => { + const ast = parse(` + query { + variableScalar(count: 5) + ...on Query { + scalar + alias: scalar + } + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(52); + }); + + it('should add fragments', () => { + const ast = parse(` + query { + scalar + ...QueryFragment + } + + fragment QueryFragment on Query { + variableScalar(count: 2) + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(21); + }); + + it('should add complexity for union types', () => { + const ast = parse(` + query { + union { + ...on Item { + scalar + complexScalar + } + } + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(22); + }); + + it('should add complexity for interface types', () => { + const ast = parse(` + query { + interface { + name + ...on NameInterface { + name + } + } + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(3); + }); + + it('should add complexity for inline fragments without type condition', () => { + const ast = parse(` + query { + interface { + ... { + name + } + } + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(2); + }); + + it('should add complexity for enum types', () => { + const ast = parse(` + query { + enum + } + `); + + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(visitor.complexity).to.equal(1); + }); + + it('should error on a missing non-null argument', () => { + const ast = parse(` + query { + requiredArgs + } + `); + const context = new ValidationContext(schema, ast, typeInfo); + const visitor = new ComplexityVisitor(context, { + maximumComplexity: 100, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ + defaultComplexity: 1 + }) + ] + }); + visit(ast, visitWithTypeInfo(typeInfo, visitor)); + expect(context.getErrors().length).to.equal(1); + expect(context.getErrors()[0].message).to.equal('Argument "count" of required type "Int!" was not provided.'); + }); +}); diff --git a/src/estimators/fieldExtensions/__tests__/fixtures/schema.ts b/src/estimators/fieldExtensions/__tests__/fixtures/schema.ts new file mode 100644 index 0000000..8281eb6 --- /dev/null +++ b/src/estimators/fieldExtensions/__tests__/fixtures/schema.ts @@ -0,0 +1,151 @@ +/** + * Created by Ivo Meißner on 28.07.17. + */ + +import { + GraphQLList, + GraphQLObjectType, + GraphQLNonNull, + GraphQLSchema, + GraphQLString, + GraphQLInt, + GraphQLEnumType, + GraphQLUnionType, + GraphQLInterfaceType, +} from 'graphql'; + +import {ComplexityEstimatorArgs} from '../../../../QueryComplexity'; + +const Item: GraphQLObjectType = new GraphQLObjectType({ + name: 'Item', + fields: () => ({ + variableList: { + type: Item, + extensions: { + complexity: (args: ComplexityEstimatorArgs) => args.childComplexity * (args.args.count || 10), + }, + args: { + count: { + type: GraphQLInt + } + } + }, + scalar: { type: GraphQLString }, + complexScalar: { + type: GraphQLString, + extensions: { + complexity: 20, + }, + }, + variableScalar: { + type: Item, + extensions: { + complexity: (args: ComplexityEstimatorArgs) => 10 * (args.args.count || 10), + }, + args: { + count: { + type: GraphQLInt + } + } + }, + list: { type: new GraphQLList(Item) }, + nonNullItem: { + type: new GraphQLNonNull(Item), + resolve: () => ({}), + }, + nonNullList: { + type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(Item))), + resolve: () => [], + }, + }), +}); + +const NameInterface = new GraphQLInterfaceType({ + name: 'NameInterface', + fields: { + name: { type: GraphQLString } + }, + resolveType: () => Item +}); + +const SecondItem = new GraphQLObjectType({ + name: 'SecondItem', + fields: () => ({ + name: {type: GraphQLString}, + scalar: {type: GraphQLString} + }), + interfaces: [ NameInterface ] +}); + +const EnumType = new GraphQLEnumType({ + name: 'RGB', + values: { + RED: { value: 0 }, + GREEN: { value: 1 }, + BLUE: { value: 2 } + } +}); + +const Union = new GraphQLUnionType({ + name: 'Union', + types: [ Item, SecondItem ], + resolveType: () => Item +}); + +const Query = new GraphQLObjectType({ + name: 'Query', + fields: () => ({ + name: { type: GraphQLString }, + variableList: { + type: Item, + extensions: { + complexity: (args: ComplexityEstimatorArgs) => args.childComplexity * (args.args.count || 10), + }, + args: { + count: { + type: GraphQLInt + } + } + }, + interface: {type: NameInterface}, + enum: {type: EnumType}, + scalar: { type: GraphQLString }, + complexScalar: { + type: GraphQLString, + extensions: { + complexity: 20, + }, + }, + union: { type: Union }, + variableScalar: { + type: Item, + extensions: { + complexity: (args: ComplexityEstimatorArgs) => 10 * (args.args.count || 10), + }, + args: { + count: { + type: GraphQLInt + } + } + }, + list: { type: new GraphQLList(Item) }, + nonNullItem: { + type: new GraphQLNonNull(Item), + resolve: () => ({}), + }, + nonNullList: { + type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(Item))), + resolve: () => [], + }, + requiredArgs: { + type: Item, + args: { + count: { + type: new GraphQLNonNull(GraphQLInt) + } + } + } + }), +}); + +export default new GraphQLSchema({ query: Query }); diff --git a/src/estimators/fieldExtensions/index.ts b/src/estimators/fieldExtensions/index.ts new file mode 100644 index 0000000..e3597df --- /dev/null +++ b/src/estimators/fieldExtensions/index.ts @@ -0,0 +1,14 @@ +import {ComplexityEstimator, ComplexityEstimatorArgs} from '../../QueryComplexity'; + +export default function (): ComplexityEstimator { + return (args: ComplexityEstimatorArgs) => { + if (args.field.extensions) { + // Calculate complexity score + if (typeof args.field.extensions.complexity === 'number') { + return args.childComplexity + args.field.extensions.complexity; + } else if (typeof args.field.extensions.complexity === 'function') { + return args.field.extensions.complexity(args); + } + } + }; +} diff --git a/src/estimators/index.ts b/src/estimators/index.ts index 984cda0..bdd1c08 100644 --- a/src/estimators/index.ts +++ b/src/estimators/index.ts @@ -2,3 +2,4 @@ export {default as simpleEstimator} from './simple'; export {default as legacyEstimator} from './legacy'; export {default as fieldConfigEstimator} from './fieldConfig'; export {default as directiveEstimator} from './directive'; +export {default as fieldExtensionsEstimator} from './fieldExtensions'; diff --git a/yarn.lock b/yarn.lock index 667c208..0be6830 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,8 +25,10 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.3.tgz#419477a3d5202bad19e14c787940a61dc9ea6407" "@types/graphql@^0.13.0 || ^14.0.0": - version "14.0.2" - resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-14.0.2.tgz#415e3779718c1e0805e418e3a798cb39dccc58ab" + version "14.5.0" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-14.5.0.tgz#a545fb3bc8013a3547cf2f07f5e13a33642b75d6" + dependencies: + graphql "*" "@types/lodash.get@^4.4.4": version "4.4.6" @@ -401,9 +403,9 @@ globals@^11.7.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" -"graphql@^0.13.0 || ^14.0.0": - version "14.0.2" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650" +graphql@*, "graphql@^0.13.0 || ^14.0.0": + version "14.5.7" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.7.tgz#8646a3fcc07922319cc3967eba4a64b32929f77f" dependencies: iterall "^1.2.2"