Thomas 3 жил өмнө
parent
commit
10c7e57574
8 өөрчлөгдсөн 263 нэмэгдсэн , 16 устгасан
  1. 76 0
      fillInteractDB.js
  2. 47 0
      fillInteractDB.ts
  3. 12 6
      index.js
  4. 11 8
      index.ts
  5. 1 0
      package.json
  6. 1 1
      test.js
  7. 1 1
      test.ts
  8. 114 0
      yarn.lock

+ 76 - 0
fillInteractDB.js

@@ -0,0 +1,76 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
+};
+var __asyncValues = (this && this.__asyncValues) || function (o) {
+    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
+    var m = o[Symbol.asyncIterator], i;
+    return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
+    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
+    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const _1 = require(".");
+const fs_1 = __importDefault(require("fs"));
+const readline_1 = __importDefault(require("readline"));
+const { Database, aql } = require("arangojs");
+const fast_xml_parser_1 = require("fast-xml-parser");
+const db = new Database({
+    url: "http://localhost:8529",
+    databaseName: "test",
+    auth: { username: "root", password: "test123" },
+});
+const line$ = (path) => readline_1.default.createInterface({
+    input: fs_1.default.createReadStream(path),
+    crlfDelay: Infinity
+});
+const parser = new fast_xml_parser_1.XMLParser({
+    ignoreAttributes: false,
+    alwaysCreateTextNode: false,
+    attributeNamePrefix: "",
+    textNodeName: "value",
+    allowBooleanAttributes: true,
+});
+(() => __awaiter(void 0, void 0, void 0, function* () {
+    var e_1, _a;
+    const uniprotDB = '/home/thomas/NGS/ref/UNIPROT/uniprot_sprot_human.xml';
+    try {
+        for (var _b = __asyncValues(line$(uniprotDB + '.jsi')), _c; _c = yield _b.next(), !_c.done;) {
+            const line = _c.value;
+            const acc = /;/.test(line) ? line.split(';')[0] : line.split(/\t/)[0];
+            const [from, to] = [line.split(/\t/)[1], line.split(/\t/)[2]];
+            const tmp = parser.parse(yield (0, _1.readOffset)(uniprotDB, Number(from), Number(to)));
+            if (Object.keys(tmp).length === 0) {
+                break;
+            }
+            else {
+                try {
+                    const inter = yield (0, _1.getInteractionsFromEntry)(tmp);
+                }
+                catch (error) {
+                    console.log(error);
+                    console.log(acc);
+                    console.log(tmp.entry.gene);
+                    console.log(tmp);
+                    break;
+                }
+            }
+        }
+    }
+    catch (e_1_1) { e_1 = { error: e_1_1 }; }
+    finally {
+        try {
+            if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
+        }
+        finally { if (e_1) throw e_1.error; }
+    }
+}))();

+ 47 - 0
fillInteractDB.ts

@@ -0,0 +1,47 @@
+import {getInteractionsFromEntry, readOffset} from '.'
+import fs from 'fs'
+import readline from 'readline'
+const { Database, aql } = require("arangojs");
+import { XMLParser } from 'fast-xml-parser'
+
+const db = new Database({
+    url: "http://localhost:8529",
+    databaseName: "test",
+    auth: { username: "root", password: "test123" },
+  });
+
+const line$ = (path: string) => readline.createInterface({
+    input: fs.createReadStream(path),
+    crlfDelay: Infinity
+})
+
+const parser = new XMLParser({
+    ignoreAttributes: false, 
+    alwaysCreateTextNode: false, 
+    attributeNamePrefix: "",
+    textNodeName: "value",
+    allowBooleanAttributes: true,
+})
+
+;(async()=>{
+    const uniprotDB = '/home/thomas/NGS/ref/UNIPROT/uniprot_sprot_human.xml' 
+    for await (const line of line$(uniprotDB + '.jsi')) {
+        const acc = /;/.test(line) ? line.split(';')[0] : line.split(/\t/)[0]
+        const [from, to] = [line.split(/\t/)[1], line.split(/\t/)[2]]
+        const tmp = parser.parse(await readOffset(uniprotDB, Number(from), Number(to)))
+
+        if(Object.keys(tmp).length === 0) {
+            break
+        } else {
+            try {
+                const inter = await getInteractionsFromEntry(tmp)
+            } catch (error) {
+                console.log(error)
+                console.log(acc)
+                console.log(tmp.entry.gene)
+                console.log(tmp)
+                break
+            }
+        }
+    }
+})()

+ 12 - 6
index.js

@@ -21,9 +21,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
 };
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.getInteractionsFromEntry = exports.getEntryFromGeneName = exports.getEnrty = exports.readOffset = exports.makeIndex = void 0;
+const fast_xml_parser_1 = require("fast-xml-parser");
 const fs_1 = __importDefault(require("fs"));
 const readline_1 = __importDefault(require("readline"));
-const fast_xml_parser_1 = require("fast-xml-parser");
 const line$ = (path) => readline_1.default.createInterface({
     input: fs_1.default.createReadStream(path),
     crlfDelay: Infinity
@@ -137,14 +137,21 @@ const getAccessFromGene = (idmappingPath, geneName) => __awaiter(void 0, void 0,
     return accessions;
 });
 const getInteractionsFromEntry = (json) => __awaiter(void 0, void 0, void 0, function* () {
+    var _k, _l, _m, _o, _p, _q, _r, _s;
     const blaskList = ['DNA', 'PHOSPHOSERINE', 'MOTIFS', 'INFECTION', 'PROTEIN', 'PROTEINS', 'GAMMA-SECRETASE', 'CALCIUM',
         'MICROBIAL', 'VIRUS', 'HEPATITIS', 'HERPES', 'SIMPLEX', 'RELATED', 'AND', 'CLATHRIN', 'WORTMANNIN',
         'NUCLEOSOME', 'undefined'];
     const uniprotIDs = Array.isArray(json.entry.accession) ? json.entry.accession : [json.entry.accession];
     // geneName
     const gnTT = Array.isArray(json.entry.gene) ? json.entry.gene[0] : json.entry.gene;
-    const gnT = Array.isArray(gnTT.name) ? gnTT.name : [gnTT.name];
-    const geneName = gnT.filter((e) => e.type === 'primary').map((e) => e.value)[0];
+    let geneName = '';
+    if (gnTT === null || gnTT === void 0 ? void 0 : gnTT.name) {
+        const gnT = Array.isArray(gnTT.name) ? gnTT.name : [gnTT.name];
+        geneName = gnT.filter((e) => e.type === 'primary').map((e) => e.value)[0];
+    }
+    else if ((_l = (_k = json.entry) === null || _k === void 0 ? void 0 : _k.protein) === null || _l === void 0 ? void 0 : _l.recommendedName) {
+        geneName = Array.isArray((_o = (_m = json.entry) === null || _m === void 0 ? void 0 : _m.protein) === null || _o === void 0 ? void 0 : _o.recommendedName) ? (_q = (_p = json.entry) === null || _p === void 0 ? void 0 : _p.protein) === null || _q === void 0 ? void 0 : _q.recommendedName[0] : (_s = (_r = json.entry) === null || _r === void 0 ? void 0 : _r.protein) === null || _s === void 0 ? void 0 : _s.recommendedName;
+    }
     // Interactants
     const jecT = Array.isArray(json.entry.comment) ? json.entry.comment : [json.entry.comment];
     const interactants = jecT
@@ -182,7 +189,8 @@ const getInteractionsFromEntry = (json) => __awaiter(void 0, void 0, void 0, fun
         text: e.text
     })));
     // uniprot_reference_scope
-    const referenceInteract = json.entry.reference
+    const jerT = Array.isArray(json.entry.reference) ? json.entry.reference : [json.entry.reference];
+    const referenceInteract = jerT
         .map((e) => (Object.assign(Object.assign({}, e), { scope: Array.isArray(e.scope) ? e.scope : [e.scope] })))
         .filter((e) => regExp.test(e.scope.join('')))
         .map((e) => (Object.assign({ to: e.scope
@@ -206,7 +214,6 @@ const getInteractionsFromEntry = (json) => __awaiter(void 0, void 0, void 0, fun
     // Group
     const byTo = {};
     [...interactants, ...referenceInteract, ...commentInteractsWith]
-        //.map((e:any)=> byTo[e.to] = byTo[e.to] ? [e, ...byTo[e.to]] : [e] )
         .map((e) => byTo[e.to] = byTo[e.to] ? Object.assign(Object.assign({}, e), byTo[e.to]) : Object.assign({}, e));
     const results = Object.keys(byTo).map((e) => {
         var _a;
@@ -218,7 +225,6 @@ const getInteractionsFromEntry = (json) => __awaiter(void 0, void 0, void 0, fun
         };
     })
         .filter((e) => !blaskList.includes(e.to) && e.to !== geneName);
-    // await fs.promises.writeFile('test/tmp.json', JSON.stringify(results.map((e:any)=>e.to), null,4))
     return results;
 });
 exports.getInteractionsFromEntry = getInteractionsFromEntry;

+ 11 - 8
index.ts

@@ -1,8 +1,8 @@
 // https://ftp.uniprot.org/pub/databases/uniprot/current_release/knowledgebase/taxonomic_divisions/uniprot_sprot_human.xml.gz
 
+import { XMLParser } from 'fast-xml-parser'
 import fs from 'fs'
 import readline from 'readline'
-import { XMLParser } from 'fast-xml-parser'
 
 const line$ = (path: string) => readline.createInterface({
     input: fs.createReadStream(path),
@@ -97,8 +97,13 @@ const getInteractionsFromEntry = async (json:any) => {
 
     // geneName
     const gnTT = Array.isArray(json.entry.gene) ? json.entry.gene[0] : json.entry.gene
-    const gnT =  Array.isArray(gnTT.name) ? gnTT.name :  [gnTT.name]
-    const geneName = gnT.filter((e:any)=> e.type === 'primary').map((e:any)=> e.value)[0]
+    let geneName = ''
+    if (gnTT?.name) {
+        const gnT =  Array.isArray(gnTT.name) ? gnTT.name :  [gnTT.name]
+        geneName = gnT.filter((e:any)=> e.type === 'primary').map((e:any)=> e.value)[0]
+    } else if(json.entry?.protein?.recommendedName) {
+        geneName = Array.isArray(json.entry?.protein?.recommendedName) ? json.entry?.protein?.recommendedName[0] : json.entry?.protein?.recommendedName
+    }
 
     // Interactants
     const jecT = Array.isArray(json.entry.comment) ? json.entry.comment : [json.entry.comment]
@@ -140,7 +145,8 @@ const getInteractionsFromEntry = async (json:any) => {
     })))
 
     // uniprot_reference_scope
-    const referenceInteract = json.entry.reference
+    const jerT = Array.isArray(json.entry.reference) ? json.entry.reference : [json.entry.reference]
+    const referenceInteract = jerT
     .map((e:any)=> ({...e, scope : Array.isArray(e.scope) ? e.scope : [e.scope]}))
     .filter((e:any) => regExp.test(e.scope.join('')))
     .map((e:any)=> ({
@@ -162,13 +168,12 @@ const getInteractionsFromEntry = async (json:any) => {
         type    : 'reference_scope',
         to      : ee,
         scope   : e.scope, 
-        //citation: e.citation
+        citation: e.citation
     })))
 
     // Group
     const byTo = {} as {[key:string]: any}
     [...interactants, ...referenceInteract, ...commentInteractsWith]
-    //.map((e:any)=> byTo[e.to] = byTo[e.to] ? [e, ...byTo[e.to]] : [e] )
     .map((e:any)=> byTo[e.to] = byTo[e.to] ? {...e, ...byTo[e.to]} : {...e} )
     
     const results = Object.keys(byTo).map((e:any) => {
@@ -180,8 +185,6 @@ const getInteractionsFromEntry = async (json:any) => {
         }
     })
     .filter((e:any) => !blaskList.includes(e.to) && e.to !== geneName)
-
-    // await fs.promises.writeFile('test/tmp.json', JSON.stringify(results.map((e:any)=>e.to), null,4))
     
     return results
 }

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "typescript": "^4.6.2"
   },
   "dependencies": {
+    "arangojs": "^7.7.0",
     "fast-xml-parser": "^4.0.6"
   }
 }

+ 1 - 1
test.js

@@ -22,7 +22,7 @@ const fs_1 = __importDefault(require("fs"));
     // const n = await getEntryFromGeneName(idmappingPath, uniprotDB, 'TTC23L')
     // await fs.promises.writeFile('test/test-CITED2.json', JSON.stringify(n, null, 4))
     // console.log(await getInteractionsFromEntry(n))
-    const geneName = 'undefined';
+    const geneName = 'ARL14EPL';
     const n = yield (0, _1.getEntryFromGeneName)(idmappingPath, uniprotDB, geneName);
     yield fs_1.default.promises.writeFile('test/test-' + geneName + '.json', JSON.stringify(n, null, 4));
     const tmp = yield (0, _1.getInteractionsFromEntry)(n);

+ 1 - 1
test.ts

@@ -11,7 +11,7 @@ import fs from 'fs'
     // await fs.promises.writeFile('test/test-CITED2.json', JSON.stringify(n, null, 4))
     // console.log(await getInteractionsFromEntry(n))
 
-    const geneName = 'undefined'
+    const geneName = 'ARL14EPL'
     const n = await getEntryFromGeneName(idmappingPath, uniprotDB, geneName)
     await fs.promises.writeFile('test/test-' + geneName + '.json', JSON.stringify(n, null, 4))
     const tmp = await getInteractionsFromEntry(n)

+ 114 - 0
yarn.lock

@@ -2,11 +2,37 @@
 # yarn lockfile v1
 
 
+"@types/node@>=13.13.4":
+  version "17.0.23"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da"
+  integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==
+
 "@types/node@^17.0.21":
   version "17.0.21"
   resolved "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz"
   integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==
 
+arangojs@^7.7.0:
+  version "7.7.0"
+  resolved "https://registry.yarnpkg.com/arangojs/-/arangojs-7.7.0.tgz#3286bb75a0b063b699f153a76e83deb4967ef0a8"
+  integrity sha512-U73Xez7/WeuvHHBoBuq3ew06erXzOpJq7kopBHfuOi6JQ9sarHf/NQzhgCGQF43O2U2OcqpY8bh1+4qnFnJt8g==
+  dependencies:
+    "@types/node" ">=13.13.4"
+    es6-error "^4.0.1"
+    multi-part "^3.0.0"
+    x3-linkedlist "1.2.0"
+    xhr "^2.4.1"
+
+dom-walk@^0.1.0:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
+  integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
+
+es6-error@^4.0.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
+  integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
+
 fast-xml-parser@^4.0.6:
   version "4.0.6"
   resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.0.6.tgz#bd0b75badc7abfc55c772f6a0c21e417ad989743"
@@ -14,6 +40,74 @@ fast-xml-parser@^4.0.6:
   dependencies:
     strnum "^1.0.5"
 
+file-type@^12.1.0:
+  version "12.4.2"
+  resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9"
+  integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==
+
+global@~4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
+  integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
+  dependencies:
+    min-document "^2.19.0"
+    process "^0.11.10"
+
+is-function@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
+  integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==
+
+mime-db@1.52.0:
+  version "1.52.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+  integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-kind@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/mime-kind/-/mime-kind-3.0.0.tgz#23bb3aba03ed6a1ea8c4f6093a9c7ab7121a9cb2"
+  integrity sha512-sx9lClVP7GXY2mO3aVDWTQLhfvAdDvNhGi3o3g7+ae3aKaoybeGbEIlnreoRKjrbDpvlPltlkIryxOtatojeXQ==
+  dependencies:
+    file-type "^12.1.0"
+    mime-types "^2.1.24"
+
+mime-types@^2.1.24:
+  version "2.1.35"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+  integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+  dependencies:
+    mime-db "1.52.0"
+
+min-document@^2.19.0:
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
+  integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=
+  dependencies:
+    dom-walk "^0.1.0"
+
+multi-part-lite@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/multi-part-lite/-/multi-part-lite-1.0.0.tgz#7b86baf8ff83ef20ca13f1269a0f35aec42b9000"
+  integrity sha512-KxIRbBZZ45hoKX1ROD/19wJr0ql1bef1rE8Y1PCwD3PuNXV42pp7Wo8lEHYuAajoT4vfAFcd3rPjlkyEEyt1nw==
+
+multi-part@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/multi-part/-/multi-part-3.0.0.tgz#2bde386e8c1dcc9f15a2277267a7f5ed13aa0cc0"
+  integrity sha512-pDbdYQ6DLDxAsD83w9R7r7rlW56cETL7hIB5bCWX7FJYw0K+kL5JwHr0I8tRk9lGeFcAzf+2OEzXWlG/4wCnFw==
+  dependencies:
+    mime-kind "^3.0.0"
+    multi-part-lite "^1.0.0"
+
+parse-headers@^2.0.0:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9"
+  integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==
+
+process@^0.11.10:
+  version "0.11.10"
+  resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+  integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
+
 strnum@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db"
@@ -23,3 +117,23 @@ typescript@^4.6.2:
   version "4.6.2"
   resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz"
   integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
+
+x3-linkedlist@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/x3-linkedlist/-/x3-linkedlist-1.2.0.tgz#c70467559b7c748595f0f79222af1d709402699e"
+  integrity sha512-mH/YwxpYSKNa8bDNF1yOuZCMuV+K80LtDN8vcLDUAwNazCxptDNsYt+zA/EJeYiGbdtKposhKLZjErGVOR8mag==
+
+xhr@^2.4.1:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d"
+  integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==
+  dependencies:
+    global "~4.4.0"
+    is-function "^1.0.1"
+    parse-headers "^2.0.0"
+    xtend "^4.0.0"
+
+xtend@^4.0.0:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+  integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==