@cmdcolin/jbrowse-plugin-hubs 1.0.4 → 1.0.6
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.
- package/dist/index.d.ts +0 -1
- package/dist/index.js +32 -9
- package/dist/index.js.map +1 -1
- package/dist/jbrowse-plugin-hubs.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-hubs.umd.production.min.js.map +4 -4
- package/package.json +4 -12
- package/src/index.ts +40 -20
- package/dist/fetchAssemblyHub.d.ts +0 -10
- package/dist/fetchAssemblyHub.js +0 -53
- package/dist/fetchAssemblyHub.js.map +0 -1
- package/dist/fetchAssemblyHub.test.d.ts +0 -1
- package/dist/fetchAssemblyHub.test.js +0 -203
- package/dist/fetchAssemblyHub.test.js.map +0 -1
- package/src/fetchAssemblyHub.test.ts +0 -255
- package/src/fetchAssemblyHub.ts +0 -68
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import Plugin from '@jbrowse/core/Plugin';
|
|
2
|
-
import { fetchAssemblyHub, fetchingAssemblies } from "./fetchAssemblyHub.js";
|
|
3
2
|
import { version } from '../package.json';
|
|
3
|
+
function getGenArkConfigUrl(accession) {
|
|
4
|
+
const [base, rest] = accession.split('_');
|
|
5
|
+
if (!rest) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
const match = rest.match(/.{1,3}/g);
|
|
9
|
+
if (!match || match.length < 3) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const [b1, b2, b3] = match;
|
|
13
|
+
return `https://jbrowse.org/hubs/genark/${base}/${b1}/${b2}/${b3}/${accession}/config.json`;
|
|
14
|
+
}
|
|
15
|
+
function getConfigUrl(assemblyName) {
|
|
16
|
+
if (assemblyName.startsWith('GCA_') || assemblyName.startsWith('GCF_')) {
|
|
17
|
+
return getGenArkConfigUrl(assemblyName);
|
|
18
|
+
}
|
|
19
|
+
return `https://jbrowse.org/ucsc/${assemblyName}/config.json`;
|
|
20
|
+
}
|
|
4
21
|
export default class HubsViewerPlugin extends Plugin {
|
|
5
22
|
name = 'HubsViewerPlugin';
|
|
6
23
|
version = version;
|
|
@@ -8,21 +25,27 @@ export default class HubsViewerPlugin extends Plugin {
|
|
|
8
25
|
pluginManager.addToExtensionPoint('Core-handleUnrecognizedAssembly', (_defaultResult, args) => {
|
|
9
26
|
const session = args.session;
|
|
10
27
|
const assemblyName = args.assemblyName;
|
|
11
|
-
// Skip if missing required args
|
|
12
28
|
if (!session || !assemblyName) {
|
|
13
29
|
return;
|
|
14
30
|
}
|
|
15
|
-
|
|
16
|
-
if (
|
|
31
|
+
const uri = getConfigUrl(assemblyName);
|
|
32
|
+
if (!uri) {
|
|
17
33
|
return;
|
|
18
34
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
const connectionId = `jb2hub-${assemblyName}`;
|
|
36
|
+
if (!session.connections.find(f => f.connectionId === connectionId)) {
|
|
37
|
+
const conf = {
|
|
38
|
+
type: 'JB2TrackHubConnection',
|
|
39
|
+
uri,
|
|
40
|
+
name: `conn_${assemblyName}`,
|
|
41
|
+
assemblyNames: [assemblyName],
|
|
42
|
+
connectionId,
|
|
43
|
+
};
|
|
44
|
+
session.addConnectionConf(conf);
|
|
45
|
+
session.makeConnection(conf);
|
|
46
|
+
}
|
|
23
47
|
});
|
|
24
48
|
}
|
|
25
49
|
configure(_pluginManager) { }
|
|
26
50
|
}
|
|
27
|
-
export { fetchAssemblyHub, fetchingAssemblies, } from "./fetchAssemblyHub.js";
|
|
28
51
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,sBAAsB,CAAA;AAGzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,sBAAsB,CAAA;AAGzC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAQzC,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,CAAA;IAC1B,OAAO,mCAAmC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,cAAc,CAAA;AAC7F,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB;IACxC,IAAI,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvE,OAAO,kBAAkB,CAAC,YAAY,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,4BAA4B,YAAY,cAAc,CAAA;AAC/D,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,MAAM;IAClD,IAAI,GAAG,kBAAkB,CAAA;IACzB,OAAO,GAAG,OAAO,CAAA;IAEjB,OAAO,CAAC,aAA4B;QAClC,aAAa,CAAC,mBAAmB,CAC/B,iCAAiC,EACjC,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE;YACvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAA8B,CAAA;YACnD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAkC,CAAA;YAC5D,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC9B,OAAM;YACR,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;YACtC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAM;YACR,CAAC;YACD,MAAM,YAAY,GAAG,UAAU,YAAY,EAAE,CAAA;YAC7C,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC,EAAE,CAAC;gBACpE,MAAM,IAAI,GAAG;oBACX,IAAI,EAAE,uBAAuB;oBAC7B,GAAG;oBACH,IAAI,EAAE,QAAQ,YAAY,EAAE;oBAC5B,aAAa,EAAE,CAAC,YAAY,CAAC;oBAC7B,YAAY;iBACb,CAAA;gBACD,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAA;gBAC/B,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC,CACF,CAAA;IACH,CAAC;IAED,SAAS,CAAC,cAA6B,IAAG,CAAC;CAC5C"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var JBrowsePluginHubs=(()=>{var
|
|
1
|
+
"use strict";var JBrowsePluginHubs=(()=>{var b=Object.create;var a=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var y=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports),C=(n,e)=>{for(var t in e)a(n,t,{get:e[t],enumerable:!0})},l=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of w(e))!x.call(n,s)&&s!==t&&a(n,s,{get:()=>e[s],enumerable:!(i=j(e,s))||i.enumerable});return n};var k=(n,e,t)=>(t=n!=null?b(h(n)):{},l(e||!n||!n.__esModule?a(t,"default",{value:n,enumerable:!0}):t,n)),v=n=>l(a({},"__esModule",{value:!0}),n);var p=y((I,g)=>{g.exports=JBrowseExports["@jbrowse/core/Plugin"]});var M={};C(M,{default:()=>d});var m=k(p());var f="1.0.6";function _(n){let[e,t]=n.split("_");if(!t)return;let i=t.match(/.{1,3}/g);if(!i||i.length<3)return;let[s,o,r]=i;return`https://jbrowse.org/hubs/genark/${e}/${s}/${o}/${r}/${n}/config.json`}function P(n){return n.startsWith("GCA_")||n.startsWith("GCF_")?_(n):`https://jbrowse.org/ucsc/${n}/config.json`}var d=class extends m.default{name="HubsViewerPlugin";version=f;install(e){e.addToExtensionPoint("Core-handleUnrecognizedAssembly",(t,i)=>{let s=i.session,o=i.assemblyName;if(!s||!o)return;let r=P(o);if(!r)return;let u=`jb2hub-${o}`;if(!s.connections.find(c=>c.connectionId===u)){let c={type:"JB2TrackHubConnection",uri:r,name:`conn_${o}`,assemblyNames:[o],connectionId:u};s.addConnectionConf(c),s.makeConnection(c)}})}configure(e){}};return v(M);})();
|
|
2
2
|
//# sourceMappingURL=jbrowse-plugin-hubs.umd.production.min.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["global-externals:@jbrowse/core/Plugin", "../src/index.ts", "../
|
|
4
|
-
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/core/Plugin\"];", "import Plugin from '@jbrowse/core/Plugin'\nimport PluginManager from '@jbrowse/core/PluginManager'\n\nimport {
|
|
5
|
-
"mappings": "gpBAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CAAAA,EAAO,QAAU,eAAe,sBAAsB,ICAtD,IAAAC,EAAA,GAAAC,EAAAD,EAAA,aAAAE,
|
|
6
|
-
"names": ["require_Plugin", "__commonJSMin", "exports", "module", "index_exports", "__export", "HubsViewerPlugin", "
|
|
3
|
+
"sources": ["global-externals:@jbrowse/core/Plugin", "../src/index.ts", "../package.json"],
|
|
4
|
+
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/core/Plugin\"];", "import Plugin from '@jbrowse/core/Plugin'\nimport PluginManager from '@jbrowse/core/PluginManager'\n\nimport { version } from '../package.json'\n\ninterface Session {\n makeConnection: (conf: unknown) => void\n addConnectionConf: (conf: unknown) => void\n connections: { connectionId: string }[]\n}\n\nfunction getGenArkConfigUrl(accession: string) {\n const [base, rest] = accession.split('_')\n if (!rest) {\n return undefined\n }\n const match = rest.match(/.{1,3}/g)\n if (!match || match.length < 3) {\n return undefined\n }\n const [b1, b2, b3] = match\n return `https://jbrowse.org/hubs/genark/${base}/${b1}/${b2}/${b3}/${accession}/config.json`\n}\n\nfunction getConfigUrl(assemblyName: string) {\n if (assemblyName.startsWith('GCA_') || assemblyName.startsWith('GCF_')) {\n return getGenArkConfigUrl(assemblyName)\n }\n return `https://jbrowse.org/ucsc/${assemblyName}/config.json`\n}\n\nexport default class HubsViewerPlugin extends Plugin {\n name = 'HubsViewerPlugin'\n version = version\n\n install(pluginManager: PluginManager) {\n pluginManager.addToExtensionPoint(\n 'Core-handleUnrecognizedAssembly',\n (_defaultResult, args) => {\n const session = args.session as Session | undefined\n const assemblyName = args.assemblyName as string | undefined\n if (!session || !assemblyName) {\n return\n }\n const uri = getConfigUrl(assemblyName)\n if (!uri) {\n return\n }\n const connectionId = `jb2hub-${assemblyName}`\n if (!session.connections.find(f => f.connectionId === connectionId)) {\n const conf = {\n type: 'JB2TrackHubConnection',\n uri,\n name: `conn_${assemblyName}`,\n assemblyNames: [assemblyName],\n connectionId,\n }\n session.addConnectionConf(conf)\n session.makeConnection(conf)\n }\n },\n )\n }\n\n configure(_pluginManager: PluginManager) {}\n}\n", "{\n \"version\": \"1.0.6\",\n \"license\": \"MIT\",\n \"name\": \"@cmdcolin/jbrowse-plugin-hubs\",\n \"keywords\": [\n \"jbrowse\",\n \"jbrowse2\"\n ],\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.esm.js\",\n \"typings\": \"dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"src\"\n ],\n \"scripts\": {\n \"clean\": \"rimraf dist\",\n \"start\": \"node esbuild.mjs --watch\",\n \"test\": \"echo 'no tests'\",\n \"format\": \"prettier --write .\",\n \"prebuild\": \"yarn clean\",\n \"build\": \"tsc && NODE_ENV=production node esbuild.mjs\",\n \"lint\": \"eslint --report-unused-disable-directives --max-warnings 0\",\n \"prepack\": \"yarn build\",\n \"postversion\": \"git push --follow-tags\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.2\",\n \"@fal-works/esbuild-plugin-global-externals\": \"^2.1.2\",\n \"@jbrowse/core\": \"^4.1.3\",\n \"@jbrowse/mobx-state-tree\": \"^5.0.2\",\n \"@mui/material\": \"^7.3.7\",\n \"@mui/system\": \"^7.3.7\",\n \"@mui/x-data-grid\": \"^8.26.0\",\n \"@types/node\": \"^25.1.0\",\n \"@types/react\": \"^19.2.10\",\n \"esbuild\": \"^0.27.2\",\n \"eslint\": \"^9.39.2\",\n \"eslint-plugin-import\": \"^2.31.0\",\n \"eslint-plugin-unicorn\": \"^62.0.0\",\n \"mobx\": \"^6.0.0\",\n \"mobx-react\": \"^9.0.1\",\n \"prettier\": \"^3.8.1\",\n \"pretty-bytes\": \"^7.0.0\",\n \"react\": \"^19.2.4\",\n \"react-dom\": \"^19.2.4\",\n \"rimraf\": \"^6.1.2\",\n \"rxjs\": \"^7.8.1\",\n \"serve\": \"^14.2.0\",\n \"typescript\": \"^5.1.6\",\n \"typescript-eslint\": \"^8.54.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"],
|
|
5
|
+
"mappings": "gpBAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CAAAA,EAAO,QAAU,eAAe,sBAAsB,ICAtD,IAAAC,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,IAAAC,EAAmB,OCCjB,IAAAC,EAAW,QDUb,SAASC,EAAmBC,EAAmB,CAC7C,GAAM,CAACC,EAAMC,CAAI,EAAIF,EAAU,MAAM,GAAG,EACxC,GAAI,CAACE,EACH,OAEF,IAAMC,EAAQD,EAAK,MAAM,SAAS,EAClC,GAAI,CAACC,GAASA,EAAM,OAAS,EAC3B,OAEF,GAAM,CAACC,EAAIC,EAAIC,CAAE,EAAIH,EACrB,MAAO,mCAAmCF,CAAI,IAAIG,CAAE,IAAIC,CAAE,IAAIC,CAAE,IAAIN,CAAS,cAC/E,CAEA,SAASO,EAAaC,EAAsB,CAC1C,OAAIA,EAAa,WAAW,MAAM,GAAKA,EAAa,WAAW,MAAM,EAC5DT,EAAmBS,CAAY,EAEjC,4BAA4BA,CAAY,cACjD,CAEA,IAAqBC,EAArB,cAA8C,EAAAC,OAAO,CACnD,KAAO,mBACP,QAAUC,EAEV,QAAQC,EAA8B,CACpCA,EAAc,oBACZ,kCACA,CAACC,EAAgBC,IAAS,CACxB,IAAMC,EAAUD,EAAK,QACfN,EAAeM,EAAK,aAC1B,GAAI,CAACC,GAAW,CAACP,EACf,OAEF,IAAMQ,EAAMT,EAAaC,CAAY,EACrC,GAAI,CAACQ,EACH,OAEF,IAAMC,EAAe,UAAUT,CAAY,GAC3C,GAAI,CAACO,EAAQ,YAAY,KAAKG,GAAKA,EAAE,eAAiBD,CAAY,EAAG,CACnE,IAAME,EAAO,CACX,KAAM,wBACN,IAAAH,EACA,KAAM,QAAQR,CAAY,GAC1B,cAAe,CAACA,CAAY,EAC5B,aAAAS,CACF,EACAF,EAAQ,kBAAkBI,CAAI,EAC9BJ,EAAQ,eAAeI,CAAI,CAC7B,CACF,CACF,CACF,CAEA,UAAUC,EAA+B,CAAC,CAC5C",
|
|
6
|
+
"names": ["require_Plugin", "__commonJSMin", "exports", "module", "index_exports", "__export", "HubsViewerPlugin", "import_Plugin", "version", "getGenArkConfigUrl", "accession", "base", "rest", "match", "b1", "b2", "b3", "getConfigUrl", "assemblyName", "HubsViewerPlugin", "Plugin", "version", "pluginManager", "_defaultResult", "args", "session", "uri", "connectionId", "f", "conf", "_pluginManager"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.
|
|
2
|
+
"version": "1.0.6",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@cmdcolin/jbrowse-plugin-hubs",
|
|
5
5
|
"keywords": [
|
|
@@ -16,30 +16,22 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"clean": "rimraf dist",
|
|
18
18
|
"start": "node esbuild.mjs --watch",
|
|
19
|
-
"test": "
|
|
19
|
+
"test": "echo 'no tests'",
|
|
20
20
|
"format": "prettier --write .",
|
|
21
|
-
"prebuild": "
|
|
21
|
+
"prebuild": "yarn clean",
|
|
22
22
|
"build": "tsc && NODE_ENV=production node esbuild.mjs",
|
|
23
23
|
"lint": "eslint --report-unused-disable-directives --max-warnings 0",
|
|
24
|
-
"prepack": "
|
|
24
|
+
"prepack": "yarn build",
|
|
25
25
|
"postversion": "git push --follow-tags"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@babel/core": "^7.28.6",
|
|
29
|
-
"@babel/preset-react": "^7.10.4",
|
|
30
|
-
"@emotion/react": "^11.10.4",
|
|
31
|
-
"@emotion/styled": "^11.14.1",
|
|
32
28
|
"@eslint/js": "^9.39.2",
|
|
33
29
|
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
|
|
34
30
|
"@jbrowse/core": "^4.1.3",
|
|
35
31
|
"@jbrowse/mobx-state-tree": "^5.0.2",
|
|
36
|
-
"@jbrowse/plugin-data-management": "^4.1.3",
|
|
37
|
-
"@jbrowse/plugin-linear-genome-view": "^4.1.3",
|
|
38
32
|
"@mui/material": "^7.3.7",
|
|
39
33
|
"@mui/system": "^7.3.7",
|
|
40
34
|
"@mui/x-data-grid": "^8.26.0",
|
|
41
|
-
"@types/d3-array": "^3.2.1",
|
|
42
|
-
"@types/d3-hierarchy": "^3.1.7",
|
|
43
35
|
"@types/node": "^25.1.0",
|
|
44
36
|
"@types/react": "^19.2.10",
|
|
45
37
|
"esbuild": "^0.27.2",
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import Plugin from '@jbrowse/core/Plugin'
|
|
2
2
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
3
|
|
|
4
|
-
import { fetchAssemblyHub, fetchingAssemblies } from './fetchAssemblyHub.ts'
|
|
5
4
|
import { version } from '../package.json'
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
interface Session {
|
|
7
|
+
makeConnection: (conf: unknown) => void
|
|
8
|
+
addConnectionConf: (conf: unknown) => void
|
|
9
|
+
connections: { connectionId: string }[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getGenArkConfigUrl(accession: string) {
|
|
13
|
+
const [base, rest] = accession.split('_')
|
|
14
|
+
if (!rest) {
|
|
15
|
+
return undefined
|
|
16
|
+
}
|
|
17
|
+
const match = rest.match(/.{1,3}/g)
|
|
18
|
+
if (!match || match.length < 3) {
|
|
19
|
+
return undefined
|
|
20
|
+
}
|
|
21
|
+
const [b1, b2, b3] = match
|
|
22
|
+
return `https://jbrowse.org/hubs/genark/${base}/${b1}/${b2}/${b3}/${accession}/config.json`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getConfigUrl(assemblyName: string) {
|
|
26
|
+
if (assemblyName.startsWith('GCA_') || assemblyName.startsWith('GCF_')) {
|
|
27
|
+
return getGenArkConfigUrl(assemblyName)
|
|
28
|
+
}
|
|
29
|
+
return `https://jbrowse.org/ucsc/${assemblyName}/config.json`
|
|
30
|
+
}
|
|
8
31
|
|
|
9
32
|
export default class HubsViewerPlugin extends Plugin {
|
|
10
33
|
name = 'HubsViewerPlugin'
|
|
@@ -14,33 +37,30 @@ export default class HubsViewerPlugin extends Plugin {
|
|
|
14
37
|
pluginManager.addToExtensionPoint(
|
|
15
38
|
'Core-handleUnrecognizedAssembly',
|
|
16
39
|
(_defaultResult, args) => {
|
|
17
|
-
const session = args.session as
|
|
40
|
+
const session = args.session as Session | undefined
|
|
18
41
|
const assemblyName = args.assemblyName as string | undefined
|
|
19
|
-
|
|
20
|
-
// Skip if missing required args
|
|
21
42
|
if (!session || !assemblyName) {
|
|
22
43
|
return
|
|
23
44
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (fetchingAssemblies.has(assemblyName)) {
|
|
45
|
+
const uri = getConfigUrl(assemblyName)
|
|
46
|
+
if (!uri) {
|
|
27
47
|
return
|
|
28
48
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
49
|
+
const connectionId = `jb2hub-${assemblyName}`
|
|
50
|
+
if (!session.connections.find(f => f.connectionId === connectionId)) {
|
|
51
|
+
const conf = {
|
|
52
|
+
type: 'JB2TrackHubConnection',
|
|
53
|
+
uri,
|
|
54
|
+
name: `conn_${assemblyName}`,
|
|
55
|
+
assemblyNames: [assemblyName],
|
|
56
|
+
connectionId,
|
|
57
|
+
}
|
|
58
|
+
session.addConnectionConf(conf)
|
|
59
|
+
session.makeConnection(conf)
|
|
60
|
+
}
|
|
35
61
|
},
|
|
36
62
|
)
|
|
37
63
|
}
|
|
38
64
|
|
|
39
65
|
configure(_pluginManager: PluginManager) {}
|
|
40
66
|
}
|
|
41
|
-
|
|
42
|
-
export {
|
|
43
|
-
type HubSession,
|
|
44
|
-
fetchAssemblyHub,
|
|
45
|
-
fetchingAssemblies,
|
|
46
|
-
} from './fetchAssemblyHub.ts'
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare const fetchingAssemblies: Set<string>;
|
|
2
|
-
export interface HubSession {
|
|
3
|
-
assemblyManager: {
|
|
4
|
-
get: (name: string) => unknown;
|
|
5
|
-
};
|
|
6
|
-
addSessionAssembly: (assembly: unknown) => void;
|
|
7
|
-
addTrackConf: (track: unknown) => void;
|
|
8
|
-
notifyError: (msg: string, e: unknown) => void;
|
|
9
|
-
}
|
|
10
|
-
export declare function fetchAssemblyHub(session: HubSession, assemblyName: string): Promise<void>;
|
package/dist/fetchAssemblyHub.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Track assemblies we're currently fetching to avoid duplicate requests
|
|
2
|
-
export const fetchingAssemblies = new Set();
|
|
3
|
-
function getGenArkConfigUrl(accession) {
|
|
4
|
-
const [base, rest] = accession.split('_');
|
|
5
|
-
if (!rest) {
|
|
6
|
-
return undefined;
|
|
7
|
-
}
|
|
8
|
-
const match = rest.match(/.{1,3}/g);
|
|
9
|
-
if (!match || match.length < 3) {
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
12
|
-
const [b1, b2, b3] = match;
|
|
13
|
-
return `https://jbrowse.org/hubs/genark/${base}/${b1}/${b2}/${b3}/${accession}/config.json`;
|
|
14
|
-
}
|
|
15
|
-
function getConfigUrl(assemblyName) {
|
|
16
|
-
// GenArk assemblies (GCA_* or GCF_*)
|
|
17
|
-
if (assemblyName.startsWith('GCA_') || assemblyName.startsWith('GCF_')) {
|
|
18
|
-
return getGenArkConfigUrl(assemblyName);
|
|
19
|
-
}
|
|
20
|
-
// UCSC assemblies (hg38, mm10, etc.)
|
|
21
|
-
return `https://jbrowse.org/ucsc/${assemblyName}/config.json`;
|
|
22
|
-
}
|
|
23
|
-
export async function fetchAssemblyHub(session, assemblyName) {
|
|
24
|
-
const url = getConfigUrl(assemblyName);
|
|
25
|
-
if (!url) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
try {
|
|
29
|
-
const response = await fetch(url);
|
|
30
|
-
if (!response.ok) {
|
|
31
|
-
throw new Error(`HTTP ${response.status} from ${url}`);
|
|
32
|
-
}
|
|
33
|
-
const config = (await response.json());
|
|
34
|
-
// Add assemblies directly to session
|
|
35
|
-
for (const assembly of config.assemblies ?? []) {
|
|
36
|
-
if (!session.assemblyManager.get(assembly.name)) {
|
|
37
|
-
session.addSessionAssembly(assembly);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
// Add tracks directly to session (addTrackConf handles duplicates)
|
|
41
|
-
for (const track of config.tracks ?? []) {
|
|
42
|
-
session.addTrackConf(track);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch (e) {
|
|
46
|
-
console.error(e);
|
|
47
|
-
session.notifyError(`Failed to load assembly ${assemblyName}: ${e}`, e);
|
|
48
|
-
}
|
|
49
|
-
finally {
|
|
50
|
-
fetchingAssemblies.delete(assemblyName);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=fetchAssemblyHub.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fetchAssemblyHub.js","sourceRoot":"","sources":["../src/fetchAssemblyHub.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAA;AASnD,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,CAAA;IAC1B,OAAO,mCAAmC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,cAAc,CAAA;AAC7F,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB;IACxC,qCAAqC;IACrC,IAAI,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvE,OAAO,kBAAkB,CAAC,YAAY,CAAC,CAAA;IACzC,CAAC;IACD,qCAAqC;IACrC,OAAO,4BAA4B,YAAY,cAAc,CAAA;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAmB,EACnB,YAAoB;IAEpB,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAM;IACR,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAA;QACxD,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGpC,CAAA;QAED,qCAAqC;QACrC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;YACtC,CAAC;QACH,CAAC;QAED,mEAAmE;QACnE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACxC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAChB,OAAO,CAAC,WAAW,CAAC,2BAA2B,YAAY,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;IACzE,CAAC;YAAS,CAAC;QACT,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACzC,CAAC;AACH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import { beforeEach, describe, it } from 'node:test';
|
|
3
|
-
import { fetchAssemblyHub, fetchingAssemblies } from "./fetchAssemblyHub.js";
|
|
4
|
-
function createMockSession() {
|
|
5
|
-
const calls = {
|
|
6
|
-
addSessionAssembly: [],
|
|
7
|
-
addTrackConf: [],
|
|
8
|
-
notifyError: [],
|
|
9
|
-
};
|
|
10
|
-
return {
|
|
11
|
-
session: {
|
|
12
|
-
assemblyManager: {
|
|
13
|
-
get: (_name) => undefined,
|
|
14
|
-
},
|
|
15
|
-
addSessionAssembly: (assembly) => {
|
|
16
|
-
calls.addSessionAssembly.push(assembly);
|
|
17
|
-
},
|
|
18
|
-
addTrackConf: (track) => {
|
|
19
|
-
calls.addTrackConf.push(track);
|
|
20
|
-
},
|
|
21
|
-
notifyError: (msg, e) => {
|
|
22
|
-
calls.notifyError.push({ msg, e });
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
calls,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function mockFetch(config, ok = true, status = 200) {
|
|
29
|
-
const originalFetch = globalThis.fetch;
|
|
30
|
-
globalThis.fetch = (async () => ({
|
|
31
|
-
ok,
|
|
32
|
-
status,
|
|
33
|
-
json: async () => config,
|
|
34
|
-
}));
|
|
35
|
-
return () => {
|
|
36
|
-
globalThis.fetch = originalFetch;
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
describe('fetchAssemblyHub', () => {
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
fetchingAssemblies.clear();
|
|
42
|
-
});
|
|
43
|
-
it('adds assemblies from fetched config', async () => {
|
|
44
|
-
const { session, calls } = createMockSession();
|
|
45
|
-
const mockConfig = {
|
|
46
|
-
assemblies: [{ name: 'hg38', sequence: {} }],
|
|
47
|
-
tracks: [],
|
|
48
|
-
};
|
|
49
|
-
const restore = mockFetch(mockConfig);
|
|
50
|
-
fetchingAssemblies.add('hg38');
|
|
51
|
-
await fetchAssemblyHub(session, 'hg38');
|
|
52
|
-
restore();
|
|
53
|
-
assert.strictEqual(calls.addSessionAssembly.length, 1);
|
|
54
|
-
assert.deepStrictEqual(calls.addSessionAssembly[0], {
|
|
55
|
-
name: 'hg38',
|
|
56
|
-
sequence: {},
|
|
57
|
-
});
|
|
58
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), false);
|
|
59
|
-
});
|
|
60
|
-
it('adds tracks from fetched config', async () => {
|
|
61
|
-
const { session, calls } = createMockSession();
|
|
62
|
-
const mockConfig = {
|
|
63
|
-
assemblies: [],
|
|
64
|
-
tracks: [{ trackId: 'genes', type: 'FeatureTrack' }],
|
|
65
|
-
};
|
|
66
|
-
const restore = mockFetch(mockConfig);
|
|
67
|
-
fetchingAssemblies.add('hg38');
|
|
68
|
-
await fetchAssemblyHub(session, 'hg38');
|
|
69
|
-
restore();
|
|
70
|
-
assert.strictEqual(calls.addTrackConf.length, 1);
|
|
71
|
-
assert.deepStrictEqual(calls.addTrackConf[0], {
|
|
72
|
-
trackId: 'genes',
|
|
73
|
-
type: 'FeatureTrack',
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
it('skips assembly if already exists', async () => {
|
|
77
|
-
const { session, calls } = createMockSession();
|
|
78
|
-
session.assemblyManager.get = () => ({ name: 'hg38' });
|
|
79
|
-
const mockConfig = {
|
|
80
|
-
assemblies: [{ name: 'hg38', sequence: {} }],
|
|
81
|
-
tracks: [],
|
|
82
|
-
};
|
|
83
|
-
const restore = mockFetch(mockConfig);
|
|
84
|
-
fetchingAssemblies.add('hg38');
|
|
85
|
-
await fetchAssemblyHub(session, 'hg38');
|
|
86
|
-
restore();
|
|
87
|
-
assert.strictEqual(calls.addSessionAssembly.length, 0);
|
|
88
|
-
});
|
|
89
|
-
it('handles fetch error gracefully', async () => {
|
|
90
|
-
const { session, calls } = createMockSession();
|
|
91
|
-
const restore = mockFetch({}, false, 404);
|
|
92
|
-
fetchingAssemblies.add('nonexistent');
|
|
93
|
-
await fetchAssemblyHub(session, 'nonexistent');
|
|
94
|
-
restore();
|
|
95
|
-
assert.strictEqual(calls.notifyError.length, 1);
|
|
96
|
-
assert.strictEqual(fetchingAssemblies.has('nonexistent'), false);
|
|
97
|
-
});
|
|
98
|
-
it('handles network error gracefully', async () => {
|
|
99
|
-
const { session, calls } = createMockSession();
|
|
100
|
-
const originalFetch = globalThis.fetch;
|
|
101
|
-
globalThis.fetch = (async () => {
|
|
102
|
-
throw new Error('Network error');
|
|
103
|
-
});
|
|
104
|
-
fetchingAssemblies.add('hg38');
|
|
105
|
-
await fetchAssemblyHub(session, 'hg38');
|
|
106
|
-
globalThis.fetch = originalFetch;
|
|
107
|
-
assert.strictEqual(calls.notifyError.length, 1);
|
|
108
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), false);
|
|
109
|
-
});
|
|
110
|
-
it('cleans up fetchingAssemblies on success', async () => {
|
|
111
|
-
const { session } = createMockSession();
|
|
112
|
-
const mockConfig = { assemblies: [], tracks: [] };
|
|
113
|
-
const restore = mockFetch(mockConfig);
|
|
114
|
-
fetchingAssemblies.add('hg38');
|
|
115
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), true);
|
|
116
|
-
await fetchAssemblyHub(session, 'hg38');
|
|
117
|
-
restore();
|
|
118
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), false);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
describe('extension point handler', () => {
|
|
122
|
-
it('fetchingAssemblies prevents duplicate requests', () => {
|
|
123
|
-
fetchingAssemblies.add('hg38');
|
|
124
|
-
const shouldFetch = !fetchingAssemblies.has('hg38');
|
|
125
|
-
assert.strictEqual(shouldFetch, false);
|
|
126
|
-
});
|
|
127
|
-
it('allows fetch for new assembly', () => {
|
|
128
|
-
fetchingAssemblies.clear();
|
|
129
|
-
const shouldFetch = !fetchingAssemblies.has('hg38');
|
|
130
|
-
assert.strictEqual(shouldFetch, true);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
describe('GenArk assembly support', () => {
|
|
134
|
-
beforeEach(() => {
|
|
135
|
-
fetchingAssemblies.clear();
|
|
136
|
-
});
|
|
137
|
-
it('fetches GenArk assembly with GCF_ prefix', async () => {
|
|
138
|
-
const { session, calls } = createMockSession();
|
|
139
|
-
const mockConfig = {
|
|
140
|
-
assemblies: [{ name: 'GCF_009858895.2', sequence: {} }],
|
|
141
|
-
tracks: [],
|
|
142
|
-
};
|
|
143
|
-
let fetchedUrl = '';
|
|
144
|
-
const originalFetch = globalThis.fetch;
|
|
145
|
-
globalThis.fetch = (async (url) => {
|
|
146
|
-
fetchedUrl = url;
|
|
147
|
-
return {
|
|
148
|
-
ok: true,
|
|
149
|
-
status: 200,
|
|
150
|
-
json: async () => mockConfig,
|
|
151
|
-
};
|
|
152
|
-
});
|
|
153
|
-
fetchingAssemblies.add('GCF_009858895.2');
|
|
154
|
-
await fetchAssemblyHub(session, 'GCF_009858895.2');
|
|
155
|
-
globalThis.fetch = originalFetch;
|
|
156
|
-
assert.strictEqual(fetchedUrl, 'https://jbrowse.org/hubs/genark/GCF/009/858/895/GCF_009858895.2/config.json');
|
|
157
|
-
assert.strictEqual(calls.addSessionAssembly.length, 1);
|
|
158
|
-
});
|
|
159
|
-
it('fetches GenArk assembly with GCA_ prefix', async () => {
|
|
160
|
-
const { session, calls } = createMockSession();
|
|
161
|
-
const mockConfig = {
|
|
162
|
-
assemblies: [{ name: 'GCA_000001405.15', sequence: {} }],
|
|
163
|
-
tracks: [],
|
|
164
|
-
};
|
|
165
|
-
let fetchedUrl = '';
|
|
166
|
-
const originalFetch = globalThis.fetch;
|
|
167
|
-
globalThis.fetch = (async (url) => {
|
|
168
|
-
fetchedUrl = url;
|
|
169
|
-
return {
|
|
170
|
-
ok: true,
|
|
171
|
-
status: 200,
|
|
172
|
-
json: async () => mockConfig,
|
|
173
|
-
};
|
|
174
|
-
});
|
|
175
|
-
fetchingAssemblies.add('GCA_000001405.15');
|
|
176
|
-
await fetchAssemblyHub(session, 'GCA_000001405.15');
|
|
177
|
-
globalThis.fetch = originalFetch;
|
|
178
|
-
assert.strictEqual(fetchedUrl, 'https://jbrowse.org/hubs/genark/GCA/000/001/405/GCA_000001405.15/config.json');
|
|
179
|
-
assert.strictEqual(calls.addSessionAssembly.length, 1);
|
|
180
|
-
});
|
|
181
|
-
it('uses UCSC URL for non-GenArk assemblies', async () => {
|
|
182
|
-
const { session } = createMockSession();
|
|
183
|
-
const mockConfig = {
|
|
184
|
-
assemblies: [{ name: 'hg38', sequence: {} }],
|
|
185
|
-
tracks: [],
|
|
186
|
-
};
|
|
187
|
-
let fetchedUrl = '';
|
|
188
|
-
const originalFetch = globalThis.fetch;
|
|
189
|
-
globalThis.fetch = (async (url) => {
|
|
190
|
-
fetchedUrl = url;
|
|
191
|
-
return {
|
|
192
|
-
ok: true,
|
|
193
|
-
status: 200,
|
|
194
|
-
json: async () => mockConfig,
|
|
195
|
-
};
|
|
196
|
-
});
|
|
197
|
-
fetchingAssemblies.add('hg38');
|
|
198
|
-
await fetchAssemblyHub(session, 'hg38');
|
|
199
|
-
globalThis.fetch = originalFetch;
|
|
200
|
-
assert.strictEqual(fetchedUrl, 'https://jbrowse.org/ucsc/hg38/config.json');
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
//# sourceMappingURL=fetchAssemblyHub.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fetchAssemblyHub.test.js","sourceRoot":"","sources":["../src/fetchAssemblyHub.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { beforeEach, describe, it } from 'node:test'
|
|
3
|
-
|
|
4
|
-
import { fetchAssemblyHub, fetchingAssemblies } from './fetchAssemblyHub.ts'
|
|
5
|
-
|
|
6
|
-
import type { HubSession } from './fetchAssemblyHub.ts'
|
|
7
|
-
|
|
8
|
-
function createMockSession(): {
|
|
9
|
-
session: HubSession
|
|
10
|
-
calls: {
|
|
11
|
-
addSessionAssembly: unknown[]
|
|
12
|
-
addTrackConf: unknown[]
|
|
13
|
-
notifyError: unknown[]
|
|
14
|
-
}
|
|
15
|
-
} {
|
|
16
|
-
const calls = {
|
|
17
|
-
addSessionAssembly: [] as unknown[],
|
|
18
|
-
addTrackConf: [] as unknown[],
|
|
19
|
-
notifyError: [] as unknown[],
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
session: {
|
|
23
|
-
assemblyManager: {
|
|
24
|
-
get: (_name: string) => undefined as unknown,
|
|
25
|
-
},
|
|
26
|
-
addSessionAssembly: (assembly: unknown) => {
|
|
27
|
-
calls.addSessionAssembly.push(assembly)
|
|
28
|
-
},
|
|
29
|
-
addTrackConf: (track: unknown) => {
|
|
30
|
-
calls.addTrackConf.push(track)
|
|
31
|
-
},
|
|
32
|
-
notifyError: (msg: string, e: unknown) => {
|
|
33
|
-
calls.notifyError.push({ msg, e })
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
calls,
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function mockFetch(config: unknown, ok = true, status = 200) {
|
|
41
|
-
const originalFetch = globalThis.fetch
|
|
42
|
-
globalThis.fetch = (async () => ({
|
|
43
|
-
ok,
|
|
44
|
-
status,
|
|
45
|
-
json: async () => config,
|
|
46
|
-
})) as unknown as typeof fetch
|
|
47
|
-
return () => {
|
|
48
|
-
globalThis.fetch = originalFetch
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
describe('fetchAssemblyHub', () => {
|
|
53
|
-
beforeEach(() => {
|
|
54
|
-
fetchingAssemblies.clear()
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('adds assemblies from fetched config', async () => {
|
|
58
|
-
const { session, calls } = createMockSession()
|
|
59
|
-
const mockConfig = {
|
|
60
|
-
assemblies: [{ name: 'hg38', sequence: {} }],
|
|
61
|
-
tracks: [],
|
|
62
|
-
}
|
|
63
|
-
const restore = mockFetch(mockConfig)
|
|
64
|
-
|
|
65
|
-
fetchingAssemblies.add('hg38')
|
|
66
|
-
await fetchAssemblyHub(session, 'hg38')
|
|
67
|
-
restore()
|
|
68
|
-
|
|
69
|
-
assert.strictEqual(calls.addSessionAssembly.length, 1)
|
|
70
|
-
assert.deepStrictEqual(calls.addSessionAssembly[0], {
|
|
71
|
-
name: 'hg38',
|
|
72
|
-
sequence: {},
|
|
73
|
-
})
|
|
74
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), false)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('adds tracks from fetched config', async () => {
|
|
78
|
-
const { session, calls } = createMockSession()
|
|
79
|
-
const mockConfig = {
|
|
80
|
-
assemblies: [],
|
|
81
|
-
tracks: [{ trackId: 'genes', type: 'FeatureTrack' }],
|
|
82
|
-
}
|
|
83
|
-
const restore = mockFetch(mockConfig)
|
|
84
|
-
|
|
85
|
-
fetchingAssemblies.add('hg38')
|
|
86
|
-
await fetchAssemblyHub(session, 'hg38')
|
|
87
|
-
restore()
|
|
88
|
-
|
|
89
|
-
assert.strictEqual(calls.addTrackConf.length, 1)
|
|
90
|
-
assert.deepStrictEqual(calls.addTrackConf[0], {
|
|
91
|
-
trackId: 'genes',
|
|
92
|
-
type: 'FeatureTrack',
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('skips assembly if already exists', async () => {
|
|
97
|
-
const { session, calls } = createMockSession()
|
|
98
|
-
session.assemblyManager.get = () => ({ name: 'hg38' })
|
|
99
|
-
const mockConfig = {
|
|
100
|
-
assemblies: [{ name: 'hg38', sequence: {} }],
|
|
101
|
-
tracks: [],
|
|
102
|
-
}
|
|
103
|
-
const restore = mockFetch(mockConfig)
|
|
104
|
-
|
|
105
|
-
fetchingAssemblies.add('hg38')
|
|
106
|
-
await fetchAssemblyHub(session, 'hg38')
|
|
107
|
-
restore()
|
|
108
|
-
|
|
109
|
-
assert.strictEqual(calls.addSessionAssembly.length, 0)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('handles fetch error gracefully', async () => {
|
|
113
|
-
const { session, calls } = createMockSession()
|
|
114
|
-
const restore = mockFetch({}, false, 404)
|
|
115
|
-
|
|
116
|
-
fetchingAssemblies.add('nonexistent')
|
|
117
|
-
await fetchAssemblyHub(session, 'nonexistent')
|
|
118
|
-
restore()
|
|
119
|
-
|
|
120
|
-
assert.strictEqual(calls.notifyError.length, 1)
|
|
121
|
-
assert.strictEqual(fetchingAssemblies.has('nonexistent'), false)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('handles network error gracefully', async () => {
|
|
125
|
-
const { session, calls } = createMockSession()
|
|
126
|
-
const originalFetch = globalThis.fetch
|
|
127
|
-
globalThis.fetch = (async () => {
|
|
128
|
-
throw new Error('Network error')
|
|
129
|
-
}) as unknown as typeof fetch
|
|
130
|
-
|
|
131
|
-
fetchingAssemblies.add('hg38')
|
|
132
|
-
await fetchAssemblyHub(session, 'hg38')
|
|
133
|
-
globalThis.fetch = originalFetch
|
|
134
|
-
|
|
135
|
-
assert.strictEqual(calls.notifyError.length, 1)
|
|
136
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), false)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('cleans up fetchingAssemblies on success', async () => {
|
|
140
|
-
const { session } = createMockSession()
|
|
141
|
-
const mockConfig = { assemblies: [], tracks: [] }
|
|
142
|
-
const restore = mockFetch(mockConfig)
|
|
143
|
-
|
|
144
|
-
fetchingAssemblies.add('hg38')
|
|
145
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), true)
|
|
146
|
-
|
|
147
|
-
await fetchAssemblyHub(session, 'hg38')
|
|
148
|
-
restore()
|
|
149
|
-
|
|
150
|
-
assert.strictEqual(fetchingAssemblies.has('hg38'), false)
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
describe('extension point handler', () => {
|
|
155
|
-
it('fetchingAssemblies prevents duplicate requests', () => {
|
|
156
|
-
fetchingAssemblies.add('hg38')
|
|
157
|
-
const shouldFetch = !fetchingAssemblies.has('hg38')
|
|
158
|
-
assert.strictEqual(shouldFetch, false)
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
it('allows fetch for new assembly', () => {
|
|
162
|
-
fetchingAssemblies.clear()
|
|
163
|
-
const shouldFetch = !fetchingAssemblies.has('hg38')
|
|
164
|
-
assert.strictEqual(shouldFetch, true)
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
describe('GenArk assembly support', () => {
|
|
169
|
-
beforeEach(() => {
|
|
170
|
-
fetchingAssemblies.clear()
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
it('fetches GenArk assembly with GCF_ prefix', async () => {
|
|
174
|
-
const { session, calls } = createMockSession()
|
|
175
|
-
const mockConfig = {
|
|
176
|
-
assemblies: [{ name: 'GCF_009858895.2', sequence: {} }],
|
|
177
|
-
tracks: [],
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
let fetchedUrl = ''
|
|
181
|
-
const originalFetch = globalThis.fetch
|
|
182
|
-
globalThis.fetch = (async (url: string) => {
|
|
183
|
-
fetchedUrl = url
|
|
184
|
-
return {
|
|
185
|
-
ok: true,
|
|
186
|
-
status: 200,
|
|
187
|
-
json: async () => mockConfig,
|
|
188
|
-
}
|
|
189
|
-
}) as unknown as typeof fetch
|
|
190
|
-
|
|
191
|
-
fetchingAssemblies.add('GCF_009858895.2')
|
|
192
|
-
await fetchAssemblyHub(session, 'GCF_009858895.2')
|
|
193
|
-
globalThis.fetch = originalFetch
|
|
194
|
-
|
|
195
|
-
assert.strictEqual(
|
|
196
|
-
fetchedUrl,
|
|
197
|
-
'https://jbrowse.org/hubs/genark/GCF/009/858/895/GCF_009858895.2/config.json',
|
|
198
|
-
)
|
|
199
|
-
assert.strictEqual(calls.addSessionAssembly.length, 1)
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('fetches GenArk assembly with GCA_ prefix', async () => {
|
|
203
|
-
const { session, calls } = createMockSession()
|
|
204
|
-
const mockConfig = {
|
|
205
|
-
assemblies: [{ name: 'GCA_000001405.15', sequence: {} }],
|
|
206
|
-
tracks: [],
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
let fetchedUrl = ''
|
|
210
|
-
const originalFetch = globalThis.fetch
|
|
211
|
-
globalThis.fetch = (async (url: string) => {
|
|
212
|
-
fetchedUrl = url
|
|
213
|
-
return {
|
|
214
|
-
ok: true,
|
|
215
|
-
status: 200,
|
|
216
|
-
json: async () => mockConfig,
|
|
217
|
-
}
|
|
218
|
-
}) as unknown as typeof fetch
|
|
219
|
-
|
|
220
|
-
fetchingAssemblies.add('GCA_000001405.15')
|
|
221
|
-
await fetchAssemblyHub(session, 'GCA_000001405.15')
|
|
222
|
-
globalThis.fetch = originalFetch
|
|
223
|
-
|
|
224
|
-
assert.strictEqual(
|
|
225
|
-
fetchedUrl,
|
|
226
|
-
'https://jbrowse.org/hubs/genark/GCA/000/001/405/GCA_000001405.15/config.json',
|
|
227
|
-
)
|
|
228
|
-
assert.strictEqual(calls.addSessionAssembly.length, 1)
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
it('uses UCSC URL for non-GenArk assemblies', async () => {
|
|
232
|
-
const { session } = createMockSession()
|
|
233
|
-
const mockConfig = {
|
|
234
|
-
assemblies: [{ name: 'hg38', sequence: {} }],
|
|
235
|
-
tracks: [],
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
let fetchedUrl = ''
|
|
239
|
-
const originalFetch = globalThis.fetch
|
|
240
|
-
globalThis.fetch = (async (url: string) => {
|
|
241
|
-
fetchedUrl = url
|
|
242
|
-
return {
|
|
243
|
-
ok: true,
|
|
244
|
-
status: 200,
|
|
245
|
-
json: async () => mockConfig,
|
|
246
|
-
}
|
|
247
|
-
}) as unknown as typeof fetch
|
|
248
|
-
|
|
249
|
-
fetchingAssemblies.add('hg38')
|
|
250
|
-
await fetchAssemblyHub(session, 'hg38')
|
|
251
|
-
globalThis.fetch = originalFetch
|
|
252
|
-
|
|
253
|
-
assert.strictEqual(fetchedUrl, 'https://jbrowse.org/ucsc/hg38/config.json')
|
|
254
|
-
})
|
|
255
|
-
})
|
package/src/fetchAssemblyHub.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// Track assemblies we're currently fetching to avoid duplicate requests
|
|
2
|
-
export const fetchingAssemblies = new Set<string>()
|
|
3
|
-
|
|
4
|
-
export interface HubSession {
|
|
5
|
-
assemblyManager: { get: (name: string) => unknown }
|
|
6
|
-
addSessionAssembly: (assembly: unknown) => void
|
|
7
|
-
addTrackConf: (track: unknown) => void
|
|
8
|
-
notifyError: (msg: string, e: unknown) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function getGenArkConfigUrl(accession: string) {
|
|
12
|
-
const [base, rest] = accession.split('_')
|
|
13
|
-
if (!rest) {
|
|
14
|
-
return undefined
|
|
15
|
-
}
|
|
16
|
-
const match = rest.match(/.{1,3}/g)
|
|
17
|
-
if (!match || match.length < 3) {
|
|
18
|
-
return undefined
|
|
19
|
-
}
|
|
20
|
-
const [b1, b2, b3] = match
|
|
21
|
-
return `https://jbrowse.org/hubs/genark/${base}/${b1}/${b2}/${b3}/${accession}/config.json`
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function getConfigUrl(assemblyName: string) {
|
|
25
|
-
// GenArk assemblies (GCA_* or GCF_*)
|
|
26
|
-
if (assemblyName.startsWith('GCA_') || assemblyName.startsWith('GCF_')) {
|
|
27
|
-
return getGenArkConfigUrl(assemblyName)
|
|
28
|
-
}
|
|
29
|
-
// UCSC assemblies (hg38, mm10, etc.)
|
|
30
|
-
return `https://jbrowse.org/ucsc/${assemblyName}/config.json`
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function fetchAssemblyHub(
|
|
34
|
-
session: HubSession,
|
|
35
|
-
assemblyName: string,
|
|
36
|
-
) {
|
|
37
|
-
const url = getConfigUrl(assemblyName)
|
|
38
|
-
if (!url) {
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
const response = await fetch(url)
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
throw new Error(`HTTP ${response.status} from ${url}`)
|
|
45
|
-
}
|
|
46
|
-
const config = (await response.json()) as {
|
|
47
|
-
assemblies?: { name: string }[]
|
|
48
|
-
tracks?: unknown[]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Add assemblies directly to session
|
|
52
|
-
for (const assembly of config.assemblies ?? []) {
|
|
53
|
-
if (!session.assemblyManager.get(assembly.name)) {
|
|
54
|
-
session.addSessionAssembly(assembly)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Add tracks directly to session (addTrackConf handles duplicates)
|
|
59
|
-
for (const track of config.tracks ?? []) {
|
|
60
|
-
session.addTrackConf(track)
|
|
61
|
-
}
|
|
62
|
-
} catch (e) {
|
|
63
|
-
console.error(e)
|
|
64
|
-
session.notifyError(`Failed to load assembly ${assemblyName}: ${e}`, e)
|
|
65
|
-
} finally {
|
|
66
|
-
fetchingAssemblies.delete(assemblyName)
|
|
67
|
-
}
|
|
68
|
-
}
|