opensearch-browser
Advanced tools
Comparing version 0.0.15 to 0.0.16
module.exports = { | ||
"extends": "pedant", | ||
"extends": "airbnb", | ||
"parser": "babel-eslint", | ||
"parserOptions": { | ||
"sourceType": "module", | ||
"allowImportExportEverywhere": false | ||
"allowImportExportEverywhere": false, | ||
"no-underscore-dangle": [ | ||
"error", { | ||
"allowAfterThis": true | ||
} | ||
] | ||
}, | ||
"env": { | ||
"es6": true, | ||
"mocha": true, | ||
@@ -10,0 +16,0 @@ "browser": true, |
@@ -38,54 +38,52 @@ 'use strict'; | ||
* Parse the given XML. | ||
* @param {Response} response The {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} object containing the XML to parse. | ||
* @returns {Promise<SearchResult>} The parsed search result as a promise | ||
* @param {string} text The XML string to parse. | ||
* @returns {SearchResult} The parsed search result | ||
*/ | ||
value: function parse(response) { | ||
value: function parse(text) { | ||
var _this2 = this; | ||
return response.text().then(function (text) { | ||
var xmlDoc = (0, _utils.parseXml)(text).documentElement; | ||
var records = (0, _utils.xPathArray)(xmlDoc, 'atom:entry').map(function (node) { | ||
var entry = { | ||
id: (0, _utils.xPath)(node, 'dc:identifier/text()') || (0, _utils.xPath)(node, 'atom:id/text()'), | ||
properties: { | ||
title: (0, _utils.xPath)(node, 'atom:title/text()'), | ||
updated: new Date((0, _utils.xPath)(node, 'atom:updated/text()')), | ||
content: (0, _utils.xPath)(node, 'atom:content/text()'), | ||
summary: (0, _utils.xPath)(node, 'atom:summary/text()'), | ||
links: _this2.parseLinks(node), | ||
media: _this2.parseMedia(node) | ||
} | ||
}; | ||
var box = _this2.parseBox(node); | ||
if (box) { | ||
entry.bbox = box; | ||
var xmlDoc = (0, _utils.parseXml)(text).documentElement; | ||
var records = (0, _utils.xPathArray)(xmlDoc, 'atom:entry').map(function (node) { | ||
var entry = { | ||
id: (0, _utils.xPath)(node, 'dc:identifier/text()') || (0, _utils.xPath)(node, 'atom:id/text()'), | ||
properties: { | ||
title: (0, _utils.xPath)(node, 'atom:title/text()'), | ||
updated: new Date((0, _utils.xPath)(node, 'atom:updated/text()')), | ||
content: (0, _utils.xPath)(node, 'atom:content/text()'), | ||
summary: (0, _utils.xPath)(node, 'atom:summary/text()'), | ||
links: _this2.parseLinks(node), | ||
media: _this2.parseMedia(node) | ||
} | ||
}; | ||
var geometry = _this2.parseGeometry(node); | ||
if (geometry) { | ||
entry.geometry = geometry; | ||
var box = _this2.parseBox(node); | ||
if (box) { | ||
entry.bbox = box; | ||
} | ||
if (!entry.bbox) { | ||
entry.bbox = _this2.getBoxFromGeometry(geometry); | ||
} | ||
} | ||
var geometry = _this2.parseGeometry(node); | ||
if (geometry) { | ||
entry.geometry = geometry; | ||
var date = _this2.parseDate(node); | ||
if (date) { | ||
entry.properties.time = date; | ||
if (!entry.bbox) { | ||
entry.bbox = _this2.getBoxFromGeometry(geometry); | ||
} | ||
} | ||
return entry; | ||
}); | ||
var date = _this2.parseDate(node); | ||
if (date) { | ||
entry.properties.time = date; | ||
} | ||
return { | ||
totalResults: parseInt((0, _utils.xPath)(xmlDoc, 'os:totalResults/text()'), 10), | ||
startIndex: parseInt((0, _utils.xPath)(xmlDoc, 'os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt((0, _utils.xPath)(xmlDoc, 'os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: _this2.parseLinks(xmlDoc), | ||
records: records | ||
}; | ||
return entry; | ||
}); | ||
return { | ||
totalResults: parseInt((0, _utils.xPath)(xmlDoc, 'os:totalResults/text()'), 10), | ||
startIndex: parseInt((0, _utils.xPath)(xmlDoc, 'os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt((0, _utils.xPath)(xmlDoc, 'os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: this.parseLinks(xmlDoc), | ||
records: records | ||
}; | ||
} | ||
@@ -92,0 +90,0 @@ }]); |
@@ -25,21 +25,20 @@ 'use strict'; | ||
* Parse the given JSON. | ||
* @param {Response} response The {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} object containing the XML to parse. | ||
* @returns {Promise<SearchResult>} The parsed search result as a promise | ||
* @param {string} text The JSON string to parse. | ||
* @returns {SearchResult} The parsed search result | ||
*/ | ||
value: function parse(response) { | ||
return response.json().then(function (result) { | ||
var records = result.features.map(function (item) { | ||
if (!item.hasOwnProperty('id') && item.properties.hasOwnProperty('id')) { | ||
return Object.assign({ | ||
id: item.properties.id | ||
}, item); | ||
} | ||
return item; | ||
}); | ||
value: function parse(text) { | ||
var result = JSON.parse(text); | ||
var records = result.features.map(function (item) { | ||
if (!item.hasOwnProperty('id') && item.properties.hasOwnProperty('id')) { | ||
return Object.assign({ | ||
id: item.properties.id | ||
}, item); | ||
} | ||
return item; | ||
}); | ||
return { | ||
// TODO: parse properties of featurecollection | ||
records: records | ||
}; | ||
}); | ||
return { | ||
// TODO: parse properties of featurecollection | ||
records: records | ||
}; | ||
} | ||
@@ -46,0 +45,0 @@ }]); |
@@ -38,53 +38,51 @@ 'use strict'; | ||
* Parse the given XML. | ||
* @param {Response} response The {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} object containing the XML to parse. | ||
* @returns {Promise<SearchResult>} The parsed search result as a promise | ||
* @param {string} text The XML string to parse. | ||
* @returns {SearchResult} The parsed search result | ||
*/ | ||
value: function parse(response) { | ||
value: function parse(text) { | ||
var _this2 = this; | ||
return response.text().then(function (text) { | ||
var xmlDoc = (0, _utils.parseXml)(text).documentElement; | ||
var records = (0, _utils.xPathArray)(xmlDoc, 'channel/item').map(function (node) { | ||
var item = { | ||
id: (0, _utils.xPath)(node, 'dc:identifier/text()') || (0, _utils.xPath)(node, 'guid/text()'), | ||
properties: { | ||
title: (0, _utils.xPath)(node, 'title/text()'), | ||
content: (0, _utils.xPath)(node, 'description/text()'), | ||
summary: (0, _utils.xPath)(node, 'description/text()'), | ||
links: _this2.parseLinks(node), | ||
media: _this2.parseMedia(node) | ||
} | ||
}; | ||
var box = _this2.parseBox(node); | ||
if (box) { | ||
item.bbox = box; | ||
var xmlDoc = (0, _utils.parseXml)(text).documentElement; | ||
var records = (0, _utils.xPathArray)(xmlDoc, 'channel/item').map(function (node) { | ||
var item = { | ||
id: (0, _utils.xPath)(node, 'dc:identifier/text()') || (0, _utils.xPath)(node, 'guid/text()'), | ||
properties: { | ||
title: (0, _utils.xPath)(node, 'title/text()'), | ||
content: (0, _utils.xPath)(node, 'description/text()'), | ||
summary: (0, _utils.xPath)(node, 'description/text()'), | ||
links: _this2.parseLinks(node), | ||
media: _this2.parseMedia(node) | ||
} | ||
}; | ||
var geometry = _this2.parseGeometry(node); | ||
if (geometry) { | ||
item.geometry = geometry; | ||
var box = _this2.parseBox(node); | ||
if (box) { | ||
item.bbox = box; | ||
} | ||
if (!item.bbox) { | ||
item.bbox = _this2.getBoxFromGeometry(geometry); | ||
} | ||
} | ||
var geometry = _this2.parseGeometry(node); | ||
if (geometry) { | ||
item.geometry = geometry; | ||
var date = _this2.parseDate(node); | ||
if (date) { | ||
item.properties.time = date; | ||
if (!item.bbox) { | ||
item.bbox = _this2.getBoxFromGeometry(geometry); | ||
} | ||
} | ||
return item; | ||
}); | ||
var date = _this2.parseDate(node); | ||
if (date) { | ||
item.properties.time = date; | ||
} | ||
return { | ||
totalResults: parseInt((0, _utils.xPath)(xmlDoc, 'channel/os:totalResults/text()'), 10), | ||
startIndex: parseInt((0, _utils.xPath)(xmlDoc, 'channel/os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt((0, _utils.xPath)(xmlDoc, 'channel/os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: _this2.parseLinks(xmlDoc), | ||
records: records | ||
}; | ||
return item; | ||
}); | ||
return { | ||
totalResults: parseInt((0, _utils.xPath)(xmlDoc, 'channel/os:totalResults/text()'), 10), | ||
startIndex: parseInt((0, _utils.xPath)(xmlDoc, 'channel/os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt((0, _utils.xPath)(xmlDoc, 'channel/os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: this.parseLinks(xmlDoc), | ||
records: records | ||
}; | ||
} | ||
@@ -91,0 +89,0 @@ }]); |
@@ -10,4 +10,6 @@ 'use strict'; | ||
var _utils = require('./utils'); | ||
var _search = require('./search'); | ||
var _config = require('./config'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -65,13 +67,17 @@ | ||
var pageIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; | ||
var maxCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; | ||
// TODO: get first page index | ||
if (this._cache && this._cache[pageIndex]) { | ||
return this._cache[pageIndex]; | ||
} | ||
// TODO: implement caching of whole pages | ||
// if (this._cache && this._cache[pageIndex]) { | ||
// return this._cache[pageIndex]; | ||
// } | ||
var parameters = Object.assign({}, this._parameters); | ||
var pageSize = this.getActualPageSize(); | ||
if (pageSize) { | ||
if (pageSize && maxCount) { | ||
parameters.count = Math.min(maxCount, pageSize); | ||
} else if (pageSize) { | ||
parameters.count = pageSize; | ||
} else if (maxCount) { | ||
parameters.count = maxCount; | ||
} | ||
@@ -88,3 +94,4 @@ | ||
} | ||
return (0, _utils.search)(this._url, parameters).then(function (result) { | ||
return (0, _search.search)(this._url, parameters).then(function (result) { | ||
_this._totalResults = result.totalResults; | ||
if (!_this._serverItemsPerPage && result.itemsPerPage) { | ||
@@ -99,3 +106,3 @@ _this._serverItemsPerPage = result.itemsPerPage; | ||
* Fetches all pages from the URL. A probing request is sent to determine how | ||
* many succeding requests have to be sent. | ||
* many succeeding requests have to be sent. | ||
* @returns {Promise<SearchResult[]>} The async result of all the pages in the | ||
@@ -111,9 +118,8 @@ * search. | ||
return this.fetchPage().then(function (firstPage) { | ||
_this2._totalResults = firstPage.totalResults; | ||
var pageCount = _this2.getPageCount() - 1; | ||
var pageCount = _this2.getPageCount(); | ||
var requests = [firstPage]; | ||
for (var i = 0; i < pageCount; ++i) { | ||
for (var i = 1; i < pageCount; ++i) { | ||
requests.push(_this2.fetchPage(i)); | ||
} | ||
return Promise.all(requests); | ||
return (0, _config.getPromiseClass)().all(requests); | ||
}); | ||
@@ -124,3 +130,3 @@ } | ||
* Convenience method to get the records of all pages in a single result array | ||
* @returns {Promise<Record[]>} The records of all the pages in the search. | ||
* @returns {Promise<SearchResult>} The records of all the pages in the search. | ||
*/ | ||
@@ -132,5 +138,12 @@ | ||
return this.fetchAllPages().then(function (pages) { | ||
return pages.reduce(function (records, page) { | ||
var firstPage = pages[0]; | ||
var records = pages.reduce(function (records, page) { | ||
return records.concat(page.records); | ||
}, []); | ||
return { | ||
totalResults: firstPage.totalResults, | ||
startIndex: firstPage.startIndex, | ||
itemsPerPage: firstPage.itemsPerPage, | ||
records: records | ||
}; | ||
}); | ||
@@ -140,2 +153,43 @@ } | ||
/** | ||
* Fetches the first X records of a search in a single search result. | ||
* @param {int} maxCount The maximum number of records to fetch. | ||
* @returns {Promise<SearchResult>} The resulting records as a promise. | ||
*/ | ||
}, { | ||
key: 'fetchFirstRecords', | ||
value: function fetchFirstRecords(maxCount) { | ||
var _this3 = this; | ||
// Get the first page | ||
return this.fetchPage(0, maxCount).then(function (firstPage) { | ||
if (firstPage.itemsPerPage >= maxCount) { | ||
// return if we already have all records | ||
return firstPage; | ||
} | ||
// fetch other pages until we have the required count | ||
var requests = [firstPage]; | ||
for (var i = 1; i < maxCount / firstPage.itemsPerPage; ++i) { | ||
var count = firstPage.itemsPerPage; | ||
if (firstPage.itemsPerPage * i > maxCount) { | ||
count = maxCount - firstPage.itemsPerPage * (i - 1); | ||
} | ||
requests.push(_this3.fetchPage(i, count)); | ||
} | ||
return (0, _config.getPromiseClass)().all(requests).then(function (pages) { | ||
var records = pages.reduce(function (records, page) { | ||
return records.concat(page.records); | ||
}, []); | ||
return { | ||
totalResults: firstPage.totalResults, | ||
startIndex: firstPage.startIndex, | ||
itemsPerPage: firstPage.itemsPerPage, | ||
records: records | ||
}; | ||
}); | ||
}); | ||
} | ||
/** | ||
* Returns the actual page size. | ||
@@ -142,0 +196,0 @@ * @returns {int} The computed page size. |
@@ -16,3 +16,3 @@ 'use strict'; | ||
var _utils = require('./utils'); | ||
var _search2 = require('./search'); | ||
@@ -100,3 +100,3 @@ var _formats = require('./formats/'); | ||
return (0, _utils.search)(url, parameters, type, raw); | ||
return (0, _search2.search)(url, parameters, type, raw); | ||
} | ||
@@ -103,0 +103,0 @@ }, { |
@@ -8,4 +8,2 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -143,89 +141,2 @@ | ||
/** | ||
* Create a request for the given parameters | ||
* @param {object} parameterValues An object mapping the name or type to the value | ||
* @returns {Request} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Request Request} | ||
* object for the | ||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API Fetch API} | ||
*/ | ||
}, { | ||
key: 'createRequest', | ||
value: function createRequest(parameterValues) { | ||
var _this3 = this; | ||
// check parameters | ||
Object.keys(parameterValues).forEach(function (key) { | ||
if (!_this3._parametersByType.hasOwnProperty(key) && !_this3._parametersByName.hasOwnProperty(key)) { | ||
throw new Error('Invalid parameter \'' + key + '\'.'); | ||
} | ||
}); | ||
var missingMandatoryParameters = this.parameters.filter(function (parameter) { | ||
return parameter.mandatory && !parameterValues.hasOwnProperty(parameter.name) && !parameterValues.hasOwnProperty(parameter.type); | ||
}).map(function (parameter) { | ||
return parameter.type; | ||
}); | ||
var missingOptionalParameters = this.parameters.filter(function (parameter) { | ||
return !parameter.mandatory && !parameterValues.hasOwnProperty(parameter.name) && !parameterValues.hasOwnProperty(parameter.type); | ||
}).map(function (parameter) { | ||
return parameter.type; | ||
}); | ||
if (missingMandatoryParameters.length) { | ||
throw new Error('Missing mandatory parameters: ' + missingMandatoryParameters.join(', ')); | ||
} | ||
if (this.method === 'GET') { | ||
var _ret = function () { | ||
// insert parameters into URL template | ||
var url = _this3.url; | ||
Object.keys(parameterValues).forEach(function (key) { | ||
var parameter = _this3._parametersByType[key] || _this3._parametersByName[key]; | ||
url = url.replace(new RegExp('{' + parameter.type + '[?]?}'), parameter.serialize(parameterValues[key])); | ||
}); | ||
missingOptionalParameters.forEach(function (type) { | ||
url = url.replace(new RegExp('{' + type + '[?]?}'), ''); | ||
}); | ||
return { | ||
v: new Request(url) | ||
}; | ||
}(); | ||
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v; | ||
} | ||
// for POST | ||
var enctype = this.enctype || 'application/x-www-form-urlencoded'; | ||
var body = null; | ||
if (enctype === 'application/x-www-form-urlencoded') { | ||
body = Object.keys(parameterValues).map(function (key) { | ||
var param = _this3._parametersByType[key] || _this3._parametersByName[key]; | ||
var k = encodeURIComponent(param.name); | ||
var v = encodeURIComponent(param.serialize(parameterValues[key])); | ||
return k + '=' + v; | ||
}).join('&'); | ||
} else if (enctype === 'multipart/form-data') { | ||
body = new FormData(); | ||
Object.keys(parameterValues).forEach(function (key) { | ||
var param = _this3._parametersByType[key] || _this3._parametersByName[key]; | ||
body.append(param.name, param.serialize(parameterValues[key])); | ||
}); | ||
} else { | ||
throw new Error('Unsupported enctype \'' + enctype + '\'.'); | ||
} | ||
return new Request(this.url, { | ||
method: this.method, | ||
headers: { | ||
'Content-Type': enctype | ||
}, | ||
body: body | ||
}); | ||
} | ||
/** | ||
* Construct a {@link OpenSearchUrl} from a DOMNode | ||
@@ -232,0 +143,0 @@ * @param {DOMNode} node The DOM node from the OpenSearchDescription XML document |
@@ -15,3 +15,2 @@ 'use strict'; | ||
exports.toWKT = toWKT; | ||
exports.search = search; | ||
@@ -24,4 +23,2 @@ require('isomorphic-fetch'); | ||
var _formats = require('./formats'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -161,32 +158,6 @@ | ||
case 'GeometryCollection': | ||
return 'GEOMETRYCOLLECTION(' + gj.geometries.map(stringify).join(', ') + ')'; | ||
return 'GEOMETRYCOLLECTION(' + gj.geometries.map(toWKT).join(', ') + ')'; | ||
default: | ||
throw new Error('stringify requires a valid GeoJSON Feature or geometry object as input'); | ||
} | ||
} | ||
/** | ||
* Performs a search for the given URL and parameters. | ||
* @param {OpenSearchUrl} url The URL to search on. | ||
* @param {object} [parameters={}] The search parameters. | ||
* @param {string} [type=null] The response format. | ||
* @param {boolean} [raw=false] Whether the response shall be parsed or returned raw. | ||
* @returns {Promise<array>|Promise<Response>} The search result as a Promise | ||
*/ | ||
function search(url) { | ||
var parameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; | ||
var raw = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; | ||
return fetchAndCheck(url.createRequest(parameters)).then(function (response) { | ||
if (raw) { | ||
return response; | ||
} | ||
var format = (0, _formats.getFormat)(type || url.type); | ||
if (!format) { | ||
throw new Error('Could not parse response of type \'' + type + '\'.'); | ||
} | ||
return format.parse(response); | ||
}); | ||
} |
{ | ||
"name": "opensearch-browser", | ||
"version": "0.0.15", | ||
"version": "0.0.16", | ||
"description": "An OpenSearch client supporting the geo and time extensions.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -11,54 +11,52 @@ import { parseXml, xPath, xPathArray } from '../utils'; | ||
* Parse the given XML. | ||
* @param {Response} response The {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} object containing the XML to parse. | ||
* @returns {Promise<SearchResult>} The parsed search result as a promise | ||
* @param {string} text The XML string to parse. | ||
* @returns {SearchResult} The parsed search result | ||
*/ | ||
parse(response) { | ||
return response.text().then(text => { | ||
const xmlDoc = parseXml(text).documentElement; | ||
const records = xPathArray(xmlDoc, 'atom:entry').map((node) => { | ||
const entry = { | ||
id: xPath(node, 'dc:identifier/text()') || xPath(node, 'atom:id/text()'), | ||
properties: { | ||
title: xPath(node, 'atom:title/text()'), | ||
updated: new Date(xPath(node, 'atom:updated/text()')), | ||
content: xPath(node, 'atom:content/text()'), | ||
summary: xPath(node, 'atom:summary/text()'), | ||
links: this.parseLinks(node), | ||
media: this.parseMedia(node), | ||
// TODO: further fields | ||
}, | ||
}; | ||
parse(text) { | ||
const xmlDoc = parseXml(text).documentElement; | ||
const records = xPathArray(xmlDoc, 'atom:entry').map((node) => { | ||
const entry = { | ||
id: xPath(node, 'dc:identifier/text()') || xPath(node, 'atom:id/text()'), | ||
properties: { | ||
title: xPath(node, 'atom:title/text()'), | ||
updated: new Date(xPath(node, 'atom:updated/text()')), | ||
content: xPath(node, 'atom:content/text()'), | ||
summary: xPath(node, 'atom:summary/text()'), | ||
links: this.parseLinks(node), | ||
media: this.parseMedia(node), | ||
// TODO: further fields | ||
}, | ||
}; | ||
const box = this.parseBox(node); | ||
if (box) { | ||
entry.bbox = box; | ||
} | ||
const box = this.parseBox(node); | ||
if (box) { | ||
entry.bbox = box; | ||
} | ||
const geometry = this.parseGeometry(node); | ||
if (geometry) { | ||
entry.geometry = geometry; | ||
const geometry = this.parseGeometry(node); | ||
if (geometry) { | ||
entry.geometry = geometry; | ||
if (!entry.bbox) { | ||
entry.bbox = this.getBoxFromGeometry(geometry); | ||
} | ||
if (!entry.bbox) { | ||
entry.bbox = this.getBoxFromGeometry(geometry); | ||
} | ||
} | ||
const date = this.parseDate(node); | ||
if (date) { | ||
entry.properties.time = date; | ||
} | ||
const date = this.parseDate(node); | ||
if (date) { | ||
entry.properties.time = date; | ||
} | ||
return entry; | ||
}); | ||
return entry; | ||
}); | ||
return { | ||
totalResults: parseInt(xPath(xmlDoc, 'os:totalResults/text()'), 10), | ||
startIndex: parseInt(xPath(xmlDoc, 'os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt(xPath(xmlDoc, 'os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: this.parseLinks(xmlDoc), | ||
records, | ||
}; | ||
}); | ||
return { | ||
totalResults: parseInt(xPath(xmlDoc, 'os:totalResults/text()'), 10), | ||
startIndex: parseInt(xPath(xmlDoc, 'os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt(xPath(xmlDoc, 'os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: this.parseLinks(xmlDoc), | ||
records, | ||
}; | ||
} | ||
} |
@@ -9,22 +9,21 @@ | ||
* Parse the given JSON. | ||
* @param {Response} response The {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} object containing the XML to parse. | ||
* @returns {Promise<SearchResult>} The parsed search result as a promise | ||
* @param {string} text The JSON string to parse. | ||
* @returns {SearchResult} The parsed search result | ||
*/ | ||
parse(response) { | ||
return response.json().then(result => { | ||
const records = result.features.map(item => { | ||
if (!item.hasOwnProperty('id') && item.properties.hasOwnProperty('id')) { | ||
return Object.assign({ | ||
id: item.properties.id, | ||
}, item); | ||
} | ||
return item; | ||
}); | ||
parse(text) { | ||
const result = JSON.parse(text); | ||
const records = result.features.map(item => { | ||
if (!item.hasOwnProperty('id') && item.properties.hasOwnProperty('id')) { | ||
return Object.assign({ | ||
id: item.properties.id, | ||
}, item); | ||
} | ||
return item; | ||
}); | ||
return { | ||
// TODO: parse properties of featurecollection | ||
records, | ||
}; | ||
}); | ||
return { | ||
// TODO: parse properties of featurecollection | ||
records, | ||
}; | ||
} | ||
} |
@@ -11,53 +11,51 @@ import { parseXml, xPath, xPathArray } from '../utils'; | ||
* Parse the given XML. | ||
* @param {Response} response The {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} object containing the XML to parse. | ||
* @returns {Promise<SearchResult>} The parsed search result as a promise | ||
* @param {string} text The XML string to parse. | ||
* @returns {SearchResult} The parsed search result | ||
*/ | ||
parse(response) { | ||
return response.text().then(text => { | ||
const xmlDoc = parseXml(text).documentElement; | ||
const records = xPathArray(xmlDoc, 'channel/item').map((node) => { | ||
const item = { | ||
id: xPath(node, 'dc:identifier/text()') || xPath(node, 'guid/text()'), | ||
properties: { | ||
title: xPath(node, 'title/text()'), | ||
content: xPath(node, 'description/text()'), | ||
summary: xPath(node, 'description/text()'), | ||
links: this.parseLinks(node), | ||
media: this.parseMedia(node), | ||
// TODO: further fields + geometry | ||
}, | ||
}; | ||
parse(text) { | ||
const xmlDoc = parseXml(text).documentElement; | ||
const records = xPathArray(xmlDoc, 'channel/item').map((node) => { | ||
const item = { | ||
id: xPath(node, 'dc:identifier/text()') || xPath(node, 'guid/text()'), | ||
properties: { | ||
title: xPath(node, 'title/text()'), | ||
content: xPath(node, 'description/text()'), | ||
summary: xPath(node, 'description/text()'), | ||
links: this.parseLinks(node), | ||
media: this.parseMedia(node), | ||
// TODO: further fields + geometry | ||
}, | ||
}; | ||
const box = this.parseBox(node); | ||
if (box) { | ||
item.bbox = box; | ||
} | ||
const box = this.parseBox(node); | ||
if (box) { | ||
item.bbox = box; | ||
} | ||
const geometry = this.parseGeometry(node); | ||
if (geometry) { | ||
item.geometry = geometry; | ||
const geometry = this.parseGeometry(node); | ||
if (geometry) { | ||
item.geometry = geometry; | ||
if (!item.bbox) { | ||
item.bbox = this.getBoxFromGeometry(geometry); | ||
} | ||
if (!item.bbox) { | ||
item.bbox = this.getBoxFromGeometry(geometry); | ||
} | ||
} | ||
const date = this.parseDate(node); | ||
if (date) { | ||
item.properties.time = date; | ||
} | ||
const date = this.parseDate(node); | ||
if (date) { | ||
item.properties.time = date; | ||
} | ||
return item; | ||
}); | ||
return item; | ||
}); | ||
return { | ||
totalResults: parseInt(xPath(xmlDoc, 'channel/os:totalResults/text()'), 10), | ||
startIndex: parseInt(xPath(xmlDoc, 'channel/os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt(xPath(xmlDoc, 'channel/os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: this.parseLinks(xmlDoc), | ||
records, | ||
}; | ||
}); | ||
return { | ||
totalResults: parseInt(xPath(xmlDoc, 'channel/os:totalResults/text()'), 10), | ||
startIndex: parseInt(xPath(xmlDoc, 'channel/os:startIndex/text()'), 10), | ||
itemsPerPage: parseInt(xPath(xmlDoc, 'channel/os:itemsPerPage/text()'), 10), | ||
query: {}, // TODO: | ||
links: this.parseLinks(xmlDoc), | ||
records, | ||
}; | ||
} | ||
} |
@@ -1,2 +0,3 @@ | ||
import { search } from './utils'; | ||
import { search } from './search'; | ||
import { getPromiseClass } from './config'; | ||
@@ -37,13 +38,16 @@ /** | ||
*/ | ||
fetchPage(pageIndex = 0) { | ||
// TODO: get first page index | ||
if (this._cache && this._cache[pageIndex]) { | ||
return this._cache[pageIndex]; | ||
} | ||
fetchPage(pageIndex = 0, maxCount = undefined) { | ||
// TODO: implement caching of whole pages | ||
// if (this._cache && this._cache[pageIndex]) { | ||
// return this._cache[pageIndex]; | ||
// } | ||
const parameters = Object.assign({}, this._parameters); | ||
const pageSize = this.getActualPageSize(); | ||
if (pageSize) { | ||
if (pageSize && maxCount) { | ||
parameters.count = Math.min(maxCount, pageSize); | ||
} else if (pageSize) { | ||
parameters.count = pageSize; | ||
} else if (maxCount) { | ||
parameters.count = maxCount; | ||
} | ||
@@ -62,2 +66,3 @@ | ||
.then(result => { | ||
this._totalResults = result.totalResults; | ||
if (!this._serverItemsPerPage && result.itemsPerPage) { | ||
@@ -72,3 +77,3 @@ this._serverItemsPerPage = result.itemsPerPage; | ||
* Fetches all pages from the URL. A probing request is sent to determine how | ||
* many succeding requests have to be sent. | ||
* many succeeding requests have to be sent. | ||
* @returns {Promise<SearchResult[]>} The async result of all the pages in the | ||
@@ -80,9 +85,8 @@ * search. | ||
.then(firstPage => { | ||
this._totalResults = firstPage.totalResults; | ||
const pageCount = this.getPageCount() - 1; | ||
const pageCount = this.getPageCount(); | ||
const requests = [firstPage]; | ||
for (let i = 0; i < pageCount; ++i) { | ||
for (let i = 1; i < pageCount; ++i) { | ||
requests.push(this.fetchPage(i)); | ||
} | ||
return Promise.all(requests); | ||
return getPromiseClass().all(requests); | ||
}); | ||
@@ -93,12 +97,60 @@ } | ||
* Convenience method to get the records of all pages in a single result array | ||
* @returns {Promise<Record[]>} The records of all the pages in the search. | ||
* @returns {Promise<SearchResult>} The records of all the pages in the search. | ||
*/ | ||
fetchAllRecords() { | ||
return this.fetchAllPages() | ||
.then(pages => pages.reduce((records, page) => { | ||
return records.concat(page.records); | ||
}, [])); | ||
.then(pages => { | ||
const firstPage = pages[0]; | ||
const records = pages.reduce((records, page) => { | ||
return records.concat(page.records); | ||
}, []); | ||
return { | ||
totalResults: firstPage.totalResults, | ||
startIndex: firstPage.startIndex, | ||
itemsPerPage: firstPage.itemsPerPage, | ||
records, | ||
}; | ||
}); | ||
} | ||
/** | ||
* Fetches the first X records of a search in a single search result. | ||
* @param {int} maxCount The maximum number of records to fetch. | ||
* @returns {Promise<SearchResult>} The resulting records as a promise. | ||
*/ | ||
fetchFirstRecords(maxCount) { | ||
// Get the first page | ||
return this.fetchPage(0, maxCount) | ||
.then(firstPage => { | ||
if (firstPage.itemsPerPage >= maxCount) { | ||
// return if we already have all records | ||
return firstPage; | ||
} | ||
// fetch other pages until we have the required count | ||
const requests = [firstPage]; | ||
for (let i = 1; i < maxCount / firstPage.itemsPerPage; ++i ) { | ||
let count = firstPage.itemsPerPage; | ||
if (firstPage.itemsPerPage * i > maxCount) { | ||
count = maxCount - firstPage.itemsPerPage * (i - 1); | ||
} | ||
requests.push(this.fetchPage(i, count)); | ||
} | ||
return getPromiseClass() | ||
.all(requests) | ||
.then(pages => { | ||
const records = pages.reduce((records, page) => { | ||
return records.concat(page.records); | ||
}, []); | ||
return { | ||
totalResults: firstPage.totalResults, | ||
startIndex: firstPage.startIndex, | ||
itemsPerPage: firstPage.itemsPerPage, | ||
records, | ||
}; | ||
}); | ||
}); | ||
} | ||
/** | ||
* Returns the actual page size. | ||
@@ -105,0 +157,0 @@ * @returns {int} The computed page size. |
@@ -5,3 +5,3 @@ import 'isomorphic-fetch'; | ||
import { OpenSearchPaginator } from './paginator'; | ||
import { search } from './utils'; | ||
import { search } from './search'; | ||
import { getSupportedTypes } from './formats/'; | ||
@@ -8,0 +8,0 @@ |
@@ -163,82 +163,2 @@ import parse from 'url-parse'; | ||
/** | ||
* Create a request for the given parameters | ||
* @param {object} parameterValues An object mapping the name or type to the value | ||
* @returns {Request} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Request Request} | ||
* object for the | ||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API Fetch API} | ||
*/ | ||
createRequest(parameterValues) { | ||
// check parameters | ||
Object.keys(parameterValues).forEach(key => { | ||
if (!this._parametersByType.hasOwnProperty(key) | ||
&& !this._parametersByName.hasOwnProperty(key)) { | ||
throw new Error(`Invalid parameter '${key}'.`); | ||
} | ||
}); | ||
const missingMandatoryParameters = this.parameters.filter( | ||
(parameter) => parameter.mandatory | ||
&& !parameterValues.hasOwnProperty(parameter.name) | ||
&& !parameterValues.hasOwnProperty(parameter.type) | ||
).map((parameter) => parameter.type); | ||
const missingOptionalParameters = this.parameters.filter( | ||
(parameter) => !parameter.mandatory | ||
&& !parameterValues.hasOwnProperty(parameter.name) | ||
&& !parameterValues.hasOwnProperty(parameter.type) | ||
).map((parameter) => parameter.type); | ||
if (missingMandatoryParameters.length) { | ||
throw new Error(`Missing mandatory parameters: ${missingMandatoryParameters.join(', ')}`); | ||
} | ||
if (this.method === 'GET') { | ||
// insert parameters into URL template | ||
let url = this.url; | ||
Object.keys(parameterValues).forEach(key => { | ||
const parameter = this._parametersByType[key] || this._parametersByName[key]; | ||
url = url.replace( | ||
new RegExp(`{${parameter.type}[?]?}`), | ||
parameter.serialize(parameterValues[key]) | ||
); | ||
}); | ||
missingOptionalParameters.forEach(type => { | ||
url = url.replace(new RegExp(`{${type}[?]?}`), ''); | ||
}); | ||
return new Request(url); | ||
} | ||
// for POST | ||
const enctype = this.enctype || 'application/x-www-form-urlencoded'; | ||
let body = null; | ||
if (enctype === 'application/x-www-form-urlencoded') { | ||
body = Object.keys(parameterValues).map(key => { | ||
const param = (this._parametersByType[key] || this._parametersByName[key]); | ||
const k = encodeURIComponent(param.name); | ||
const v = encodeURIComponent(param.serialize(parameterValues[key])); | ||
return `${k}=${v}`; | ||
}).join('&'); | ||
} else if (enctype === 'multipart/form-data') { | ||
body = new FormData(); | ||
Object.keys(parameterValues).forEach(key => { | ||
const param = (this._parametersByType[key] || this._parametersByName[key]); | ||
body.append(param.name, param.serialize(parameterValues[key])); | ||
}); | ||
} else { | ||
throw new Error(`Unsupported enctype '${enctype}'.`); | ||
} | ||
return new Request(this.url, { | ||
method: this.method, | ||
headers: { | ||
'Content-Type': enctype, | ||
}, | ||
body, | ||
}); | ||
} | ||
/** | ||
* Construct a {@link OpenSearchUrl} from a DOMNode | ||
@@ -245,0 +165,0 @@ * @param {DOMNode} node The DOM node from the OpenSearchDescription XML document |
import 'isomorphic-fetch'; | ||
import xpath from 'xpath'; | ||
import { getFormat } from './formats' | ||
export function parseURLQuery(url) { | ||
@@ -137,3 +135,3 @@ const search = (url.indexOf('?') === -1) ? url : url.substring(url.indexOf('?')); | ||
case 'GeometryCollection': | ||
return 'GEOMETRYCOLLECTION(' + gj.geometries.map(stringify).join(', ') + ')'; | ||
return 'GEOMETRYCOLLECTION(' + gj.geometries.map(toWKT).join(', ') + ')'; | ||
default: | ||
@@ -143,24 +141,1 @@ throw new Error('stringify requires a valid GeoJSON Feature or geometry object as input'); | ||
} | ||
/** | ||
* Performs a search for the given URL and parameters. | ||
* @param {OpenSearchUrl} url The URL to search on. | ||
* @param {object} [parameters={}] The search parameters. | ||
* @param {string} [type=null] The response format. | ||
* @param {boolean} [raw=false] Whether the response shall be parsed or returned raw. | ||
* @returns {Promise<array>|Promise<Response>} The search result as a Promise | ||
*/ | ||
export function search(url, parameters = {}, type = null, raw = false) { | ||
return fetchAndCheck(url.createRequest(parameters)) | ||
.then(response => { | ||
if (raw) { | ||
return response; | ||
} | ||
const format = getFormat(type || url.type); | ||
if (!format) { | ||
throw new Error(`Could not parse response of type '${type}'.`); | ||
} | ||
return format.parse(response); | ||
}); | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1356571
101
4419