datapackage
Version:
Utilities to work with Data Packages as defined on specs.frictionlessdata.io
1,232 lines (992 loc) • 36.7 kB
JavaScript
'use strict';
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
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; }; }();
var createByteStream = function () {
var _ref14 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(source, remote) {
var stream, response, _response;
return regeneratorRuntime.wrap(function _callee8$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
stream = void 0;
// Remote source
if (!remote) {
_context8.next = 17;
break;
}
if (!config.IS_BROWSER) {
_context8.next = 11;
break;
}
_context8.next = 5;
return axios.get(source);
case 5:
response = _context8.sent;
stream = new Readable();
stream.push(response.data);
stream.push(null);
_context8.next = 15;
break;
case 11:
_context8.next = 13;
return axios.get(source, { responseType: 'stream' });
case 13:
_response = _context8.sent;
stream = _response.data;
case 15:
_context8.next = 22;
break;
case 17:
if (!config.IS_BROWSER) {
_context8.next = 21;
break;
}
throw new DataPackageError('Local paths are not supported in the browser');
case 21:
stream = fs.createReadStream(source);
case 22:
return _context8.abrupt('return', stream);
case 23:
case 'end':
return _context8.stop();
}
}
}, _callee8, this);
}));
return function createByteStream(_x9, _x10) {
return _ref14.apply(this, arguments);
};
}();
// System
function _objectEntries(obj) {
var entries = [];
var keys = Object.keys(obj);
for (var k = 0; k < keys.length; ++k) entries.push([keys[k], obj[keys[k]]]);
return entries;
}
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var fs = require('fs');
var axios = require('axios');
var _require = require('buffer'),
Buffer = _require.Buffer;
var pathModule = require('path');
var urljoin = require('url-join');
var _require2 = require('stream'),
Readable = _require2.Readable;
var assign = require('lodash/assign');
var isEqual = require('lodash/isEqual');
var isArray = require('lodash/isArray');
var isObject = require('lodash/isObject');
var isBoolean = require('lodash/isBoolean');
var cloneDeep = require('lodash/cloneDeep');
var isUndefined = require('lodash/isUndefined');
var S2A = require('stream-to-async-iterator').default;
var _require3 = require('tableschema'),
Table = _require3.Table,
Schema = _require3.Schema;
var _require4 = require('./errors'),
DataPackageError = _require4.DataPackageError;
var _require5 = require('./profile'),
Profile = _require5.Profile;
var helpers = require('./helpers');
var config = require('./config');
// Module API
/**
* Resource representation
*/
var Resource = function () {
_createClass(Resource, [{
key: 'iter',
/**
* Iterate through the table data
*
* > Only for tabular resources
*
* And emits rows cast based on table schema (async for loop).
* With a `stream` flag instead of async iterator a Node stream will be returned.
* Data casting can be disabled.
*
* @param {boolean} keyed - iter keyed rows
* @param {boolean} extended - iter extended rows
* @param {boolean} cast - disable data casting if false
* @param {boolean} forceCast - instead of raising on the first row with cast error
* return an error object to replace failed row. It will allow
* to iterate over the whole data file even if it's not compliant to the schema.
* Example of output stream:
* `[['val1', 'val2'], TableSchemaError, ['val3', 'val4'], ...]`
* @param {boolean} relations - if true foreign key fields will be
* checked and resolved to its references
* @param {boolean} stream - return Node Readable Stream of table rows
* @throws {TableSchemaError} raises any error occurred in this process
* @returns {(AsyncIterator|Stream)} async iterator/stream of rows:
* - `[value1, value2]` - base
* - `{header1: value1, header2: value2}` - keyed
* - `[rowNumber, [header1, header2], [value1, value2]]` - extended
*/
value: function () {
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref2$relations = _ref2.relations,
relations = _ref2$relations === undefined ? false : _ref2$relations,
options = _objectWithoutProperties(_ref2, ['relations']);
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (this.tabular) {
_context.next = 2;
break;
}
throw new DataPackageError('Methods iter/read are not supported for non tabular data');
case 2:
if (!relations) {
_context.next = 6;
break;
}
_context.next = 5;
return this._getRelations();
case 5:
relations = _context.sent;
case 6:
_context.next = 8;
return this._getTable().iter(_extends({ relations: relations }, options));
case 8:
return _context.abrupt('return', _context.sent);
case 9:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function iter() {
return _ref.apply(this, arguments);
}
return iter;
}()
/**
* Read the table data into memory
*
* > Only for tabular resources; the API is the same as `resource.iter` has except for:
*
* @param {integer} limit - limit of rows to read
* @returns {(Array[]|Object[])} list of rows:
* - `[value1, value2]` - base
* - `{header1: value1, header2: value2}` - keyed
* - `[rowNumber, [header1, header2], [value1, value2]]` - extended
*/
}, {
key: 'read',
value: function () {
var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref4$relations = _ref4.relations,
relations = _ref4$relations === undefined ? false : _ref4$relations,
options = _objectWithoutProperties(_ref4, ['relations']);
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (this.tabular) {
_context2.next = 2;
break;
}
throw new DataPackageError('Methods iter/read are not supported for non tabular data');
case 2:
if (!relations) {
_context2.next = 6;
break;
}
_context2.next = 5;
return this._getRelations();
case 5:
relations = _context2.sent;
case 6:
_context2.next = 8;
return this._getTable().read(_extends({ relations: relations }, options));
case 8:
return _context2.abrupt('return', _context2.sent);
case 9:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function read() {
return _ref3.apply(this, arguments);
}
return read;
}()
/**
* It checks foreign keys and raises an exception if there are integrity issues.
*
* > Only for tabular resources
*
* @throws {DataPackageError} raises if there are integrity issues
* @returns {boolean} returns True if no issues
*/
}, {
key: 'checkRelations',
value: function () {
var _ref5 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return this.read({ relations: true });
case 2:
return _context3.abrupt('return', true);
case 3:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
function checkRelations() {
return _ref5.apply(this, arguments);
}
return checkRelations;
}()
/**
* Iterate over data chunks as bytes. If `stream` is true Node Stream will be returned.
*
* @param {boolean} stream - Node Stream will be returned
* @returns {Iterator|Stream} returns Iterator/Stream
*/
}, {
key: 'rawIter',
value: function () {
var _ref6 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref7$stream = _ref7.stream,
stream = _ref7$stream === undefined ? false : _ref7$stream;
var byteStream;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
if (!this.inline) {
_context4.next = 2;
break;
}
throw new DataPackageError('Methods iter/read are not supported for inline data');
case 2:
_context4.next = 4;
return createByteStream(this.source, this.remote);
case 4:
byteStream = _context4.sent;
return _context4.abrupt('return', stream ? byteStream : new S2A(byteStream));
case 6:
case 'end':
return _context4.stop();
}
}
}, _callee4, this);
}));
function rawIter() {
return _ref6.apply(this, arguments);
}
return rawIter;
}()
/**
* Returns resource data as bytes.
*
* @returns {Buffer} returns Buffer with resource data
*/
}, {
key: 'rawRead',
value: function rawRead() {
var _this = this;
return new Promise(function (resolve) {
var bytes = void 0;
_this.rawIter({ stream: true }).then(function (stream) {
stream.on('data', function (data) {
bytes = bytes ? Buffer.concat([bytes, data]) : data;
});
stream.on('end', function () {
return resolve(bytes);
});
});
});
}
/**
* Infer resource metadata like name, format, mediatype, encoding, schema and profile.
*
* It commits this changes into resource instance.
*
* @returns {Object} returns resource descriptor
*/
}, {
key: 'infer',
value: function () {
var _ref8 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
var descriptor, jschardet, iterator, bytes, encoding;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
descriptor = cloneDeep(this._currentDescriptor);
// Blank -> Stop
if (!this._sourceInspection.blank) {
_context5.next = 3;
break;
}
return _context5.abrupt('return', descriptor);
case 3:
// Name
if (!descriptor.name) {
descriptor.name = this._sourceInspection.name;
}
// Only for non inline
if (this.inline) {
_context5.next = 18;
break;
}
// Format
if (!descriptor.format) {
descriptor.format = this._sourceInspection.format;
}
// Mediatype
if (!descriptor.mediatype) {
descriptor.mediatype = 'text/' + descriptor.format;
}
// Encoding
if (!(descriptor.encoding === config.DEFAULT_RESOURCE_ENCODING)) {
_context5.next = 18;
break;
}
if (config.IS_BROWSER) {
_context5.next = 18;
break;
}
jschardet = require('jschardet');
_context5.next = 12;
return this.rawIter();
case 12:
iterator = _context5.sent;
_context5.next = 15;
return iterator.next();
case 15:
bytes = _context5.sent.value;
encoding = jschardet.detect(bytes).encoding.toLowerCase();
descriptor.encoding = encoding === 'ascii' ? 'utf-8' : encoding;
case 18:
if (descriptor.schema) {
_context5.next = 23;
break;
}
if (!this.tabular) {
_context5.next = 23;
break;
}
_context5.next = 22;
return this._getTable().infer();
case 22:
descriptor.schema = _context5.sent;
case 23:
// Profile
if (descriptor.profile === config.DEFAULT_RESOURCE_PROFILE) {
if (this.tabular) {
descriptor.profile = 'tabular-data-resource';
}
}
// Save descriptor
this._currentDescriptor = descriptor;
this._build();
return _context5.abrupt('return', descriptor);
case 27:
case 'end':
return _context5.stop();
}
}
}, _callee5, this);
}));
function infer() {
return _ref8.apply(this, arguments);
}
return infer;
}()
/**
* Update resource instance if there are in-place changes in the descriptor.
*
* @param {boolean} strict - alter `strict` mode for further work
* @throws DataPackageError raises error if something goes wrong
* @returns {boolean} returns true on success and false if not modified
*/
}, {
key: 'commit',
value: function commit() {
var _ref9 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
strict = _ref9.strict;
if (isBoolean(strict)) this._strict = strict;else if (isEqual(this._currentDescriptor, this._nextDescriptor)) return false;
this._currentDescriptor = cloneDeep(this._nextDescriptor);
this._table = null;
this._build();
return true;
}
/**
* Save resource to target destination.
*
* > For now only descriptor will be saved.
*
* @param {string} target - path where to save a resource
* @throws {DataPackageError} raises error if something goes wrong
* @returns {boolean} returns true on success
*/
}, {
key: 'save',
value: function save(target) {
var _this2 = this;
return new Promise(function (resolve, reject) {
var contents = JSON.stringify(_this2._currentDescriptor, null, 4);
fs.writeFile(target, contents, function (error) {
return !error ? resolve() : reject(error);
});
});
}
// Private
}, {
key: 'valid',
/**
* Validation status
*
* It always `true` in strict mode.
*
* @returns {Boolean} returns validation status
*/
get: function get() {
return this._errors.length === 0;
}
/**
* Validation errors
*
* It always empty in strict mode.
*
* @returns {Error[]} returns validation errors
*/
}, {
key: 'errors',
get: function get() {
return this._errors;
}
/**
* Profile
*
* @returns {Profile}
*/
}, {
key: 'profile',
get: function get() {
return this._profile;
}
/**
* Descriptor
*
* @returns {Object} schema descriptor
*/
}, {
key: 'descriptor',
get: function get() {
// Never use this.descriptor inside this class (!!!)
return this._nextDescriptor;
}
/**
* Name
*
* @returns {string}
*/
}, {
key: 'name',
get: function get() {
return this._currentDescriptor.name;
}
/**
* Whether resource is inline
*
* @returns {boolean}
*/
}, {
key: 'inline',
get: function get() {
return !!this._sourceInspection.inline;
}
/**
* Whether resource is local
*
* @returns {boolean}
*/
}, {
key: 'local',
get: function get() {
return !!this._sourceInspection.local;
}
/**
* Whether resource is remote
*
* @returns {boolean}
*/
}, {
key: 'remote',
get: function get() {
return !!this._sourceInspection.remote;
}
/**
* Whether resource is multipart
*
* @returns {boolean}
*/
}, {
key: 'multipart',
get: function get() {
return !!this._sourceInspection.multipart;
}
/**
* Whether resource is tabular
*
* @returns {boolean}
*/
}, {
key: 'tabular',
get: function get() {
if (this._currentDescriptor.profile === 'tabular-data-resource') return true;
if (!this._strict) {
if (config.TABULAR_FORMATS.includes(this._currentDescriptor.format)) return true;
if (this._sourceInspection.tabular) return true;
}
return false;
}
/**
* Source
*
* Combination of `resource.source` and `resource.inline/local/remote/multipart`
* provides predictable interface to work with resource data.
*
* @returns {Array|string}
*/
}, {
key: 'source',
get: function get() {
return this._sourceInspection.source;
}
/**
* Headers
*
* > Only for tabular resources
*
* @returns {string[]} data source headers
*/
}, {
key: 'headers',
get: function get() {
if (!this.tabular) return null;
return this._getTable().headers;
}
/**
* Schema
*
* > Only for tabular resources
*
* @returns {tableschema.Schema}
*/
}, {
key: 'schema',
get: function get() {
if (!this.tabular) return null;
return this._getTable().schema;
}
}], [{
key: 'load',
// Public
/**
* Factory method to instantiate `Resource` class.
*
* This method is async and it should be used with await keyword or as a `Promise`.
*
* @param {string|Object} descriptor - resource descriptor as local path, url or object
* @param {string} basePath - base path for all relative paths
* @param {boolean} strict - strict flag to alter validation behavior.
* Setting it to `true` leads to throwing errors on
* any operation with invalid descriptor
* @throws {DataPackageError} raises error if something goes wrong
* @returns {Resource} returns resource class instance
*/
value: function () {
var _ref10 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6() {
var descriptor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref11 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
basePath = _ref11.basePath,
_ref11$strict = _ref11.strict,
strict = _ref11$strict === undefined ? false : _ref11$strict;
return regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
// Get base path
if (isUndefined(basePath)) {
basePath = helpers.locateDescriptor(descriptor);
}
// Process descriptor
_context6.next = 3;
return helpers.retrieveDescriptor(descriptor);
case 3:
descriptor = _context6.sent;
_context6.next = 6;
return helpers.dereferenceResourceDescriptor(descriptor, basePath);
case 6:
descriptor = _context6.sent;
return _context6.abrupt('return', new Resource(descriptor, { basePath: basePath, strict: strict }));
case 8:
case 'end':
return _context6.stop();
}
}
}, _callee6, this);
}));
function load() {
return _ref10.apply(this, arguments);
}
return load;
}()
}]);
function Resource() {
var descriptor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref12 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
basePath = _ref12.basePath,
_ref12$strict = _ref12.strict,
strict = _ref12$strict === undefined ? false : _ref12$strict,
dataPackage = _ref12.dataPackage;
_classCallCheck(this, Resource);
// Handle deprecated resource.path.url
if (descriptor.url) {
console.warn('Resource property "url: <url>" is deprecated.\n Please use "path: <url>" instead.');
descriptor.path = descriptor.url;
delete descriptor.url;
}
// Set attributes
this._currentDescriptor = cloneDeep(descriptor);
this._nextDescriptor = cloneDeep(descriptor);
this._dataPackage = dataPackage;
this._basePath = basePath;
this._relations = null;
this._strict = strict;
this._errors = [];
// Build resource
this._build();
}
_createClass(Resource, [{
key: '_build',
value: function _build() {
// Process descriptor
this._currentDescriptor = helpers.expandResourceDescriptor(this._currentDescriptor);
this._nextDescriptor = cloneDeep(this._currentDescriptor);
// Inspect source
this._sourceInspection = inspectSource(this._currentDescriptor.data, this._currentDescriptor.path, this._basePath);
// Instantiate profile
this._profile = new Profile(this._currentDescriptor.profile);
// Validate descriptor
this._errors = [];
var _profile$validate = this._profile.validate(this._currentDescriptor),
valid = _profile$validate.valid,
errors = _profile$validate.errors;
if (!valid) {
this._errors = errors;
if (this._strict) {
var message = 'There are ' + errors.length + ' validation errors (see \'error.errors\')';
throw new DataPackageError(message, errors);
}
}
}
}, {
key: '_getTable',
value: function _getTable() {
if (!this._table) {
// Resource -> Regular
if (!this.tabular) {
return null;
}
// Resource -> Multipart
if (this.multipart) {
throw new DataPackageError('Resource.table does not support multipart resources');
}
// Resource -> Tabular
var options = {};
var descriptor = this._currentDescriptor;
options.format = descriptor.format || 'csv';
options.encoding = descriptor.encoding;
var dialect = descriptor.dialect;
if (dialect) {
if (dialect.header === false || config.DEFAULT_DIALECT.header === false) {
var fields = (descriptor.schema || {}).fields || [];
options.headers = fields.length ? fields.map(function (field) {
return field.name;
}) : null;
}
helpers.validateDialect(dialect);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = DIALECT_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var key = _step.value;
if (dialect[key]) options[key.toLowerCase()] = dialect[key];
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
var schemaDescriptor = this._currentDescriptor.schema;
var schema = schemaDescriptor ? new Schema(schemaDescriptor) : null;
this._table = new Table(this.source, _extends({ schema: schema }, options));
}
return this._table;
}
}, {
key: '_getRelations',
value: function () {
var _ref13 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() {
var resources, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, fk, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, field, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, _step4$value, resource, data;
return regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
if (this._relations) {
_context7.next = 80;
break;
}
// Prepare resources
resources = {};
if (!(this._getTable() && this._getTable().schema)) {
_context7.next = 47;
break;
}
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
_context7.prev = 6;
_iterator2 = this._getTable().schema.foreignKeys[Symbol.iterator]();
case 8:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
_context7.next = 33;
break;
}
fk = _step2.value;
resources[fk.reference.resource] = resources[fk.reference.resource] || [];
_iteratorNormalCompletion3 = true;
_didIteratorError3 = false;
_iteratorError3 = undefined;
_context7.prev = 14;
for (_iterator3 = fk.reference.fields[Symbol.iterator](); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
field = _step3.value;
resources[fk.reference.resource].push(field);
}
_context7.next = 22;
break;
case 18:
_context7.prev = 18;
_context7.t0 = _context7['catch'](14);
_didIteratorError3 = true;
_iteratorError3 = _context7.t0;
case 22:
_context7.prev = 22;
_context7.prev = 23;
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
case 25:
_context7.prev = 25;
if (!_didIteratorError3) {
_context7.next = 28;
break;
}
throw _iteratorError3;
case 28:
return _context7.finish(25);
case 29:
return _context7.finish(22);
case 30:
_iteratorNormalCompletion2 = true;
_context7.next = 8;
break;
case 33:
_context7.next = 39;
break;
case 35:
_context7.prev = 35;
_context7.t1 = _context7['catch'](6);
_didIteratorError2 = true;
_iteratorError2 = _context7.t1;
case 39:
_context7.prev = 39;
_context7.prev = 40;
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
case 42:
_context7.prev = 42;
if (!_didIteratorError2) {
_context7.next = 45;
break;
}
throw _iteratorError2;
case 45:
return _context7.finish(42);
case 46:
return _context7.finish(39);
case 47:
// Fill relations
this._relations = {};
_iteratorNormalCompletion4 = true;
_didIteratorError4 = false;
_iteratorError4 = undefined;
_context7.prev = 51;
_iterator4 = _objectEntries(resources)[Symbol.iterator]();
case 53:
if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
_context7.next = 66;
break;
}
_step4$value = _slicedToArray(_step4.value, 1), resource = _step4$value[0];
if (!(resource && !this._dataPackage)) {
_context7.next = 57;
break;
}
return _context7.abrupt('continue', 63);
case 57:
this._relations[resource] = this._relations[resource] || [];
data = resource ? this._dataPackage.getResource(resource) : this;
if (!data.tabular) {
_context7.next = 63;
break;
}
_context7.next = 62;
return data.read({ keyed: true });
case 62:
this._relations[resource] = _context7.sent;
case 63:
_iteratorNormalCompletion4 = true;
_context7.next = 53;
break;
case 66:
_context7.next = 72;
break;
case 68:
_context7.prev = 68;
_context7.t2 = _context7['catch'](51);
_didIteratorError4 = true;
_iteratorError4 = _context7.t2;
case 72:
_context7.prev = 72;
_context7.prev = 73;
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
case 75:
_context7.prev = 75;
if (!_didIteratorError4) {
_context7.next = 78;
break;
}
throw _iteratorError4;
case 78:
return _context7.finish(75);
case 79:
return _context7.finish(72);
case 80:
return _context7.abrupt('return', this._relations);
case 81:
case 'end':
return _context7.stop();
}
}
}, _callee7, this, [[6, 35, 39, 47], [14, 18, 22, 30], [23,, 25, 29], [40,, 42, 46], [51, 68, 72, 80], [73,, 75, 79]]);
}));
function _getRelations() {
return _ref13.apply(this, arguments);
}
return _getRelations;
}()
// Deprecated
}, {
key: 'table',
get: function get() {
return this._getTable();
}
}]);
return Resource;
}();
// Internal
var DIALECT_KEYS = ['delimiter', 'doubleQuote', 'lineTerminator', 'quoteChar', 'escapeChar', 'skipInitialSpace'];
function inspectSource(data, path, basePath) {
var inspection = {};
// Normalize path
if (path && !isArray(path)) {
path = [path];
}
// Blank
if (!data && !path) {
inspection.source = null;
inspection.blank = true;
// Inline
} else if (data) {
inspection.source = data;
inspection.inline = true;
inspection.tabular = isArray(data) && data.every(isObject);
// Local/Remote
} else if (path.length === 1) {
// Remote
if (helpers.isRemotePath(path[0])) {
inspection.source = path[0];
inspection.remote = true;
} else if (basePath && helpers.isRemotePath(basePath)) {
inspection.source = urljoin(basePath, path[0]);
inspection.remote = true;
// Local
} else {
// Path is not safe
if (!helpers.isSafePath(path[0])) {
throw new DataPackageError('Local path "' + path[0] + '" is not safe');
}
// Not base path
if (!basePath) {
throw new DataPackageError('Local path "' + path[0] + '" requires base path');
}
inspection.source = [basePath, path[0]].join('/');
inspection.local = true;
}
// Inspect
inspection.format = pathModule.extname(path[0]).slice(1);
inspection.name = pathModule.basename(path[0], '.' + inspection.format);
inspection.tabular = config.TABULAR_FORMATS.includes(inspection.format);
// Multipart Local/Remote
} else if (path.length > 1) {
var inspections = path.map(function (item) {
return inspectSource(null, item, basePath);
});
assign(inspection, inspections[0]);
inspection.source = inspections.map(function (item) {
return item.source;
});
inspection.multipart = true;
}
return inspection;
}
module.exports = {
Resource: Resource
};