UNPKG

datapackage

Version:

Utilities to work with Data Packages as defined on specs.frictionlessdata.io

1,232 lines (992 loc) 36.7 kB
'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 };