@jbrowse/plugin-linear-genome-view 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.
- package/dist/BaseLinearDisplay/components/Block.d.ts +7 -10
- package/dist/LinearGenomeView/components/HelpDialog.d.ts +5 -0
- package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +3 -5
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +4 -0
- package/dist/LinearGenomeView/components/OverviewRubberBand.d.ts +2 -3
- package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +116 -2
- package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +3 -1
- package/dist/LinearGenomeView/components/ScaleBar.d.ts +14 -0
- package/dist/LinearGenomeView/components/util.d.ts +1 -1
- package/dist/LinearGenomeView/index.d.ts +9 -2
- package/dist/plugin-linear-genome-view.cjs.development.js +3163 -2886
- package/dist/plugin-linear-genome-view.cjs.development.js.map +1 -1
- package/dist/plugin-linear-genome-view.cjs.production.min.js +1 -1
- package/dist/plugin-linear-genome-view.cjs.production.min.js.map +1 -1
- package/dist/plugin-linear-genome-view.esm.js +3122 -2845
- package/dist/plugin-linear-genome-view.esm.js.map +1 -1
- package/package.json +4 -4
- package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +0 -1
- package/src/BaseLinearDisplay/components/Block.tsx +20 -33
- package/src/LinearGenomeView/components/Header.tsx +19 -7
- package/src/LinearGenomeView/components/HelpDialog.tsx +81 -0
- package/src/LinearGenomeView/components/ImportForm.tsx +42 -51
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +30 -245
- package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +317 -0
- package/src/LinearGenomeView/components/OverviewRubberBand.tsx +74 -34
- package/src/LinearGenomeView/components/OverviewScaleBar.tsx +326 -177
- package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +145 -145
- package/src/LinearGenomeView/components/SearchResultsDialog.tsx +12 -34
- package/src/LinearGenomeView/components/SequenceDialog.tsx +9 -8
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +127 -78
- package/src/LinearGenomeView/components/util.ts +6 -4
- package/src/LinearGenomeView/index.tsx +55 -14
- package/src/declare.d.ts +0 -1
|
@@ -1,58 +1,37 @@
|
|
|
1
|
-
import React, { useMemo, useEffect, useState } from 'react'
|
|
1
|
+
import React, { lazy, useMemo, useEffect, useState } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
|
-
|
|
4
|
-
// jbrowse core
|
|
5
3
|
import { getSession, useDebounce, measureText } from '@jbrowse/core/util'
|
|
6
4
|
import BaseResult, {
|
|
7
5
|
RefSequenceResult,
|
|
8
6
|
} from '@jbrowse/core/TextSearch/BaseResults'
|
|
9
|
-
|
|
10
|
-
// material ui
|
|
11
7
|
import {
|
|
12
8
|
CircularProgress,
|
|
9
|
+
IconButton,
|
|
13
10
|
InputAdornment,
|
|
14
11
|
Popper,
|
|
12
|
+
PopperProps,
|
|
15
13
|
TextField,
|
|
16
14
|
TextFieldProps as TFP,
|
|
17
|
-
PopperProps,
|
|
18
15
|
Typography,
|
|
19
16
|
} from '@material-ui/core'
|
|
17
|
+
|
|
18
|
+
// icons
|
|
20
19
|
import SearchIcon from '@material-ui/icons/Search'
|
|
21
20
|
import Autocomplete from '@material-ui/lab/Autocomplete'
|
|
21
|
+
import HelpIcon from '@material-ui/icons/Help'
|
|
22
22
|
|
|
23
23
|
// locals
|
|
24
24
|
import { LinearGenomeViewModel } from '..'
|
|
25
|
+
import { dedupe } from './util'
|
|
26
|
+
|
|
27
|
+
// lazy
|
|
28
|
+
const HelpDialog = lazy(() => import('./HelpDialog'))
|
|
25
29
|
|
|
26
30
|
export interface Option {
|
|
27
31
|
group?: string
|
|
28
32
|
result: BaseResult
|
|
29
33
|
}
|
|
30
34
|
|
|
31
|
-
async function fetchResults(
|
|
32
|
-
self: LinearGenomeViewModel,
|
|
33
|
-
query: string,
|
|
34
|
-
assemblyName: string,
|
|
35
|
-
) {
|
|
36
|
-
const { textSearchManager } = getSession(self)
|
|
37
|
-
const { rankSearchResults } = self
|
|
38
|
-
const searchScope = self.searchScope(assemblyName)
|
|
39
|
-
return textSearchManager
|
|
40
|
-
?.search(
|
|
41
|
-
{
|
|
42
|
-
queryString: query,
|
|
43
|
-
searchType: 'prefix',
|
|
44
|
-
},
|
|
45
|
-
searchScope,
|
|
46
|
-
rankSearchResults,
|
|
47
|
-
)
|
|
48
|
-
.then(results =>
|
|
49
|
-
results.filter(
|
|
50
|
-
(elem, index, self) =>
|
|
51
|
-
index === self.findIndex(t => t.label === elem.label),
|
|
52
|
-
),
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
35
|
// the logic of this method is to only apply a filter to RefSequenceResults
|
|
57
36
|
// because they do not have a matchedObject. the trix search results already
|
|
58
37
|
// filter so don't need re-filtering
|
|
@@ -90,23 +69,28 @@ function RefNameAutocomplete({
|
|
|
90
69
|
onSelect,
|
|
91
70
|
assemblyName,
|
|
92
71
|
style,
|
|
72
|
+
fetchResults,
|
|
93
73
|
value,
|
|
74
|
+
minWidth = 200,
|
|
94
75
|
TextFieldProps = {},
|
|
95
76
|
}: {
|
|
96
77
|
model: LinearGenomeViewModel
|
|
97
78
|
onSelect: (region: BaseResult) => void
|
|
98
79
|
assemblyName?: string
|
|
99
80
|
value?: string
|
|
81
|
+
fetchResults: (query: string) => Promise<BaseResult[]>
|
|
100
82
|
style?: React.CSSProperties
|
|
83
|
+
minWidth?: number
|
|
101
84
|
TextFieldProps?: TFP
|
|
102
85
|
}) {
|
|
103
86
|
const session = getSession(model)
|
|
104
87
|
const { assemblyManager } = session
|
|
105
88
|
const [open, setOpen] = useState(false)
|
|
106
89
|
const [loaded, setLoaded] = useState(true)
|
|
90
|
+
const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
|
|
107
91
|
const [currentSearch, setCurrentSearch] = useState('')
|
|
108
92
|
const [inputValue, setInputValue] = useState('')
|
|
109
|
-
const [searchOptions, setSearchOptions] = useState
|
|
93
|
+
const [searchOptions, setSearchOptions] = useState<Option[]>()
|
|
110
94
|
const debouncedSearch = useDebounce(currentSearch, 300)
|
|
111
95
|
const { coarseVisibleLocStrings, hasDisplayedRegions } = model
|
|
112
96
|
const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined
|
|
@@ -136,11 +120,13 @@ function RefNameAutocomplete({
|
|
|
136
120
|
}
|
|
137
121
|
|
|
138
122
|
setLoaded(false)
|
|
139
|
-
const results = await fetchResults(
|
|
123
|
+
const results = await fetchResults(debouncedSearch)
|
|
140
124
|
if (active) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
125
|
+
setSearchOptions(
|
|
126
|
+
dedupe(results, r => r.getDisplayString()).map(result => ({
|
|
127
|
+
result,
|
|
128
|
+
})),
|
|
129
|
+
)
|
|
144
130
|
setLoaded(true)
|
|
145
131
|
}
|
|
146
132
|
} catch (e) {
|
|
@@ -154,125 +140,139 @@ function RefNameAutocomplete({
|
|
|
154
140
|
return () => {
|
|
155
141
|
active = false
|
|
156
142
|
}
|
|
157
|
-
}, [assemblyName, debouncedSearch, session, model])
|
|
143
|
+
}, [assemblyName, fetchResults, debouncedSearch, session, model])
|
|
158
144
|
|
|
159
145
|
const inputBoxVal = coarseVisibleLocStrings || value || ''
|
|
160
146
|
|
|
161
|
-
// heuristic, text width + icon width
|
|
162
|
-
|
|
147
|
+
// heuristic, text width + icon width
|
|
148
|
+
// + 45 accomodates help icon and search icon
|
|
149
|
+
const width = Math.min(
|
|
150
|
+
Math.max(measureText(inputBoxVal, 16) + 45, minWidth),
|
|
151
|
+
550,
|
|
152
|
+
)
|
|
163
153
|
|
|
164
154
|
// notes on implementation:
|
|
165
155
|
// The selectOnFocus setting helps highlight the field when clicked
|
|
166
156
|
return (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
157
|
+
<>
|
|
158
|
+
<Autocomplete
|
|
159
|
+
id={`refNameAutocomplete-${model.id}`}
|
|
160
|
+
data-testid="autocomplete"
|
|
161
|
+
disableListWrap
|
|
162
|
+
disableClearable
|
|
163
|
+
PopperComponent={MyPopper}
|
|
164
|
+
disabled={!assemblyName}
|
|
165
|
+
freeSolo
|
|
166
|
+
includeInputInList
|
|
167
|
+
selectOnFocus
|
|
168
|
+
style={{ ...style, width }}
|
|
169
|
+
value={inputBoxVal}
|
|
170
|
+
loading={!loaded}
|
|
171
|
+
inputValue={inputValue}
|
|
172
|
+
onInputChange={(event, newInputValue) => setInputValue(newInputValue)}
|
|
173
|
+
loadingText="loading results"
|
|
174
|
+
open={open}
|
|
175
|
+
onOpen={() => setOpen(true)}
|
|
176
|
+
onClose={() => {
|
|
177
|
+
setOpen(false)
|
|
178
|
+
setLoaded(true)
|
|
179
|
+
if (hasDisplayedRegions) {
|
|
180
|
+
setCurrentSearch('')
|
|
181
|
+
setSearchOptions(undefined)
|
|
182
|
+
}
|
|
183
|
+
}}
|
|
184
|
+
onChange={(_event, selectedOption) => {
|
|
185
|
+
if (!selectedOption || !assemblyName) {
|
|
186
|
+
return
|
|
187
|
+
}
|
|
197
188
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
189
|
+
if (typeof selectedOption === 'string') {
|
|
190
|
+
// handles string inputs on keyPress enter
|
|
191
|
+
onSelect(new BaseResult({ label: selectedOption }))
|
|
192
|
+
} else {
|
|
193
|
+
onSelect(selectedOption.result)
|
|
194
|
+
}
|
|
195
|
+
setInputValue(inputBoxVal)
|
|
196
|
+
}}
|
|
197
|
+
options={!searchOptions?.length ? options : searchOptions}
|
|
198
|
+
getOptionDisabled={option => option?.group === 'limitOption'}
|
|
199
|
+
filterOptions={(options, params) => {
|
|
200
|
+
const filtered = filterOptions(
|
|
201
|
+
options,
|
|
202
|
+
params.inputValue.toLocaleLowerCase(),
|
|
203
|
+
)
|
|
204
|
+
return [
|
|
205
|
+
...filtered.slice(0, 100),
|
|
206
|
+
...(filtered.length > 100
|
|
207
|
+
? [
|
|
208
|
+
{
|
|
209
|
+
group: 'limitOption',
|
|
210
|
+
result: new BaseResult({
|
|
211
|
+
label: 'keep typing for more results',
|
|
212
|
+
}),
|
|
213
|
+
},
|
|
214
|
+
]
|
|
215
|
+
: []),
|
|
216
|
+
]
|
|
217
|
+
}}
|
|
218
|
+
renderInput={params => {
|
|
219
|
+
const { helperText, InputProps = {} } = TextFieldProps
|
|
220
|
+
return (
|
|
221
|
+
<TextField
|
|
222
|
+
onBlur={() => {
|
|
223
|
+
// this is used to restore a refName or the non-user-typed input
|
|
224
|
+
// to the box on blurring
|
|
225
|
+
setInputValue(inputBoxVal)
|
|
226
|
+
}}
|
|
227
|
+
{...params}
|
|
228
|
+
{...TextFieldProps}
|
|
229
|
+
helperText={helperText}
|
|
230
|
+
InputProps={{
|
|
231
|
+
...params.InputProps,
|
|
232
|
+
...InputProps,
|
|
242
233
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
234
|
+
endAdornment: (
|
|
235
|
+
<>
|
|
236
|
+
{regions.length === 0 ? (
|
|
237
|
+
<CircularProgress color="inherit" size={20} />
|
|
238
|
+
) : (
|
|
239
|
+
<InputAdornment position="end" style={{ marginRight: 7 }}>
|
|
240
|
+
<SearchIcon />
|
|
241
|
+
<IconButton
|
|
242
|
+
onClick={() => setHelpDialogDisplayed(true)}
|
|
243
|
+
>
|
|
244
|
+
<HelpIcon />
|
|
245
|
+
</IconButton>
|
|
246
|
+
</InputAdornment>
|
|
247
|
+
)}
|
|
248
|
+
{params.InputProps.endAdornment}
|
|
249
|
+
</>
|
|
250
|
+
),
|
|
251
|
+
}}
|
|
252
|
+
placeholder="Search for location"
|
|
253
|
+
onChange={e => {
|
|
254
|
+
setCurrentSearch(e.target.value)
|
|
255
|
+
}}
|
|
256
|
+
/>
|
|
257
|
+
)
|
|
258
|
+
}}
|
|
259
|
+
renderOption={option => {
|
|
260
|
+
const { result } = option
|
|
261
|
+
const component = result.getRenderingComponent()
|
|
262
|
+
if (component && React.isValidElement(component)) {
|
|
263
|
+
return component
|
|
264
|
+
}
|
|
269
265
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
266
|
+
return <Typography noWrap>{result.getDisplayString()}</Typography>
|
|
267
|
+
}}
|
|
268
|
+
getOptionLabel={option =>
|
|
269
|
+
(typeof option === 'string' ? option : option.result.getLabel()) || ''
|
|
270
|
+
}
|
|
271
|
+
/>
|
|
272
|
+
{isHelpDialogDisplayed ? (
|
|
273
|
+
<HelpDialog handleClose={() => setHelpDialogDisplayed(false)} />
|
|
274
|
+
) : null}
|
|
275
|
+
</>
|
|
276
276
|
)
|
|
277
277
|
}
|
|
278
278
|
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
Dialog,
|
|
7
7
|
DialogActions,
|
|
8
8
|
DialogContent,
|
|
9
|
-
DialogContentText,
|
|
10
9
|
DialogTitle,
|
|
11
10
|
Divider,
|
|
12
11
|
IconButton,
|
|
@@ -18,10 +17,9 @@ import {
|
|
|
18
17
|
TableRow,
|
|
19
18
|
Typography,
|
|
20
19
|
Paper,
|
|
20
|
+
makeStyles,
|
|
21
21
|
} from '@material-ui/core'
|
|
22
22
|
import CloseIcon from '@material-ui/icons/Close'
|
|
23
|
-
import { makeStyles } from '@material-ui/core/styles'
|
|
24
|
-
import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
|
|
25
23
|
import { LinearGenomeViewModel } from '../..'
|
|
26
24
|
|
|
27
25
|
export const useStyles = makeStyles(theme => ({
|
|
@@ -101,8 +99,8 @@ export default function SearchResultsDialog({
|
|
|
101
99
|
|
|
102
100
|
return (
|
|
103
101
|
<Dialog open maxWidth="xl" onClose={handleClose}>
|
|
104
|
-
<DialogTitle
|
|
105
|
-
Search
|
|
102
|
+
<DialogTitle>
|
|
103
|
+
Search results
|
|
106
104
|
{handleClose ? (
|
|
107
105
|
<IconButton
|
|
108
106
|
data-testid="close-resultsDialog"
|
|
@@ -117,18 +115,15 @@ export default function SearchResultsDialog({
|
|
|
117
115
|
</DialogTitle>
|
|
118
116
|
<Divider />
|
|
119
117
|
<DialogContent>
|
|
120
|
-
{model.searchResults?.length
|
|
121
|
-
model.searchResults === undefined ? (
|
|
118
|
+
{!model.searchResults?.length ? (
|
|
122
119
|
<Typography>
|
|
123
|
-
|
|
124
|
-
<b>{model.searchQuery}</b>
|
|
120
|
+
No results found for <b>{model.searchQuery}</b>
|
|
125
121
|
</Typography>
|
|
126
122
|
) : (
|
|
127
123
|
<>
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
</DialogContentText>
|
|
124
|
+
<Typography>
|
|
125
|
+
Showing results for <b>{model.searchQuery}</b>
|
|
126
|
+
</Typography>
|
|
132
127
|
<TableContainer component={Paper}>
|
|
133
128
|
<Table>
|
|
134
129
|
<TableHead>
|
|
@@ -140,8 +135,8 @@ export default function SearchResultsDialog({
|
|
|
140
135
|
</TableRow>
|
|
141
136
|
</TableHead>
|
|
142
137
|
<TableBody>
|
|
143
|
-
{model.searchResults.map(
|
|
144
|
-
<TableRow key={`${result.
|
|
138
|
+
{model.searchResults.map(result => (
|
|
139
|
+
<TableRow key={`${result.getId()}`}>
|
|
145
140
|
<TableCell component="th" scope="row">
|
|
146
141
|
{result.getLabel()}
|
|
147
142
|
</TableCell>
|
|
@@ -151,18 +146,6 @@ export default function SearchResultsDialog({
|
|
|
151
146
|
<TableCell align="right">
|
|
152
147
|
{getTrackName(result.getTrackId()) || 'N/A'}
|
|
153
148
|
</TableCell>
|
|
154
|
-
<TableCell align="right">
|
|
155
|
-
<Button
|
|
156
|
-
onClick={() => {
|
|
157
|
-
handleClick(result.getLocation())
|
|
158
|
-
handleClose()
|
|
159
|
-
}}
|
|
160
|
-
color="primary"
|
|
161
|
-
variant="contained"
|
|
162
|
-
>
|
|
163
|
-
Go to location
|
|
164
|
-
</Button>
|
|
165
|
-
</TableCell>
|
|
166
149
|
<TableCell align="right">
|
|
167
150
|
<Button
|
|
168
151
|
onClick={() => {
|
|
@@ -177,7 +160,7 @@ export default function SearchResultsDialog({
|
|
|
177
160
|
color="primary"
|
|
178
161
|
variant="contained"
|
|
179
162
|
>
|
|
180
|
-
|
|
163
|
+
Go
|
|
181
164
|
</Button>
|
|
182
165
|
</TableCell>
|
|
183
166
|
</TableRow>
|
|
@@ -190,12 +173,7 @@ export default function SearchResultsDialog({
|
|
|
190
173
|
</DialogContent>
|
|
191
174
|
<Divider />
|
|
192
175
|
<DialogActions>
|
|
193
|
-
<Button
|
|
194
|
-
onClick={() => {
|
|
195
|
-
handleClose()
|
|
196
|
-
}}
|
|
197
|
-
color="primary"
|
|
198
|
-
>
|
|
176
|
+
<Button onClick={() => handleClose()} color="primary">
|
|
199
177
|
Cancel
|
|
200
178
|
</Button>
|
|
201
179
|
</DialogActions>
|
|
@@ -17,14 +17,18 @@ import {
|
|
|
17
17
|
import { observer } from 'mobx-react'
|
|
18
18
|
import { saveAs } from 'file-saver'
|
|
19
19
|
import { Region } from '@jbrowse/core/util/types'
|
|
20
|
-
import {
|
|
20
|
+
import { getConf } from '@jbrowse/core/configuration'
|
|
21
21
|
import copy from 'copy-to-clipboard'
|
|
22
|
-
import { ContentCopy as ContentCopyIcon } from '@jbrowse/core/ui/Icons'
|
|
23
|
-
import CloseIcon from '@material-ui/icons/Close'
|
|
24
|
-
import GetAppIcon from '@material-ui/icons/GetApp'
|
|
25
22
|
import { getSession } from '@jbrowse/core/util'
|
|
26
23
|
import { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
27
24
|
import { formatSeqFasta } from '@jbrowse/core/util/formatFastaStrings'
|
|
25
|
+
|
|
26
|
+
// icons
|
|
27
|
+
import { ContentCopy as ContentCopyIcon } from '@jbrowse/core/ui/Icons'
|
|
28
|
+
import CloseIcon from '@material-ui/icons/Close'
|
|
29
|
+
import GetAppIcon from '@material-ui/icons/GetApp'
|
|
30
|
+
|
|
31
|
+
// locals
|
|
28
32
|
import { LinearGenomeViewModel } from '..'
|
|
29
33
|
|
|
30
34
|
const useStyles = makeStyles(theme => ({
|
|
@@ -71,10 +75,7 @@ async function fetchSequence(
|
|
|
71
75
|
if (!assembly) {
|
|
72
76
|
throw new Error(`assembly ${assemblyName} not found`)
|
|
73
77
|
}
|
|
74
|
-
const adapterConfig =
|
|
75
|
-
'sequence',
|
|
76
|
-
'adapter',
|
|
77
|
-
])
|
|
78
|
+
const adapterConfig = getConf(assembly, ['sequence', 'adapter'])
|
|
78
79
|
|
|
79
80
|
const sessionId = 'getSequence'
|
|
80
81
|
const chunks = (await Promise.all(
|