@jbrowse/plugin-gff3 1.5.0 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,16 @@
1
- import { Instance } from 'mobx-state-tree';
2
1
  import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
3
- import { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
4
- import PluginManager from '@jbrowse/core/PluginManager';
5
2
  import { NoAssemblyRegion } from '@jbrowse/core/util/types';
6
3
  import IntervalTree from '@flatten-js/interval-tree';
7
4
  import { Feature } from '@jbrowse/core/util/simpleFeature';
8
- import { GenericFilehandle } from 'generic-filehandle';
9
- import MyConfigSchema from './configSchema';
10
5
  export default class extends BaseFeatureDataAdapter {
11
- protected gffFeatures?: Promise<Record<string, IntervalTree>>;
12
- protected uri: string;
13
- protected filehandle: GenericFilehandle;
14
- constructor(config: Instance<typeof MyConfigSchema>, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
6
+ protected gffFeatures?: Promise<{
7
+ header: string;
8
+ intervalTree: Record<string, IntervalTree>;
9
+ }>;
10
+ private loadDataP;
15
11
  private loadData;
16
12
  getRefNames(opts?: BaseOptions): Promise<string[]>;
13
+ getHeader(): Promise<string>;
17
14
  getFeatures(query: NoAssemblyRegion, opts?: BaseOptions): import("rxjs").Observable<Feature>;
18
15
  private featureData;
19
16
  freeResources(): void;
@@ -8,6 +8,7 @@ var AdapterType = _interopDefault(require('@jbrowse/core/pluggableElementTypes/A
8
8
  var Plugin = _interopDefault(require('@jbrowse/core/Plugin'));
9
9
  var mobxStateTree = require('mobx-state-tree');
10
10
  var configuration = require('@jbrowse/core/configuration');
11
+ var tracks = require('@jbrowse/core/util/tracks');
11
12
  var BaseAdapter = require('@jbrowse/core/data_adapters/BaseAdapter');
12
13
  var range = require('@jbrowse/core/util/range');
13
14
  var io = require('@jbrowse/core/util/io');
@@ -16,20 +17,16 @@ var SimpleFeature = _interopDefault(require('@jbrowse/core/util/simpleFeature'))
16
17
  var tabix = require('@gmod/tabix');
17
18
  var gff = _interopDefault(require('@gmod/gff'));
18
19
  var IntervalTree = _interopDefault(require('@flatten-js/interval-tree'));
20
+ var bgzfFilehandle = require('@gmod/bgzf-filehandle');
19
21
 
20
22
  function ownKeys(object, enumerableOnly) {
21
23
  var keys = Object.keys(object);
22
24
 
23
25
  if (Object.getOwnPropertySymbols) {
24
26
  var symbols = Object.getOwnPropertySymbols(object);
25
-
26
- if (enumerableOnly) {
27
- symbols = symbols.filter(function (sym) {
28
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
29
- });
30
- }
31
-
32
- keys.push.apply(keys, symbols);
27
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
28
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
29
+ })), keys.push.apply(keys, symbols);
33
30
  }
34
31
 
35
32
  return keys;
@@ -37,19 +34,12 @@ function ownKeys(object, enumerableOnly) {
37
34
 
38
35
  function _objectSpread2(target) {
39
36
  for (var i = 1; i < arguments.length; i++) {
40
- var source = arguments[i] != null ? arguments[i] : {};
41
-
42
- if (i % 2) {
43
- ownKeys(Object(source), true).forEach(function (key) {
44
- _defineProperty(target, key, source[key]);
45
- });
46
- } else if (Object.getOwnPropertyDescriptors) {
47
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
48
- } else {
49
- ownKeys(Object(source)).forEach(function (key) {
50
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
51
- });
52
- }
37
+ var source = null != arguments[i] ? arguments[i] : {};
38
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
39
+ _defineProperty(target, key, source[key]);
40
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
41
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
42
+ });
53
43
  }
54
44
 
55
45
  return target;
@@ -110,6 +100,9 @@ function _defineProperties(target, props) {
110
100
  function _createClass(Constructor, protoProps, staticProps) {
111
101
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
112
102
  if (staticProps) _defineProperties(Constructor, staticProps);
103
+ Object.defineProperty(Constructor, "prototype", {
104
+ writable: false
105
+ });
113
106
  return Constructor;
114
107
  }
115
108
 
@@ -133,12 +126,15 @@ function _inherits(subClass, superClass) {
133
126
  throw new TypeError("Super expression must either be null or a function");
134
127
  }
135
128
 
136
- subClass.prototype = Object.create(superClass && superClass.prototype, {
137
- constructor: {
138
- value: subClass,
139
- writable: true,
140
- configurable: true
141
- }
129
+ Object.defineProperty(subClass, "prototype", {
130
+ value: Object.create(superClass && superClass.prototype, {
131
+ constructor: {
132
+ value: subClass,
133
+ writable: true,
134
+ configurable: true
135
+ }
136
+ }),
137
+ writable: false
142
138
  });
143
139
  if (superClass) _setPrototypeOf(subClass, superClass);
144
140
  }
@@ -339,6 +335,28 @@ var _default = /*#__PURE__*/function (_Plugin) {
339
335
  }
340
336
  });
341
337
  });
338
+ pluginManager.addToExtensionPoint('Core-guessAdapterForLocation', function (adapterGuesser) {
339
+ return function (file, index, adapterHint) {
340
+ var regexGuess = /\.gff3?\.b?gz$/i;
341
+ var adapterName = 'Gff3TabixAdapter';
342
+ var fileName = tracks.getFileName(file);
343
+ var indexName = index && tracks.getFileName(index);
344
+
345
+ if (regexGuess.test(fileName) || adapterHint === adapterName) {
346
+ return {
347
+ type: adapterName,
348
+ bamLocation: file,
349
+ gffGzLocation: file,
350
+ index: {
351
+ location: index || tracks.makeIndex(file, '.tbi'),
352
+ indexType: tracks.makeIndexType(indexName, 'CSI', 'TBI')
353
+ }
354
+ };
355
+ }
356
+
357
+ return adapterGuesser(file, index, adapterHint);
358
+ };
359
+ });
342
360
  pluginManager.addAdapterType(function () {
343
361
  return new AdapterType({
344
362
  name: 'Gff3Adapter',
@@ -350,6 +368,22 @@ var _default = /*#__PURE__*/function (_Plugin) {
350
368
  }
351
369
  });
352
370
  });
371
+ pluginManager.addToExtensionPoint('Core-guessAdapterForLocation', function (adapterGuesser) {
372
+ return function (file, index, adapterHint) {
373
+ var regexGuess = /\.gff3?$/i;
374
+ var adapterName = 'Gff3Adapter';
375
+ var fileName = tracks.getFileName(file);
376
+
377
+ if (regexGuess.test(fileName) || adapterHint === adapterName) {
378
+ return {
379
+ type: adapterName,
380
+ gffLocation: file
381
+ };
382
+ }
383
+
384
+ return adapterGuesser(file, index, adapterHint);
385
+ };
386
+ });
353
387
  }
354
388
  }]);
355
389
 
@@ -1261,9 +1295,6 @@ var _default$1 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1261
1295
  break;
1262
1296
  }
1263
1297
 
1264
- // console.log(
1265
- // `redispatching ${query.start}-${query.end} => ${minStart}-${maxEnd}`,
1266
- // )
1267
1298
  // make a new feature callback to only return top-level features
1268
1299
  // in the original query range
1269
1300
  this.getFeaturesHelper(_objectSpread2(_objectSpread2({}, query), {}, {
@@ -1340,6 +1371,7 @@ var _default$1 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1340
1371
  return featureLocs.map(function (featureLoc) {
1341
1372
  return new SimpleFeature({
1342
1373
  data: _this4.featureData(featureLoc),
1374
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1343
1375
  id: "".concat(_this4.id, "-offset-").concat(featureLoc.attributes._lineHash[0])
1344
1376
  });
1345
1377
  });
@@ -1353,12 +1385,15 @@ var _default$1 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1353
1385
 
1354
1386
  f.start -= 1; // convert to interbase
1355
1387
 
1356
- f.strand = {
1357
- '+': 1,
1358
- '-': -1,
1359
- '.': 0,
1360
- '?': undefined
1361
- }[data.strand]; // convert strand
1388
+ if (data.strand === '+') {
1389
+ f.strand = 1;
1390
+ } else if (data.strand === '-') {
1391
+ f.strand = -1;
1392
+ } else if (data.strand === '.') {
1393
+ f.strand = 0;
1394
+ } else {
1395
+ f.strand = undefined;
1396
+ }
1362
1397
 
1363
1398
  f.phase = Number(data.phase);
1364
1399
  f.refName = data.seq_id;
@@ -1372,7 +1407,8 @@ var _default$1 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1372
1407
  }
1373
1408
 
1374
1409
  var defaultFields = ['start', 'end', 'seq_id', 'score', 'type', 'source', 'phase', 'strand'];
1375
- Object.keys(data.attributes).forEach(function (a) {
1410
+ var dataAttributes = data.attributes || {};
1411
+ Object.keys(dataAttributes).forEach(function (a) {
1376
1412
  var b = a.toLowerCase();
1377
1413
 
1378
1414
  if (defaultFields.includes(b)) {
@@ -1381,8 +1417,8 @@ var _default$1 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1381
1417
  b += '2';
1382
1418
  }
1383
1419
 
1384
- if (data.attributes[a] !== null) {
1385
- var attr = data.attributes[a];
1420
+ if (dataAttributes[a] !== null) {
1421
+ var attr = dataAttributes[a];
1386
1422
 
1387
1423
  if (Array.isArray(attr) && attr.length === 1) {
1388
1424
  var _attr = attr;
@@ -1415,7 +1451,9 @@ var _default$1 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1415
1451
  }
1416
1452
  }, {
1417
1453
  key: "freeResources",
1418
- value: function freeResources() {}
1454
+ value: function
1455
+ /* { region } */
1456
+ freeResources() {}
1419
1457
  }]);
1420
1458
 
1421
1459
  return _default;
@@ -1426,88 +1464,141 @@ var Gff3TabixAdapter = {
1426
1464
  'default': _default$1
1427
1465
  };
1428
1466
 
1467
+ function isGzip(buf) {
1468
+ return buf[0] === 31 && buf[1] === 139 && buf[2] === 8;
1469
+ }
1470
+
1429
1471
  var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1430
1472
  _inherits(_default, _BaseFeatureDataAdapt);
1431
1473
 
1432
1474
  var _super = /*#__PURE__*/_createSuper(_default);
1433
1475
 
1434
- function _default(config, getSubAdapter, pluginManager) {
1435
- var _this;
1436
-
1476
+ function _default() {
1437
1477
  _classCallCheck(this, _default);
1438
1478
 
1439
- _this = _super.call(this, config, getSubAdapter, pluginManager);
1440
- var gffLocation = configuration.readConfObject(config, 'gffLocation');
1441
- var uri = gffLocation.uri;
1442
- _this.uri = uri;
1443
- _this.filehandle = io.openLocation(gffLocation, _this.pluginManager);
1444
- return _this;
1479
+ return _super.apply(this, arguments);
1445
1480
  }
1446
1481
 
1447
1482
  _createClass(_default, [{
1448
- key: "loadData",
1483
+ key: "loadDataP",
1449
1484
  value: function () {
1450
- var _loadData = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
1451
- var _this2 = this;
1452
-
1453
- var _yield$this$filehandl, size;
1485
+ var _loadDataP = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
1486
+ var _this = this;
1454
1487
 
1488
+ var buffer, buf, data, lines, headerLines, i, header, feats, intervalTree;
1455
1489
  return runtime_1.wrap(function _callee$(_context) {
1456
1490
  while (1) {
1457
1491
  switch (_context.prev = _context.next) {
1458
1492
  case 0:
1459
1493
  _context.next = 2;
1460
- return this.filehandle.stat();
1494
+ return io.openLocation(configuration.readConfObject(this.config, 'gffLocation'), this.pluginManager).readFile();
1461
1495
 
1462
1496
  case 2:
1463
- _yield$this$filehandl = _context.sent;
1464
- size = _yield$this$filehandl.size;
1497
+ buffer = _context.sent;
1465
1498
 
1466
- if (!(size > 500000000)) {
1467
- _context.next = 6;
1499
+ if (!isGzip(buffer)) {
1500
+ _context.next = 9;
1468
1501
  break;
1469
1502
  }
1470
1503
 
1471
- throw new Error('This file is too large. Consider using Gff3TabixAdapter');
1504
+ _context.next = 6;
1505
+ return bgzfFilehandle.unzip(buffer);
1472
1506
 
1473
1507
  case 6:
1508
+ _context.t0 = _context.sent;
1509
+ _context.next = 10;
1510
+ break;
1511
+
1512
+ case 9:
1513
+ _context.t0 = buffer;
1514
+
1515
+ case 10:
1516
+ buf = _context.t0;
1517
+
1518
+ if (!(buf.length > 536870888)) {
1519
+ _context.next = 13;
1520
+ break;
1521
+ }
1522
+
1523
+ throw new Error('Data exceeds maximum string length (512MB)');
1524
+
1525
+ case 13:
1526
+ data = new TextDecoder('utf8', {
1527
+ fatal: true
1528
+ }).decode(buf);
1529
+ lines = data.split('\n');
1530
+ headerLines = [];
1531
+
1532
+ for (i = 0; i < lines.length && lines[i].startsWith('#'); i++) {
1533
+ headerLines.push(lines[i]);
1534
+ }
1535
+
1536
+ header = headerLines.join('\n');
1537
+ feats = gff.parseStringSync(data, {
1538
+ parseFeatures: true,
1539
+ parseComments: false,
1540
+ parseDirectives: false,
1541
+ parseSequences: false
1542
+ });
1543
+ intervalTree = feats.flat().map(function (f, i) {
1544
+ return new SimpleFeature({
1545
+ data: _this.featureData(f),
1546
+ id: "".concat(_this.id, "-offset-").concat(i)
1547
+ });
1548
+ }).reduce(function (acc, obj) {
1549
+ var key = obj.get('refName');
1550
+
1551
+ if (!acc[key]) {
1552
+ acc[key] = new IntervalTree();
1553
+ }
1554
+
1555
+ acc[key].insert([obj.get('start'), obj.get('end')], obj);
1556
+ return acc;
1557
+ }, {});
1558
+ return _context.abrupt("return", {
1559
+ header: header,
1560
+ intervalTree: intervalTree
1561
+ });
1562
+
1563
+ case 21:
1564
+ case "end":
1565
+ return _context.stop();
1566
+ }
1567
+ }
1568
+ }, _callee, this);
1569
+ }));
1570
+
1571
+ function loadDataP() {
1572
+ return _loadDataP.apply(this, arguments);
1573
+ }
1574
+
1575
+ return loadDataP;
1576
+ }()
1577
+ }, {
1578
+ key: "loadData",
1579
+ value: function () {
1580
+ var _loadData = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2() {
1581
+ var _this2 = this;
1582
+
1583
+ return runtime_1.wrap(function _callee2$(_context2) {
1584
+ while (1) {
1585
+ switch (_context2.prev = _context2.next) {
1586
+ case 0:
1474
1587
  if (!this.gffFeatures) {
1475
- this.gffFeatures = this.filehandle.readFile('utf8').then(function (data) {
1476
- var gffFeatures = gff.parseStringSync(data, {
1477
- parseFeatures: true,
1478
- parseComments: false,
1479
- parseDirectives: false,
1480
- parseSequences: false
1481
- });
1482
- return gffFeatures.flat().map(function (f, i) {
1483
- return new SimpleFeature({
1484
- data: _this2.featureData(f),
1485
- id: "".concat(_this2.id, "-offset-").concat(i)
1486
- });
1487
- }).reduce(function (acc, obj) {
1488
- var key = obj.get('refName');
1489
-
1490
- if (!acc[key]) {
1491
- acc[key] = new IntervalTree();
1492
- }
1493
-
1494
- acc[key].insert([obj.get('start'), obj.get('end')], obj);
1495
- return acc;
1496
- }, {});
1497
- })["catch"](function (e) {
1588
+ this.gffFeatures = this.loadDataP()["catch"](function (e) {
1498
1589
  _this2.gffFeatures = undefined;
1499
1590
  throw e;
1500
1591
  });
1501
1592
  }
1502
1593
 
1503
- return _context.abrupt("return", this.gffFeatures);
1594
+ return _context2.abrupt("return", this.gffFeatures);
1504
1595
 
1505
- case 8:
1596
+ case 2:
1506
1597
  case "end":
1507
- return _context.stop();
1598
+ return _context2.stop();
1508
1599
  }
1509
1600
  }
1510
- }, _callee, this);
1601
+ }, _callee2, this);
1511
1602
  }));
1512
1603
 
1513
1604
  function loadData() {
@@ -1519,25 +1610,28 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1519
1610
  }, {
1520
1611
  key: "getRefNames",
1521
1612
  value: function () {
1522
- var _getRefNames = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2() {
1523
- var gffFeatures;
1524
- return runtime_1.wrap(function _callee2$(_context2) {
1613
+ var _getRefNames = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3() {
1614
+ var _yield$this$loadData,
1615
+ intervalTree;
1616
+
1617
+ return runtime_1.wrap(function _callee3$(_context3) {
1525
1618
  while (1) {
1526
- switch (_context2.prev = _context2.next) {
1619
+ switch (_context3.prev = _context3.next) {
1527
1620
  case 0:
1528
- _context2.next = 3;
1621
+ _context3.next = 3;
1529
1622
  return this.loadData();
1530
1623
 
1531
1624
  case 3:
1532
- gffFeatures = _context2.sent;
1533
- return _context2.abrupt("return", Object.keys(gffFeatures));
1625
+ _yield$this$loadData = _context3.sent;
1626
+ intervalTree = _yield$this$loadData.intervalTree;
1627
+ return _context3.abrupt("return", Object.keys(intervalTree));
1534
1628
 
1535
- case 5:
1629
+ case 6:
1536
1630
  case "end":
1537
- return _context2.stop();
1631
+ return _context3.stop();
1538
1632
  }
1539
1633
  }
1540
- }, _callee2, this);
1634
+ }, _callee3, this);
1541
1635
  }));
1542
1636
 
1543
1637
  function getRefNames() {
@@ -1546,6 +1640,38 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1546
1640
 
1547
1641
  return getRefNames;
1548
1642
  }()
1643
+ }, {
1644
+ key: "getHeader",
1645
+ value: function () {
1646
+ var _getHeader = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4() {
1647
+ var _yield$this$loadData2, header;
1648
+
1649
+ return runtime_1.wrap(function _callee4$(_context4) {
1650
+ while (1) {
1651
+ switch (_context4.prev = _context4.next) {
1652
+ case 0:
1653
+ _context4.next = 2;
1654
+ return this.loadData();
1655
+
1656
+ case 2:
1657
+ _yield$this$loadData2 = _context4.sent;
1658
+ header = _yield$this$loadData2.header;
1659
+ return _context4.abrupt("return", header);
1660
+
1661
+ case 5:
1662
+ case "end":
1663
+ return _context4.stop();
1664
+ }
1665
+ }
1666
+ }, _callee4, this);
1667
+ }));
1668
+
1669
+ function getHeader() {
1670
+ return _getHeader.apply(this, arguments);
1671
+ }
1672
+
1673
+ return getHeader;
1674
+ }()
1549
1675
  }, {
1550
1676
  key: "getFeatures",
1551
1677
  value: function getFeatures(query) {
@@ -1553,39 +1679,39 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1553
1679
 
1554
1680
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1555
1681
  return rxjs.ObservableCreate( /*#__PURE__*/function () {
1556
- var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(observer) {
1557
- var start, end, refName, gffFeatures, tree, feats;
1558
- return runtime_1.wrap(function _callee3$(_context3) {
1682
+ var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5(observer) {
1683
+ var _intervalTree$refName, start, end, refName, _yield$_this3$loadDat, intervalTree;
1684
+
1685
+ return runtime_1.wrap(function _callee5$(_context5) {
1559
1686
  while (1) {
1560
- switch (_context3.prev = _context3.next) {
1687
+ switch (_context5.prev = _context5.next) {
1561
1688
  case 0:
1562
- _context3.prev = 0;
1689
+ _context5.prev = 0;
1563
1690
  start = query.start, end = query.end, refName = query.refName;
1564
- _context3.next = 4;
1691
+ _context5.next = 4;
1565
1692
  return _this3.loadData();
1566
1693
 
1567
1694
  case 4:
1568
- gffFeatures = _context3.sent;
1569
- tree = gffFeatures[refName];
1570
- feats = tree.search([start, end]);
1571
- feats.forEach(function (f) {
1572
- observer.next(f);
1695
+ _yield$_this3$loadDat = _context5.sent;
1696
+ intervalTree = _yield$_this3$loadDat.intervalTree;
1697
+ (_intervalTree$refName = intervalTree[refName]) === null || _intervalTree$refName === void 0 ? void 0 : _intervalTree$refName.search([start, end]).forEach(function (f) {
1698
+ return observer.next(f);
1573
1699
  });
1574
1700
  observer.complete();
1575
- _context3.next = 14;
1701
+ _context5.next = 13;
1576
1702
  break;
1577
1703
 
1578
- case 11:
1579
- _context3.prev = 11;
1580
- _context3.t0 = _context3["catch"](0);
1581
- observer.error(_context3.t0);
1704
+ case 10:
1705
+ _context5.prev = 10;
1706
+ _context5.t0 = _context5["catch"](0);
1707
+ observer.error(_context5.t0);
1582
1708
 
1583
- case 14:
1709
+ case 13:
1584
1710
  case "end":
1585
- return _context3.stop();
1711
+ return _context5.stop();
1586
1712
  }
1587
1713
  }
1588
- }, _callee3, null, [[0, 11]]);
1714
+ }, _callee5, null, [[0, 10]]);
1589
1715
  }));
1590
1716
 
1591
1717
  return function (_x) {
@@ -1602,12 +1728,15 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1602
1728
 
1603
1729
  f.start -= 1; // convert to interbase
1604
1730
 
1605
- f.strand = {
1606
- '+': 1,
1607
- '-': -1,
1608
- '.': 0,
1609
- '?': undefined
1610
- }[data.strand]; // convert strand
1731
+ if (data.strand === '+') {
1732
+ f.strand = 1;
1733
+ } else if (data.strand === '-') {
1734
+ f.strand = -1;
1735
+ } else if (data.strand === '.') {
1736
+ f.strand = 0;
1737
+ } else {
1738
+ f.strand = undefined;
1739
+ }
1611
1740
 
1612
1741
  f.phase = Number(data.phase);
1613
1742
  f.refName = data.seq_id;
@@ -1621,7 +1750,8 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1621
1750
  }
1622
1751
 
1623
1752
  var defaultFields = ['start', 'end', 'seq_id', 'score', 'type', 'source', 'phase', 'strand'];
1624
- Object.keys(data.attributes).forEach(function (a) {
1753
+ var dataAttributes = data.attributes || {};
1754
+ Object.keys(dataAttributes).forEach(function (a) {
1625
1755
  var b = a.toLowerCase();
1626
1756
 
1627
1757
  if (defaultFields.includes(b)) {
@@ -1630,8 +1760,8 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1630
1760
  b += '2';
1631
1761
  }
1632
1762
 
1633
- if (data.attributes[a] !== null) {
1634
- var attr = data.attributes[a];
1763
+ if (dataAttributes[a] !== null) {
1764
+ var attr = dataAttributes[a];
1635
1765
 
1636
1766
  if (Array.isArray(attr) && attr.length === 1) {
1637
1767
  var _attr = attr;
@@ -1663,7 +1793,9 @@ var _default$2 = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1663
1793
  }
1664
1794
  }, {
1665
1795
  key: "freeResources",
1666
- value: function freeResources() {}
1796
+ value: function
1797
+ /* { region } */
1798
+ freeResources() {}
1667
1799
  }]);
1668
1800
 
1669
1801
  return _default;