@apollo-annotation/cli 0.3.1 → 0.3.3

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,51 @@
1
+ import assert from 'node:assert';
2
+ import { after, before, describe } from 'node:test';
3
+ import { Shell } from './utils.js';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ const hostTmpDir = path.resolve('tmpTestDocker');
7
+ const hostDataDir = path.resolve('test_data');
8
+ const apollo = `docker run --network host -v ${hostTmpDir}:/root/.config/apollo-cli -v ${hostDataDir}:/data apollo`;
9
+ const configFile = '/root/.config/apollo-cli/config.yml';
10
+ void describe('Test Docker', () => {
11
+ before(() => {
12
+ if (fs.existsSync(hostTmpDir) && fs.lstatSync(hostTmpDir).isDirectory()) {
13
+ fs.rmSync(hostTmpDir, { recursive: true });
14
+ }
15
+ fs.mkdirSync(hostTmpDir);
16
+ fs.writeFileSync(path.join(hostTmpDir, 'config.yml'), '');
17
+ new Shell('docker build --no-cache -t apollo .');
18
+ // See apollo-collaboration-server/.development.env for credentials etc.
19
+ new Shell(`${apollo} config --config-file ${configFile} address http://localhost:3999`);
20
+ new Shell(`${apollo} config --config-file ${configFile} accessType root`);
21
+ new Shell(`${apollo} config --config-file ${configFile} rootPassword pass`);
22
+ new Shell(`${apollo} login --config-file ${configFile}`, true, 60_000);
23
+ });
24
+ after(() => {
25
+ fs.rmSync(hostTmpDir, { recursive: true });
26
+ });
27
+ void globalThis.itName('Print help', () => {
28
+ const p = new Shell(`${apollo} --help`);
29
+ assert.ok(p.stdout.includes('COMMANDS'));
30
+ });
31
+ void globalThis.itName('Add assembly', () => {
32
+ const configFile = '/root/.config/apollo-cli/config.yml';
33
+ new Shell(`${apollo} assembly add-from-gff --config-file ${configFile} data/tiny.fasta.gff3 -a vv1 -f`);
34
+ let p = new Shell(`${apollo} assembly get --config-file ${configFile} -a vv1`);
35
+ assert.ok(p.stdout.includes('vv1'));
36
+ new Shell(`${apollo} assembly delete --config-file ${configFile} -a vv1`);
37
+ p = new Shell(`${apollo} assembly get --config-file ${configFile} -a vv1`);
38
+ assert.deepStrictEqual(p.stdout.trim(), '[]');
39
+ });
40
+ void globalThis.itName('Missing config', () => {
41
+ let p = new Shell(`${apollo} config address --config-file {hostTmpDir}/new.yml http://localhost:3999`, false);
42
+ assert.ok(p.returncode != 0);
43
+ assert.ok(p.stderr.includes('does not exist yet'));
44
+ p = new Shell(`${apollo} config address --config-file /root/.config/apollo-cli/new.yml http://localhost:3999`, false);
45
+ assert.ok(p.returncode != 0);
46
+ assert.ok(p.stderr.includes('does not exist yet'));
47
+ fs.writeFileSync(path.join(hostTmpDir, 'new.yml'), '');
48
+ p = new Shell(`${apollo} config address --config-file /root/.config/apollo-cli/new.yml http://localhost:3999`);
49
+ assert.strictEqual(p.returncode, 0);
50
+ });
51
+ });
@@ -0,0 +1,9 @@
1
+ declare global {
2
+ function itName(name: string, fn: Function): Promise<void>;
3
+ }
4
+ export declare class Shell {
5
+ returncode: number | null;
6
+ stdout: string;
7
+ stderr: string;
8
+ constructor(cmd: string, strict?: boolean, timeout?: number);
9
+ }
@@ -0,0 +1,28 @@
1
+ import { it } from 'node:test';
2
+ import spawn from 'cross-spawn';
3
+ // Workaround to print test name before each test
4
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
5
+ globalThis.itName = (name, fn) => {
6
+ const wrappedFn = () => {
7
+ process.stdout.write(`Running test: ${name}\n`);
8
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
9
+ return fn();
10
+ };
11
+ return it(name, wrappedFn);
12
+ };
13
+ export class Shell {
14
+ returncode;
15
+ stdout;
16
+ stderr;
17
+ constructor(cmd, strict = true, timeout) {
18
+ process.stdout.write(`${cmd}\n`);
19
+ cmd = `set -e; set -u; set -o pipefail\n${cmd}`;
20
+ const p = spawn.sync(cmd, { shell: '/bin/bash', timeout });
21
+ this.returncode = p.status;
22
+ this.stdout = p.stdout.toString();
23
+ this.stderr = p.stderr.toString();
24
+ if (strict && this.returncode != 0) {
25
+ throw new Error(`${p.error}\nCOMMAND:\n${cmd}\nSTDOUT:\n${this.stdout}\nSTDERR:\n${this.stderr}\nEXIT CODE: ${this.returncode}`);
26
+ }
27
+ }
28
+ }
@@ -240,20 +240,24 @@
240
240
  "aliases": [],
241
241
  "args": {
242
242
  "input": {
243
- "description": "Input fasta file, local or remote, or id of a previously uploaded file. For local or remote files, it is assumed the file is bgzip'd with `bgzip` and indexed with `samtools faidx`. The indexes are assumed to be at <my.fasta.gz>.fai and <my.fasta.gz>.gzi unless the options --fai and --gzi are provided.",
243
+ "description": "Input fasta file, local or remote, or id of a previously uploaded file. For local or remote files, it is assumed the file is bgzip'd with `bgzip` and indexed with `samtools faidx`. The indexes are assumed to be at <my.fasta.gz>.fai and <my.fasta.gz>.gzi unless the options --fai and --gzi are provided. A local file can be uncompressed if the flag -e/--editable is set (but see below about using -e)",
244
244
  "name": "input",
245
245
  "required": true
246
246
  }
247
247
  },
248
- "description": "Add new assembly. The input fasta may be:\n * A local file\n * An external fasta file\n * The id of a file previously uploaded to Apollo",
248
+ "description": "Add new assembly. The input fasta may be:\n * A local file bgzip'd and indexed. It can be uncompressed if the -e/--editable is set (but see description of -e)\n * An external fasta file bgzip'd and indexed\n * The id of a file previously uploaded to Apollo",
249
249
  "examples": [
250
250
  {
251
- "description": "From local file:",
251
+ "description": "From local file assuming indexes genome.gz.fai and genome.gz.gzi are present:",
252
+ "command": "<%= config.bin %> <%= command.id %> genome.fa.gz -a myAssembly"
253
+ },
254
+ {
255
+ "description": "Local file with editable sequence does not require compression and indexing:",
252
256
  "command": "<%= config.bin %> <%= command.id %> genome.fa -a myAssembly"
253
257
  },
254
258
  {
255
- "description": "From external source we also need the URL of the index:",
256
- "command": "<%= config.bin %> <%= command.id %> https://.../genome.fa -x https://.../genome.fa.fai -a myAssembly"
259
+ "description": "From external source assuming there are also indexes https://.../genome.fa.gz.fai and https://.../genome.fa.gz.gzi:",
260
+ "command": "<%= config.bin %> <%= command.id %> https://.../genome.fa.gz -a myAssembly"
257
261
  }
258
262
  ],
259
263
  "flags": {
@@ -725,185 +729,20 @@
725
729
  "get.js"
726
730
  ]
727
731
  },
728
- "file:delete": {
729
- "aliases": [],
730
- "args": {},
731
- "description": "Deleted files are printed to stdout. See also `apollo file get` to list the files on the server",
732
- "examples": [
733
- {
734
- "description": "Delete file multiple files:",
735
- "command": "<%= config.bin %> <%= command.id %> -i 123...abc xyz...789"
736
- }
737
- ],
738
- "flags": {
739
- "profile": {
740
- "description": "Use credentials from this profile",
741
- "name": "profile",
742
- "hasDynamicHelp": false,
743
- "multiple": false,
744
- "type": "option"
745
- },
746
- "config-file": {
747
- "description": "Use this config file (mostly for testing)",
748
- "name": "config-file",
749
- "hasDynamicHelp": false,
750
- "multiple": false,
751
- "type": "option"
752
- },
753
- "file-id": {
754
- "char": "i",
755
- "description": "IDs of the files to delete",
756
- "name": "file-id",
757
- "default": [
758
- "-"
759
- ],
760
- "hasDynamicHelp": false,
761
- "multiple": true,
762
- "type": "option"
763
- }
764
- },
765
- "hasDynamicHelp": false,
766
- "hiddenAliases": [],
767
- "id": "file:delete",
768
- "pluginAlias": "@apollo-annotation/cli",
769
- "pluginName": "@apollo-annotation/cli",
770
- "pluginType": "core",
771
- "strict": true,
772
- "summary": "Delete files from the Apollo server",
773
- "enableJsonFlag": false,
774
- "isESM": true,
775
- "relativePath": [
776
- "dist",
777
- "commands",
778
- "file",
779
- "delete.js"
780
- ]
781
- },
782
- "file:download": {
783
- "aliases": [],
784
- "args": {},
785
- "description": "See also `apollo file get` to list the files on the server",
786
- "examples": [
787
- {
788
- "description": "Download file with id xyz",
789
- "command": "<%= config.bin %> <%= command.id %> -i xyz -o genome.fa"
790
- }
791
- ],
792
- "flags": {
793
- "profile": {
794
- "description": "Use credentials from this profile",
795
- "name": "profile",
796
- "hasDynamicHelp": false,
797
- "multiple": false,
798
- "type": "option"
799
- },
800
- "config-file": {
801
- "description": "Use this config file (mostly for testing)",
802
- "name": "config-file",
803
- "hasDynamicHelp": false,
804
- "multiple": false,
805
- "type": "option"
806
- },
807
- "file-id": {
808
- "char": "i",
809
- "description": "ID of the file to download",
810
- "name": "file-id",
811
- "default": "-",
812
- "hasDynamicHelp": false,
813
- "multiple": false,
814
- "type": "option"
815
- },
816
- "output": {
817
- "char": "o",
818
- "description": "Write output to this file or \"-\" for stdout. Default to the name of the uploaded file.",
819
- "name": "output",
820
- "hasDynamicHelp": false,
821
- "multiple": false,
822
- "type": "option"
823
- }
824
- },
825
- "hasDynamicHelp": false,
826
- "hiddenAliases": [],
827
- "id": "file:download",
828
- "pluginAlias": "@apollo-annotation/cli",
829
- "pluginName": "@apollo-annotation/cli",
830
- "pluginType": "core",
831
- "strict": true,
832
- "summary": "Download a file from the Apollo server",
833
- "enableJsonFlag": false,
834
- "isESM": true,
835
- "relativePath": [
836
- "dist",
837
- "commands",
838
- "file",
839
- "download.js"
840
- ]
841
- },
842
- "file:get": {
843
- "aliases": [],
844
- "args": {},
845
- "description": "Print to stdout the list of files in json format",
846
- "examples": [
847
- {
848
- "description": "Get files by id:",
849
- "command": "<%= config.bin %> <%= command.id %> -i xyz abc"
850
- }
851
- ],
852
- "flags": {
853
- "profile": {
854
- "description": "Use credentials from this profile",
855
- "name": "profile",
856
- "hasDynamicHelp": false,
857
- "multiple": false,
858
- "type": "option"
859
- },
860
- "config-file": {
861
- "description": "Use this config file (mostly for testing)",
862
- "name": "config-file",
863
- "hasDynamicHelp": false,
864
- "multiple": false,
865
- "type": "option"
866
- },
867
- "file-id": {
868
- "char": "i",
869
- "description": "Get files matching this IDs",
870
- "name": "file-id",
871
- "hasDynamicHelp": false,
872
- "multiple": true,
873
- "type": "option"
874
- }
875
- },
876
- "hasDynamicHelp": false,
877
- "hiddenAliases": [],
878
- "id": "file:get",
879
- "pluginAlias": "@apollo-annotation/cli",
880
- "pluginName": "@apollo-annotation/cli",
881
- "pluginType": "core",
882
- "strict": true,
883
- "summary": "Get list of files uploaded to the Apollo server",
884
- "enableJsonFlag": false,
885
- "isESM": true,
886
- "relativePath": [
887
- "dist",
888
- "commands",
889
- "file",
890
- "get.js"
891
- ]
892
- },
893
- "file:upload": {
732
+ "export:gff3": {
894
733
  "aliases": [],
895
734
  "args": {
896
- "input-file": {
897
- "description": "Local file to upload",
898
- "name": "input-file",
735
+ "assembly": {
736
+ "description": "Export annotations for this assembly name or id",
737
+ "name": "assembly",
899
738
  "required": true
900
739
  }
901
740
  },
902
- "description": "This command only uploads a file and returns the corresponding file id.\n To add an assembly based on this file or to upload & add an assembly in a single pass see `apollo assembly add-from-fasta` and `add-from-gff`",
741
+ "description": "Export the annotations for an assembly to stdout as gff3",
903
742
  "examples": [
904
743
  {
905
- "description": "Upload local file, type auto-detected:",
906
- "command": "<%= config.bin %> <%= command.id %> genome.fa > file.json"
744
+ "description": "Export annotations for myAssembly:",
745
+ "command": "<%= config.bin %> <%= command.id %> myAssembly > out.gff3"
907
746
  }
908
747
  ],
909
748
  "flags": {
@@ -921,56 +760,27 @@
921
760
  "multiple": false,
922
761
  "type": "option"
923
762
  },
924
- "type": {
925
- "char": "t",
926
- "description": "Set file type or autodetected it if not set.\n NB: There is no check for whether the file complies to this type",
927
- "name": "type",
928
- "hasDynamicHelp": false,
929
- "multiple": false,
930
- "options": [
931
- "text/x-fasta",
932
- "text/x-gff3",
933
- "application/x-bgzip-fasta",
934
- "text/x-fai",
935
- "application/x-gzi"
936
- ],
937
- "type": "option"
938
- },
939
- "gzip": {
940
- "char": "z",
941
- "description": "Override autodetection and instruct that input is gzip compressed",
942
- "exclusive": [
943
- "decompressed"
944
- ],
945
- "name": "gzip",
946
- "allowNo": false,
947
- "type": "boolean"
948
- },
949
- "decompressed": {
950
- "char": "d",
951
- "description": "Override autodetection and instruct that input is decompressed",
952
- "exclusive": [
953
- "gzip"
954
- ],
955
- "name": "decompressed",
763
+ "include-fasta": {
764
+ "description": "Include fasta sequence in output",
765
+ "name": "include-fasta",
956
766
  "allowNo": false,
957
767
  "type": "boolean"
958
768
  }
959
769
  },
960
770
  "hasDynamicHelp": false,
961
771
  "hiddenAliases": [],
962
- "id": "file:upload",
772
+ "id": "export:gff3",
963
773
  "pluginAlias": "@apollo-annotation/cli",
964
774
  "pluginName": "@apollo-annotation/cli",
965
775
  "pluginType": "core",
966
776
  "strict": true,
967
- "summary": "Upload a local file to the Apollo server",
777
+ "enableJsonFlag": false,
968
778
  "isESM": true,
969
779
  "relativePath": [
970
780
  "dist",
971
781
  "commands",
972
- "file",
973
- "upload.js"
782
+ "export",
783
+ "gff3.js"
974
784
  ]
975
785
  },
976
786
  "feature:add-child": {
@@ -1775,6 +1585,254 @@
1775
1585
  "search.js"
1776
1586
  ]
1777
1587
  },
1588
+ "file:delete": {
1589
+ "aliases": [],
1590
+ "args": {},
1591
+ "description": "Deleted files are printed to stdout. See also `apollo file get` to list the files on the server",
1592
+ "examples": [
1593
+ {
1594
+ "description": "Delete file multiple files:",
1595
+ "command": "<%= config.bin %> <%= command.id %> -i 123...abc xyz...789"
1596
+ }
1597
+ ],
1598
+ "flags": {
1599
+ "profile": {
1600
+ "description": "Use credentials from this profile",
1601
+ "name": "profile",
1602
+ "hasDynamicHelp": false,
1603
+ "multiple": false,
1604
+ "type": "option"
1605
+ },
1606
+ "config-file": {
1607
+ "description": "Use this config file (mostly for testing)",
1608
+ "name": "config-file",
1609
+ "hasDynamicHelp": false,
1610
+ "multiple": false,
1611
+ "type": "option"
1612
+ },
1613
+ "file-id": {
1614
+ "char": "i",
1615
+ "description": "IDs of the files to delete",
1616
+ "name": "file-id",
1617
+ "default": [
1618
+ "-"
1619
+ ],
1620
+ "hasDynamicHelp": false,
1621
+ "multiple": true,
1622
+ "type": "option"
1623
+ }
1624
+ },
1625
+ "hasDynamicHelp": false,
1626
+ "hiddenAliases": [],
1627
+ "id": "file:delete",
1628
+ "pluginAlias": "@apollo-annotation/cli",
1629
+ "pluginName": "@apollo-annotation/cli",
1630
+ "pluginType": "core",
1631
+ "strict": true,
1632
+ "summary": "Delete files from the Apollo server",
1633
+ "enableJsonFlag": false,
1634
+ "isESM": true,
1635
+ "relativePath": [
1636
+ "dist",
1637
+ "commands",
1638
+ "file",
1639
+ "delete.js"
1640
+ ]
1641
+ },
1642
+ "file:download": {
1643
+ "aliases": [],
1644
+ "args": {},
1645
+ "description": "See also `apollo file get` to list the files on the server",
1646
+ "examples": [
1647
+ {
1648
+ "description": "Download file with id xyz",
1649
+ "command": "<%= config.bin %> <%= command.id %> -i xyz -o genome.fa"
1650
+ }
1651
+ ],
1652
+ "flags": {
1653
+ "profile": {
1654
+ "description": "Use credentials from this profile",
1655
+ "name": "profile",
1656
+ "hasDynamicHelp": false,
1657
+ "multiple": false,
1658
+ "type": "option"
1659
+ },
1660
+ "config-file": {
1661
+ "description": "Use this config file (mostly for testing)",
1662
+ "name": "config-file",
1663
+ "hasDynamicHelp": false,
1664
+ "multiple": false,
1665
+ "type": "option"
1666
+ },
1667
+ "file-id": {
1668
+ "char": "i",
1669
+ "description": "ID of the file to download",
1670
+ "name": "file-id",
1671
+ "default": "-",
1672
+ "hasDynamicHelp": false,
1673
+ "multiple": false,
1674
+ "type": "option"
1675
+ },
1676
+ "output": {
1677
+ "char": "o",
1678
+ "description": "Write output to this file or \"-\" for stdout. Default to the name of the uploaded file.",
1679
+ "name": "output",
1680
+ "hasDynamicHelp": false,
1681
+ "multiple": false,
1682
+ "type": "option"
1683
+ }
1684
+ },
1685
+ "hasDynamicHelp": false,
1686
+ "hiddenAliases": [],
1687
+ "id": "file:download",
1688
+ "pluginAlias": "@apollo-annotation/cli",
1689
+ "pluginName": "@apollo-annotation/cli",
1690
+ "pluginType": "core",
1691
+ "strict": true,
1692
+ "summary": "Download a file from the Apollo server",
1693
+ "enableJsonFlag": false,
1694
+ "isESM": true,
1695
+ "relativePath": [
1696
+ "dist",
1697
+ "commands",
1698
+ "file",
1699
+ "download.js"
1700
+ ]
1701
+ },
1702
+ "file:get": {
1703
+ "aliases": [],
1704
+ "args": {},
1705
+ "description": "Print to stdout the list of files in json format",
1706
+ "examples": [
1707
+ {
1708
+ "description": "Get files by id:",
1709
+ "command": "<%= config.bin %> <%= command.id %> -i xyz abc"
1710
+ }
1711
+ ],
1712
+ "flags": {
1713
+ "profile": {
1714
+ "description": "Use credentials from this profile",
1715
+ "name": "profile",
1716
+ "hasDynamicHelp": false,
1717
+ "multiple": false,
1718
+ "type": "option"
1719
+ },
1720
+ "config-file": {
1721
+ "description": "Use this config file (mostly for testing)",
1722
+ "name": "config-file",
1723
+ "hasDynamicHelp": false,
1724
+ "multiple": false,
1725
+ "type": "option"
1726
+ },
1727
+ "file-id": {
1728
+ "char": "i",
1729
+ "description": "Get files matching this IDs",
1730
+ "name": "file-id",
1731
+ "hasDynamicHelp": false,
1732
+ "multiple": true,
1733
+ "type": "option"
1734
+ }
1735
+ },
1736
+ "hasDynamicHelp": false,
1737
+ "hiddenAliases": [],
1738
+ "id": "file:get",
1739
+ "pluginAlias": "@apollo-annotation/cli",
1740
+ "pluginName": "@apollo-annotation/cli",
1741
+ "pluginType": "core",
1742
+ "strict": true,
1743
+ "summary": "Get list of files uploaded to the Apollo server",
1744
+ "enableJsonFlag": false,
1745
+ "isESM": true,
1746
+ "relativePath": [
1747
+ "dist",
1748
+ "commands",
1749
+ "file",
1750
+ "get.js"
1751
+ ]
1752
+ },
1753
+ "file:upload": {
1754
+ "aliases": [],
1755
+ "args": {
1756
+ "input-file": {
1757
+ "description": "Local file to upload",
1758
+ "name": "input-file",
1759
+ "required": true
1760
+ }
1761
+ },
1762
+ "description": "This command only uploads a file and returns the corresponding file id.\n To add an assembly based on this file or to upload & add an assembly in a single pass see `apollo assembly add-from-fasta` and `add-from-gff`",
1763
+ "examples": [
1764
+ {
1765
+ "description": "Upload local file, type auto-detected:",
1766
+ "command": "<%= config.bin %> <%= command.id %> genome.fa > file.json"
1767
+ }
1768
+ ],
1769
+ "flags": {
1770
+ "profile": {
1771
+ "description": "Use credentials from this profile",
1772
+ "name": "profile",
1773
+ "hasDynamicHelp": false,
1774
+ "multiple": false,
1775
+ "type": "option"
1776
+ },
1777
+ "config-file": {
1778
+ "description": "Use this config file (mostly for testing)",
1779
+ "name": "config-file",
1780
+ "hasDynamicHelp": false,
1781
+ "multiple": false,
1782
+ "type": "option"
1783
+ },
1784
+ "type": {
1785
+ "char": "t",
1786
+ "description": "Set file type or autodetected it if not set.\n NB: There is no check for whether the file complies to this type",
1787
+ "name": "type",
1788
+ "hasDynamicHelp": false,
1789
+ "multiple": false,
1790
+ "options": [
1791
+ "text/x-fasta",
1792
+ "text/x-gff3",
1793
+ "application/x-bgzip-fasta",
1794
+ "text/x-fai",
1795
+ "application/x-gzi"
1796
+ ],
1797
+ "type": "option"
1798
+ },
1799
+ "gzip": {
1800
+ "char": "z",
1801
+ "description": "Override autodetection and instruct that input is gzip compressed",
1802
+ "exclusive": [
1803
+ "decompressed"
1804
+ ],
1805
+ "name": "gzip",
1806
+ "allowNo": false,
1807
+ "type": "boolean"
1808
+ },
1809
+ "decompressed": {
1810
+ "char": "d",
1811
+ "description": "Override autodetection and instruct that input is decompressed",
1812
+ "exclusive": [
1813
+ "gzip"
1814
+ ],
1815
+ "name": "decompressed",
1816
+ "allowNo": false,
1817
+ "type": "boolean"
1818
+ }
1819
+ },
1820
+ "hasDynamicHelp": false,
1821
+ "hiddenAliases": [],
1822
+ "id": "file:upload",
1823
+ "pluginAlias": "@apollo-annotation/cli",
1824
+ "pluginName": "@apollo-annotation/cli",
1825
+ "pluginType": "core",
1826
+ "strict": true,
1827
+ "summary": "Upload a local file to the Apollo server",
1828
+ "isESM": true,
1829
+ "relativePath": [
1830
+ "dist",
1831
+ "commands",
1832
+ "file",
1833
+ "upload.js"
1834
+ ]
1835
+ },
1778
1836
  "jbrowse:get-config": {
1779
1837
  "aliases": [],
1780
1838
  "args": {},
@@ -2048,5 +2106,5 @@
2048
2106
  ]
2049
2107
  }
2050
2108
  },
2051
- "version": "0.3.1"
2109
+ "version": "0.3.3"
2052
2110
  }