move xpath query to insomnia src (#5388)

* remove xpath query package

* fix tests

* install types

* fix test
This commit is contained in:
Jack Kavanagh 2022-11-10 13:13:02 +00:00 committed by GitHub
parent 492a48927b
commit cc3a7cbbda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 145 additions and 6085 deletions

View File

@ -1 +0,0 @@
dist

View File

@ -1,5 +0,0 @@
# Insomnia XPath
[![Npm Version](https://img.shields.io/npm/v/insomnia-xpath.svg)](https://www.npmjs.com/package/insomnia-xpath)
Execute XPath queries on XML.

View File

@ -1,9 +0,0 @@
/** @type { import('@jest/types').Config.InitialOptions } */
module.exports = {
preset: '../../jest-preset.js',
globals: {
'ts-jest': {
isolatedModules: true,
},
},
};

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +0,0 @@
{
"private": true,
"name": "insomnia-xpath",
"version": "3.6.1-beta.3",
"author": "Kong <office@konghq.com>",
"description": "Query XML using XPath",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Kong/insomnia.git",
"directory": "packages/insomnia-xpath"
},
"bugs": {
"url": "https://github.com/Kong/insomnia/issues"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist",
"package.json",
"README.md"
],
"scripts": {
"bootstrap": "npm run build",
"lint": "eslint . --ext .js,.ts,.tsx --cache",
"lint:fix": "npm run lint -- --fix",
"clean": "tsc --build tsconfig.build.json --clean",
"postclean": "rimraf dist",
"build": "tsc --build tsconfig.build.json",
"test": "jest --silent"
},
"devDependencies": {
"@jest/globals": "^28.1.0",
"@types/xmldom": "0.1.30",
"jest": "^28.1.0"
},
"dependencies": {
"insomnia-cookies": "^3.6.1-beta.3",
"xmldom": "^0.5.0",
"xpath": "0.0.32"
}
}

View File

@ -1 +0,0 @@
export { query } from './query';

View File

@ -1,14 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src",
},
"include": [
"src",
],
"exclude": [
"**/*.test.ts",
],
}

View File

@ -1,13 +0,0 @@
{
"extends": "./tsconfig.build.json",
"compilerOptions": {
"rootDir": ".",
},
"include": [
"jest.config.js",
"src",
],
"exclude": [
"dist",
],
}

View File

@ -98,6 +98,7 @@
"@types/uuid": "^8.3.4",
"@types/vkbeautify": "^0.99.2",
"@types/ws": "^8.5.3",
"@types/xmldom": "0.1.30",
"@types/yaml": "^1.9.7",
"@vitejs/plugin-react": "^1.2.0",
"buffer": "^6.0.3",
@ -152,7 +153,9 @@
"vite": "^2.8.6",
"vite-plugin-commonjs-externals": "^0.1.1",
"vkbeautify": "^0.99.1",
"ws": "^8.8.1"
"ws": "^8.8.1",
"xmldom": "^0.5.0",
"xpath": "0.0.32"
}
},
"node_modules/@ampproject/remapping": {
@ -6587,6 +6590,12 @@
"@types/node": "*"
}
},
"node_modules/@types/xmldom": {
"version": "0.1.30",
"resolved": "https://registry.npmjs.org/@types/xmldom/-/xmldom-0.1.30.tgz",
"integrity": "sha512-edqgAFXMEtVvaBZ3YnhamvmrHjoYpuxETmnb0lbTZmf/dXpAsO9ZKotUO4K2rn2SIZBDFCMOuA7fOe0H6dRZcA==",
"dev": true
},
"node_modules/@types/yaml": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
@ -22197,6 +22206,24 @@
"integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==",
"dev": true
},
"node_modules/xmldom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz",
"integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/xpath": {
"version": "0.0.32",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz",
"integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==",
"dev": true,
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -27614,6 +27641,12 @@
"@types/node": "*"
}
},
"@types/xmldom": {
"version": "0.1.30",
"resolved": "https://registry.npmjs.org/@types/xmldom/-/xmldom-0.1.30.tgz",
"integrity": "sha512-edqgAFXMEtVvaBZ3YnhamvmrHjoYpuxETmnb0lbTZmf/dXpAsO9ZKotUO4K2rn2SIZBDFCMOuA7fOe0H6dRZcA==",
"dev": true
},
"@types/yaml": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
@ -39657,6 +39690,18 @@
"integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==",
"dev": true
},
"xmldom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz",
"integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==",
"dev": true
},
"xpath": {
"version": "0.0.32",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz",
"integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==",
"dev": true
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View File

@ -86,7 +86,6 @@
"insomnia-plugin-uuid": "^3.6.1-beta.3",
"insomnia-testing": "^3.6.1-beta.3",
"insomnia-url": "^3.6.1-beta.3",
"insomnia-xpath": "^3.6.1-beta.3",
"isomorphic-git": "^1.10.4",
"js-yaml": "^3.14.1",
"jshint": "^2.11.1",
@ -154,6 +153,7 @@
"@types/uuid": "^8.3.4",
"@types/vkbeautify": "^0.99.2",
"@types/ws": "^8.5.3",
"@types/xmldom": "0.1.30",
"@types/yaml": "^1.9.7",
"@vitejs/plugin-react": "^1.2.0",
"buffer": "^6.0.3",
@ -208,6 +208,8 @@
"vite": "^2.8.6",
"vite-plugin-commonjs-externals": "^0.1.1",
"vkbeautify": "^0.99.1",
"xmldom": "^0.5.0",
"xpath": "0.0.32",
"ws": "^8.8.1"
},
"dev": {

View File

@ -7,7 +7,6 @@ import { GraphQLInfoOptions } from 'codemirror-graphql/info';
import { ModifiedGraphQLJumpOptions } from 'codemirror-graphql/jump';
import deepEqual from 'deep-equal';
import { KeyCombination } from 'insomnia-common';
import { query as queryXPath } from 'insomnia-xpath';
import { JSONPath } from 'jsonpath-plus';
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
@ -19,6 +18,7 @@ import * as misc from '../../../common/misc';
import { getTagDefinitions } from '../../../templating/index';
import { NunjucksParsedTag } from '../../../templating/utils';
import { jsonPrettify } from '../../../utils/prettify/json';
import { queryXPath } from '../../../utils/xpath/query';
import { useGatedNunjucks } from '../../context/nunjucks/use-gated-nunjucks';
import { selectSettings } from '../../redux/selectors';
import { Dropdown } from '../base/dropdown/dropdown';

View File

@ -1,43 +1,43 @@
import { describe, expect, it } from '@jest/globals';
import { query } from './query';
import { queryXPath } from './query';
describe('query()', () => {
describe('queryXPath()', () => {
it('handles missing query', () => {
expect(() => {
query('<foo><bar></bar></foo>');
queryXPath('<foo><bar></bar></foo>');
}).toThrowError('Must pass an XPath query.');
});
it('handles basic query', () => {
expect(query('<x><y>foo</y><y>bar</y></x>', '//y')).toEqual([
expect(queryXPath('<x><y>foo</y><y>bar</y></x>', '//y')).toEqual([
{ inner: 'foo', outer: '<y>foo</y>' },
{ inner: 'bar', outer: '<y>bar</y>' },
]);
});
it('handles attribute query', () => {
expect(query('<x><y foo="bar">foo</y><y hi="there">bar</y></x>', '//*[@foo="bar"]')).toEqual([
expect(queryXPath('<x><y foo="bar">foo</y><y hi="there">bar</y></x>', '//*[@foo="bar"]')).toEqual([
{ inner: 'foo', outer: '<y foo="bar">foo</y>' },
]);
});
it('handles string query', () => {
expect(query('<x><y>foo</y><y>bar</y></x>', 'substring(//y[1], 2)')).toEqual([
expect(queryXPath('<x><y>foo</y><y>bar</y></x>', 'substring(//y[1], 2)')).toEqual([
{ inner: 'oo', outer: 'oo' },
]);
});
it('handles text() query', () => {
expect(query('<book><title>Harry</title><title>Potter</title></book>', 'local-name(/book)'))
expect(queryXPath('<book><title>Harry</title><title>Potter</title></book>', 'local-name(/book)'))
.toEqual([{ 'inner': 'book', 'outer': 'book' }]);
expect(query('<book><title>Harry</title><title>Potter</title></book>', '//title/text()'))
expect(queryXPath('<book><title>Harry</title><title>Potter</title></book>', '//title/text()'))
.toEqual([{ 'inner': 'Harry', 'outer': 'Harry' }, { 'inner': 'Potter', 'outer': 'Potter' }]);
});
it('handles invalid query', () => {
expect(() => {
query('<hi>there</hi>', '//[]');
queryXPath('<hi>there</hi>', '//[]');
}).toThrowError('Invalid XPath query: //[]');
});
});

View File

@ -4,22 +4,18 @@ import xpath, { SelectedValue } from 'xpath';
/**
* Query an XML blob with XPath
*/
export const query = (xml: string, query?: string) => {
export const queryXPath = (xml: string, query?: string) => {
const dom = new DOMParser().parseFromString(xml);
let selectedValues: SelectedValue[] = [];
if (query === undefined) {
throw new Error('Must pass an XPath query.');
}
try {
selectedValues = xpath.select(query, dom);
} catch (err) {
throw new Error(`Invalid XPath query: ${query}`);
}
const output = [];
// Functions return plain strings
if (typeof selectedValues === 'string') {
output.push({
@ -55,6 +51,5 @@ export const query = (xml: string, query?: string) => {
}
}
}
return output;
};

View File

@ -1,6 +1,5 @@
const { JSONPath } = require('jsonpath-plus');
const iconv = require('iconv-lite');
const { query: queryXPath } = require('insomnia-xpath');
function isFilterableField(field) {
return field !== 'raw' && field !== 'url';
@ -280,3 +279,56 @@ function matchHeader(headers, name) {
return header.value;
}
/**
* Query an XML blob with XPath
*/
const queryXPath = (xml, query) => {
const DOMParser = require('xmldom').DOMParser
const dom = new DOMParser().parseFromString(xml);
let selectedValues = [];
if (query === undefined) {
throw new Error('Must pass an XPath query.');
}
try {
selectedValues = require('xpath').select(query, dom);
} catch (err) {
throw new Error(`Invalid XPath query: ${query}`);
}
const output = [];
// Functions return plain strings
if (typeof selectedValues === 'string') {
output.push({
outer: selectedValues,
inner: selectedValues,
});
} else {
for (const selectedValue of selectedValues || []) {
switch (selectedValue.constructor.name) {
case 'Attr':
output.push({
outer: selectedValue.toString().trim(),
inner: selectedValue.nodeValue,
});
break;
case 'Element':
output.push({
outer: selectedValue.toString().trim(),
inner: selectedValue.childNodes.toString(),
});
break;
case 'Text':
output.push({
outer: selectedValue.toString().trim(),
inner: selectedValue.toString().trim(),
});
break;
default:
break;
}
}
}
return output;
};

View File

@ -10,7 +10,9 @@
"license": "MIT",
"dependencies": {
"iconv-lite": "^0.6.3",
"jsonpath-plus": "^6.0.1"
"jsonpath-plus": "^6.0.1",
"xmldom": "^0.5.0",
"xpath": "0.0.32"
}
},
"node_modules/iconv-lite": {
@ -36,6 +38,22 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/xmldom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz",
"integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/xpath": {
"version": "0.0.32",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz",
"integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==",
"engines": {
"node": ">=0.6.0"
}
}
},
"dependencies": {
@ -56,6 +74,16 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"xmldom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz",
"integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA=="
},
"xpath": {
"version": "0.0.32",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz",
"integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw=="
}
}
}

View File

@ -23,7 +23,8 @@
},
"dependencies": {
"iconv-lite": "^0.6.3",
"insomnia-xpath": "^3.6.1-beta.3",
"jsonpath-plus": "^6.0.1"
"jsonpath-plus": "^6.0.1",
"xmldom": "^0.5.0",
"xpath": "0.0.32"
}
}