@apollo-annotation/shared 0.1.18 → 0.1.20
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/Changes/AddAssemblyAndFeaturesFromFileChange.d.ts +33 -0
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js +83 -0
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js.map +1 -0
- package/dist/Changes/AddAssemblyFromExternalChange.d.ts +34 -0
- package/dist/Changes/AddAssemblyFromExternalChange.js +97 -0
- package/dist/Changes/AddAssemblyFromExternalChange.js.map +1 -0
- package/dist/Changes/AddAssemblyFromFileChange.d.ts +43 -0
- package/dist/Changes/AddAssemblyFromFileChange.js +140 -0
- package/dist/Changes/AddAssemblyFromFileChange.js.map +1 -0
- package/dist/Changes/AddFeatureChange.d.ts +35 -0
- package/dist/Changes/AddFeatureChange.js +169 -0
- package/dist/Changes/AddFeatureChange.js.map +1 -0
- package/dist/Changes/AddFeaturesFromFileChange.d.ts +32 -0
- package/dist/Changes/AddFeaturesFromFileChange.js +76 -0
- package/dist/Changes/AddFeaturesFromFileChange.js.map +1 -0
- package/dist/Changes/AddRefSeqAliasesChange.d.ts +20 -0
- package/dist/Changes/AddRefSeqAliasesChange.js +61 -0
- package/dist/Changes/AddRefSeqAliasesChange.js.map +1 -0
- package/dist/Changes/DeleteAssemblyChange.d.ts +18 -0
- package/dist/Changes/DeleteAssemblyChange.js +72 -0
- package/dist/Changes/DeleteAssemblyChange.js.map +1 -0
- package/dist/Changes/DeleteFeatureChange.d.ts +42 -0
- package/dist/Changes/DeleteFeatureChange.js +143 -0
- package/dist/Changes/DeleteFeatureChange.js.map +1 -0
- package/dist/Changes/DeleteUserChange.d.ts +25 -0
- package/dist/Changes/DeleteUserChange.js +53 -0
- package/dist/Changes/DeleteUserChange.js.map +1 -0
- package/dist/Changes/FeatureAttributeChange.d.ts +31 -0
- package/dist/Changes/FeatureAttributeChange.js +112 -0
- package/dist/Changes/FeatureAttributeChange.js.map +1 -0
- package/dist/Changes/FromFileBaseChange.d.ts +9 -0
- package/dist/Changes/FromFileBaseChange.js +187 -0
- package/dist/Changes/FromFileBaseChange.js.map +1 -0
- package/dist/Changes/ImportJBrowseConfigChange.d.ts +43 -0
- package/dist/Changes/ImportJBrowseConfigChange.js +67 -0
- package/dist/Changes/ImportJBrowseConfigChange.js.map +1 -0
- package/dist/Changes/LocationEndChange.d.ts +32 -0
- package/dist/Changes/LocationEndChange.js +129 -0
- package/dist/Changes/LocationEndChange.js.map +1 -0
- package/dist/Changes/LocationStartChange.d.ts +32 -0
- package/dist/Changes/LocationStartChange.js +129 -0
- package/dist/Changes/LocationStartChange.js.map +1 -0
- package/dist/Changes/StrandChange.d.ts +31 -0
- package/dist/Changes/StrandChange.js +114 -0
- package/dist/Changes/StrandChange.js.map +1 -0
- package/dist/Changes/TypeChange.d.ts +31 -0
- package/dist/Changes/TypeChange.js +114 -0
- package/dist/Changes/TypeChange.js.map +1 -0
- package/dist/Changes/UserChange.d.ts +25 -0
- package/dist/Changes/UserChange.js +51 -0
- package/dist/Changes/UserChange.js.map +1 -0
- package/dist/Changes/index.d.ts +50 -0
- package/dist/Changes/index.js +55 -0
- package/dist/Changes/index.js.map +1 -0
- package/dist/Checks/CDSCheck.d.ts +8 -0
- package/dist/Checks/CDSCheck.js +197 -0
- package/dist/Checks/CDSCheck.js.map +1 -0
- package/dist/Checks/index.d.ts +1 -0
- package/dist/Checks/index.js +5 -0
- package/dist/Checks/index.js.map +1 -0
- package/dist/Common/index.d.ts +1 -0
- package/dist/Common/index.js +5 -0
- package/dist/Common/index.js.map +1 -0
- package/dist/Common/jwtPayload.d.ts +12 -0
- package/dist/Common/jwtPayload.js +16 -0
- package/dist/Common/jwtPayload.js.map +1 -0
- package/dist/GFF3/gff3ToAnnotationFeature.d.ts +3 -0
- package/dist/GFF3/gff3ToAnnotationFeature.js +211 -0
- package/dist/GFF3/gff3ToAnnotationFeature.js.map +1 -0
- package/dist/GFF3/gff3ToAnnotationFeature.test.d.ts +1 -0
- package/dist/GFF3/gff3ToAnnotationFeature.test.js +174 -0
- package/dist/GFF3/gff3ToAnnotationFeature.test.js.map +1 -0
- package/dist/GFF3/gffReservedKeys.d.ts +5 -0
- package/dist/GFF3/gffReservedKeys.js +34 -0
- package/dist/GFF3/gffReservedKeys.js.map +1 -0
- package/dist/GFF3/index.d.ts +2 -0
- package/dist/GFF3/index.js +6 -0
- package/dist/GFF3/index.js.map +1 -0
- package/dist/Messages.d.ts +28 -0
- package/dist/Messages.js +3 -0
- package/dist/Messages.js.map +1 -0
- package/dist/Operations/GetAssembliesOperation.d.ts +13 -0
- package/dist/Operations/GetAssembliesOperation.js +20 -0
- package/dist/Operations/GetAssembliesOperation.js.map +1 -0
- package/dist/Operations/GetFeaturesOperation.d.ts +26 -0
- package/dist/Operations/GetFeaturesOperation.js +42 -0
- package/dist/Operations/GetFeaturesOperation.js.map +1 -0
- package/dist/Operations/index.d.ts +8 -0
- package/dist/Operations/index.js +10 -0
- package/dist/Operations/index.js.map +1 -0
- package/dist/Validations/CoreValidation.d.ts +17 -0
- package/dist/Validations/CoreValidation.js +36 -0
- package/dist/Validations/CoreValidation.js.map +1 -0
- package/dist/Validations/ParentChildValidation.d.ts +17 -0
- package/dist/Validations/ParentChildValidation.js +61 -0
- package/dist/Validations/ParentChildValidation.js.map +1 -0
- package/dist/Validations/Validation.d.ts +27 -0
- package/dist/Validations/Validation.js +27 -0
- package/dist/Validations/Validation.js.map +1 -0
- package/dist/Validations/ValidationSet.d.ts +24 -0
- package/dist/Validations/ValidationSet.js +86 -0
- package/dist/Validations/ValidationSet.js.map +1 -0
- package/dist/Validations/index.d.ts +4 -0
- package/dist/Validations/index.js +8 -0
- package/dist/Validations/index.js.map +1 -0
- package/dist/Validations/soSequenceTypes.d.ts +2 -0
- package/dist/Validations/soSequenceTypes.js +1868 -0
- package/dist/Validations/soSequenceTypes.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/util.d.ts +4 -0
- package/dist/util.js +102 -0
- package/dist/util.js.map +1 -0
- package/package.json +17 -8
- package/src/Changes/AddAssemblyAndFeaturesFromFileChange.ts +13 -9
- package/src/Changes/AddAssemblyFromFileChange.ts +129 -43
- package/src/Changes/AddFeatureChange.ts +2 -3
- package/src/Changes/AddFeaturesFromFileChange.ts +8 -3
- package/src/Changes/AddRefSeqAliasesChange.ts +88 -0
- package/src/Changes/DeleteAssemblyChange.ts +1 -1
- package/src/Changes/DeleteFeatureChange.ts +1 -1
- package/src/Changes/FeatureAttributeChange.ts +1 -1
- package/src/Changes/FromFileBaseChange.ts +221 -0
- package/src/Changes/ImportJBrowseConfigChange.ts +116 -0
- package/src/Changes/LocationEndChange.ts +25 -18
- package/src/Changes/LocationStartChange.ts +25 -18
- package/src/Changes/TypeChange.ts +1 -1
- package/src/Changes/index.ts +6 -6
- package/src/Checks/CDSCheck.ts +125 -173
- package/src/Common/jwtPayload.ts +1 -1
- package/src/GFF3/gff3ToAnnotationFeature.test.ts +209 -0
- package/src/GFF3/gff3ToAnnotationFeature.ts +257 -0
- package/src/GFF3/gffReservedKeys.ts +61 -0
- package/src/GFF3/index.ts +2 -0
- package/src/Operations/GetFeaturesOperation.ts +2 -2
- package/src/Validations/ParentChildValidation.ts +5 -5
- package/src/index.ts +1 -0
- package/src/util.ts +16 -12
- package/test_data/braker.gff +13 -0
- package/test_data/example01.gff3 +26 -0
- package/test_data/example01.json +236 -0
- package/test_data/example02.json +225 -0
- package/test_data/example04.json +225 -0
- package/test_data/example05.gff3 +30 -0
- package/test_data/example06.gff3 +30 -0
- package/test_data/example07.gff3 +30 -0
- package/test_data/gene_mrna.gff3 +4 -0
- package/test_data/gene_representations.gff3 +1781 -0
- package/test_data/one_cds.gff3 +9 -0
- package/test_data/one_cds.json +67 -0
- package/test_data/two_cds.gff3 +9 -0
- package/test_data/two_cds.json +67 -0
- package/tsconfig.json +4 -4
- package/src/Changes/DiscontinuousLocationEndChange.ts +0 -182
- package/src/Changes/DiscontinuousLocationStartChange.ts +0 -182
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
6
|
+
import {
|
|
7
|
+
AssemblySpecificChange,
|
|
8
|
+
ServerDataStore,
|
|
9
|
+
} from '@apollo-annotation/common'
|
|
10
|
+
import { FileDocument, RefSeqDocument } from '@apollo-annotation/schemas'
|
|
11
|
+
import { GFF3Feature } from '@gmod/gff'
|
|
12
|
+
|
|
13
|
+
import { gff3ToAnnotationFeature } from '../GFF3'
|
|
14
|
+
|
|
15
|
+
export abstract class FromFileBaseChange extends AssemblySpecificChange {
|
|
16
|
+
async addRefSeqIntoDb(
|
|
17
|
+
fileDoc: FileDocument,
|
|
18
|
+
assembly: string,
|
|
19
|
+
backend: ServerDataStore,
|
|
20
|
+
) {
|
|
21
|
+
const { logger } = this
|
|
22
|
+
const { filesService, refSeqChunkModel, refSeqModel, user } = backend
|
|
23
|
+
const { CHUNK_SIZE } = process.env
|
|
24
|
+
const customChunkSize = CHUNK_SIZE && Number(CHUNK_SIZE)
|
|
25
|
+
let chunkIndex = 0
|
|
26
|
+
let refSeqLen = 0
|
|
27
|
+
let refSeqDoc: RefSeqDocument | undefined
|
|
28
|
+
let fastaInfoStarted = fileDoc.type !== 'text/x-gff3'
|
|
29
|
+
|
|
30
|
+
// Read data from compressed file and parse the content
|
|
31
|
+
const sequenceStream = filesService.getFileStream(fileDoc)
|
|
32
|
+
let sequenceBuffer = ''
|
|
33
|
+
let incompleteLine = ''
|
|
34
|
+
let lastLineIsIncomplete = true
|
|
35
|
+
let parsingStarted = false
|
|
36
|
+
logger.debug?.('starting sequence stream')
|
|
37
|
+
let lineCount = 0
|
|
38
|
+
for await (const data of sequenceStream) {
|
|
39
|
+
const chunk = data.toString()
|
|
40
|
+
lastLineIsIncomplete = !chunk.endsWith('\n')
|
|
41
|
+
// chunk is small enough that you can split the whole thing into lines without having to make it into smaller chunks first.
|
|
42
|
+
const lines = chunk.split(/\r?\n/)
|
|
43
|
+
if (incompleteLine) {
|
|
44
|
+
lines[0] = `${incompleteLine}${lines[0]}`
|
|
45
|
+
incompleteLine = ''
|
|
46
|
+
}
|
|
47
|
+
if (lastLineIsIncomplete) {
|
|
48
|
+
incompleteLine = lines.pop() || ''
|
|
49
|
+
}
|
|
50
|
+
for await (const line of lines) {
|
|
51
|
+
lineCount++
|
|
52
|
+
if (lineCount % 1_000_000 === 0) {
|
|
53
|
+
logger.debug?.(`Processed ${lineCount} lines`)
|
|
54
|
+
}
|
|
55
|
+
// In case of GFF3 file we start to read sequence after '##FASTA' is found
|
|
56
|
+
if (!fastaInfoStarted) {
|
|
57
|
+
if (line.trim() === '##FASTA') {
|
|
58
|
+
fastaInfoStarted = true
|
|
59
|
+
}
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
const refSeqInfoLine = /^>\s*(\S+)\s*(.*)/.exec(line)
|
|
63
|
+
// Add new ref sequence info if we are reference seq info line
|
|
64
|
+
if (refSeqInfoLine) {
|
|
65
|
+
parsingStarted = true
|
|
66
|
+
logger.debug?.(
|
|
67
|
+
`Reference sequence information line "${refSeqInfoLine[0]}"`,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
// If there is sequence from previous reference sequence then we need to add it to previous ref seq
|
|
71
|
+
if (sequenceBuffer !== '') {
|
|
72
|
+
if (!refSeqDoc) {
|
|
73
|
+
throw new Error('No refSeq document found')
|
|
74
|
+
}
|
|
75
|
+
refSeqLen += sequenceBuffer.length
|
|
76
|
+
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
77
|
+
await refSeqChunkModel.create([
|
|
78
|
+
{
|
|
79
|
+
refSeq: refSeqDoc._id,
|
|
80
|
+
n: chunkIndex,
|
|
81
|
+
sequence: sequenceBuffer,
|
|
82
|
+
user,
|
|
83
|
+
status: -1,
|
|
84
|
+
},
|
|
85
|
+
])
|
|
86
|
+
sequenceBuffer = ''
|
|
87
|
+
}
|
|
88
|
+
await refSeqDoc?.updateOne({ length: refSeqLen })
|
|
89
|
+
// await refSeqDoc?.updateOne({ length: refSeqLen }, { session })
|
|
90
|
+
refSeqLen = 0
|
|
91
|
+
chunkIndex = 0
|
|
92
|
+
|
|
93
|
+
const name = refSeqInfoLine[1].trim()
|
|
94
|
+
const description = refSeqInfoLine[2] ? refSeqInfoLine[2].trim() : ''
|
|
95
|
+
|
|
96
|
+
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
97
|
+
const [newRefSeqDoc] = await refSeqModel.create([
|
|
98
|
+
{
|
|
99
|
+
name,
|
|
100
|
+
description,
|
|
101
|
+
assembly,
|
|
102
|
+
length: 0,
|
|
103
|
+
...(customChunkSize ? { chunkSize: customChunkSize } : null),
|
|
104
|
+
user,
|
|
105
|
+
status: -1,
|
|
106
|
+
},
|
|
107
|
+
])
|
|
108
|
+
logger.debug?.(
|
|
109
|
+
`Added new refSeq "${name}", desc "${description}", docId "${newRefSeqDoc._id}"`,
|
|
110
|
+
)
|
|
111
|
+
refSeqDoc = newRefSeqDoc
|
|
112
|
+
} else if (/\S/.test(line)) {
|
|
113
|
+
if (!refSeqDoc) {
|
|
114
|
+
throw new Error('No refSeq document found')
|
|
115
|
+
}
|
|
116
|
+
const { _id, chunkSize } = refSeqDoc
|
|
117
|
+
sequenceBuffer += line.replaceAll(/\s/g, '')
|
|
118
|
+
// If sequence block > chunk size then save chunk into Mongo
|
|
119
|
+
while (sequenceBuffer.length >= chunkSize) {
|
|
120
|
+
const sequence = sequenceBuffer.slice(0, chunkSize)
|
|
121
|
+
refSeqLen += sequence.length
|
|
122
|
+
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
123
|
+
await refSeqChunkModel.create([
|
|
124
|
+
{ refSeq: _id, n: chunkIndex, sequence, user, status: -1 },
|
|
125
|
+
])
|
|
126
|
+
chunkIndex++
|
|
127
|
+
// Set remaining sequence
|
|
128
|
+
sequenceBuffer = sequenceBuffer.slice(chunkSize)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (!parsingStarted) {
|
|
134
|
+
throw new Error('No reference sequences found in file')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (sequenceBuffer || lastLineIsIncomplete) {
|
|
138
|
+
if (!refSeqDoc) {
|
|
139
|
+
throw new Error('No refSeq document found')
|
|
140
|
+
}
|
|
141
|
+
// If the file did not end with line break so the last line is incomplete
|
|
142
|
+
if (lastLineIsIncomplete) {
|
|
143
|
+
sequenceBuffer += incompleteLine
|
|
144
|
+
}
|
|
145
|
+
refSeqLen += sequenceBuffer.length
|
|
146
|
+
logger.verbose?.(
|
|
147
|
+
`*** Add the very last chunk to ref seq ("${refSeqDoc._id}", index ${chunkIndex} and total length for ref seq is ${refSeqLen}): "${sequenceBuffer}"`,
|
|
148
|
+
)
|
|
149
|
+
logger.debug?.(
|
|
150
|
+
`Creating refSeq chunk number ${chunkIndex} of "${refSeqDoc._id}"`,
|
|
151
|
+
)
|
|
152
|
+
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
153
|
+
await refSeqChunkModel.create([
|
|
154
|
+
{
|
|
155
|
+
refSeq: refSeqDoc._id,
|
|
156
|
+
n: chunkIndex,
|
|
157
|
+
sequence: sequenceBuffer,
|
|
158
|
+
user,
|
|
159
|
+
status: -1,
|
|
160
|
+
},
|
|
161
|
+
])
|
|
162
|
+
await refSeqDoc.updateOne({ length: refSeqLen })
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private refSeqCache = new Map<string, RefSeqDocument>()
|
|
167
|
+
|
|
168
|
+
async removeExistingFeatures(backend: ServerDataStore) {
|
|
169
|
+
const { featureModel, refSeqModel } = backend
|
|
170
|
+
const { assembly, logger } = this
|
|
171
|
+
logger.debug?.(`Removing existing features for assembly = ${assembly}`)
|
|
172
|
+
|
|
173
|
+
const refSeqs: RefSeqDocument[] = await refSeqModel
|
|
174
|
+
.find({ assembly })
|
|
175
|
+
.exec()
|
|
176
|
+
|
|
177
|
+
for (const refSeq of refSeqs) {
|
|
178
|
+
await featureModel.deleteMany({ refSeq: refSeq._id })
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async addFeatureIntoDb(gff3Feature: GFF3Feature, backend: ServerDataStore) {
|
|
183
|
+
const { featureModel, refSeqModel, user } = backend
|
|
184
|
+
const { assembly, refSeqCache } = this
|
|
185
|
+
|
|
186
|
+
const [{ seq_id: refName }] = gff3Feature
|
|
187
|
+
if (!refName) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
`Valid seq_id not found in feature ${JSON.stringify(gff3Feature)}`,
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
let refSeqDoc = refSeqCache.get(refName)
|
|
193
|
+
if (!refSeqDoc) {
|
|
194
|
+
refSeqDoc =
|
|
195
|
+
(await refSeqModel.findOne({ assembly, name: refName }).exec()) ??
|
|
196
|
+
undefined
|
|
197
|
+
if (refSeqDoc) {
|
|
198
|
+
refSeqCache.set(refName, refSeqDoc)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!refSeqDoc) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
`RefSeq was not found by assembly "${assembly}" and seq_id "${refName}" not found`,
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
// Let's add featureId to parent feature
|
|
207
|
+
const featureIds: string[] = []
|
|
208
|
+
|
|
209
|
+
const newFeature = gff3ToAnnotationFeature(
|
|
210
|
+
gff3Feature,
|
|
211
|
+
refSeqDoc._id,
|
|
212
|
+
featureIds,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
// Add into Mongo
|
|
216
|
+
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
217
|
+
await featureModel.create([
|
|
218
|
+
{ allIds: featureIds, ...newFeature, user, status: -1 },
|
|
219
|
+
])
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
2
|
+
import {
|
|
3
|
+
Change,
|
|
4
|
+
ChangeOptions,
|
|
5
|
+
ClientDataStore,
|
|
6
|
+
LocalGFF3DataStore,
|
|
7
|
+
ServerDataStore,
|
|
8
|
+
} from '@apollo-annotation/common'
|
|
9
|
+
|
|
10
|
+
interface JBrowseAssembly {
|
|
11
|
+
sequence: { adapter: { type: string } }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface JBrowseTrack {
|
|
15
|
+
type: string
|
|
16
|
+
trackId: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface JBrowsePlugin {
|
|
20
|
+
name: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface JBrowseInternetAccount {
|
|
24
|
+
type: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface JBrowseConfig {
|
|
28
|
+
assemblies?: JBrowseAssembly[]
|
|
29
|
+
tracks?: JBrowseTrack[]
|
|
30
|
+
plugins?: JBrowsePlugin[]
|
|
31
|
+
internetAccounts?: JBrowseInternetAccount[]
|
|
32
|
+
[key: string]: unknown
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SerializedImportJBrowseConfigChange {
|
|
36
|
+
typeName: 'ImportJBrowseConfigChange'
|
|
37
|
+
oldJBrowseConfig?: JBrowseConfig
|
|
38
|
+
newJBrowseConfig?: JBrowseConfig
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function filterJBrowseConfig(config: JBrowseConfig): JBrowseConfig {
|
|
42
|
+
const { assemblies, internetAccounts, plugins, tracks, ...rest } = config
|
|
43
|
+
const filteredAssemblies = assemblies?.filter(
|
|
44
|
+
(a) => a.sequence.adapter.type !== 'ApolloSequenceAdapter',
|
|
45
|
+
)
|
|
46
|
+
const filteredTracks = tracks?.filter((t) => t.type !== 'ApolloTrack')
|
|
47
|
+
const filteredPlugins = plugins?.filter((p) => p.name !== 'Apollo')
|
|
48
|
+
const filteredInternetAccounts = internetAccounts?.filter(
|
|
49
|
+
(i) => i.type !== 'ApolloInternetAccount',
|
|
50
|
+
)
|
|
51
|
+
const filteredConfig = rest as JBrowseConfig
|
|
52
|
+
if (filteredAssemblies) {
|
|
53
|
+
filteredConfig.assemblies = filteredAssemblies
|
|
54
|
+
}
|
|
55
|
+
if (filteredTracks) {
|
|
56
|
+
filteredConfig.tracks = filteredTracks
|
|
57
|
+
}
|
|
58
|
+
if (filteredPlugins) {
|
|
59
|
+
filteredConfig.plugins = filteredPlugins
|
|
60
|
+
}
|
|
61
|
+
if (filteredInternetAccounts) {
|
|
62
|
+
filteredConfig.internetAccounts = filteredInternetAccounts
|
|
63
|
+
}
|
|
64
|
+
return filteredConfig
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class ImportJBrowseConfigChange extends Change {
|
|
68
|
+
typeName = 'ImportJBrowseConfigChange' as const
|
|
69
|
+
oldJBrowseConfig?: JBrowseConfig
|
|
70
|
+
newJBrowseConfig?: JBrowseConfig
|
|
71
|
+
|
|
72
|
+
constructor(
|
|
73
|
+
json: SerializedImportJBrowseConfigChange,
|
|
74
|
+
options?: ChangeOptions,
|
|
75
|
+
) {
|
|
76
|
+
super(json, options)
|
|
77
|
+
this.oldJBrowseConfig = json.oldJBrowseConfig
|
|
78
|
+
this.newJBrowseConfig = json.newJBrowseConfig
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
toJSON(): SerializedImportJBrowseConfigChange {
|
|
82
|
+
const { newJBrowseConfig, oldJBrowseConfig, typeName } = this
|
|
83
|
+
return { typeName, oldJBrowseConfig, newJBrowseConfig }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async executeOnServer(backend: ServerDataStore) {
|
|
87
|
+
const { jbrowseConfigModel } = backend
|
|
88
|
+
const { logger, newJBrowseConfig } = this
|
|
89
|
+
await jbrowseConfigModel.deleteMany()
|
|
90
|
+
if (!newJBrowseConfig) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
const filteredConfig = filterJBrowseConfig(newJBrowseConfig)
|
|
94
|
+
await jbrowseConfigModel.create(filteredConfig)
|
|
95
|
+
logger.debug?.('Stored new JBrowse Config')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
99
|
+
throw new Error('executeOnLocalGFF3 not implemented')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
103
|
+
async executeOnClient(_dataStore: ClientDataStore) {}
|
|
104
|
+
|
|
105
|
+
getInverse() {
|
|
106
|
+
const { logger, newJBrowseConfig, oldJBrowseConfig } = this
|
|
107
|
+
return new ImportJBrowseConfigChange(
|
|
108
|
+
{
|
|
109
|
+
typeName: 'ImportJBrowseConfigChange',
|
|
110
|
+
oldJBrowseConfig: newJBrowseConfig,
|
|
111
|
+
newJBrowseConfig: oldJBrowseConfig,
|
|
112
|
+
},
|
|
113
|
+
{ logger },
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -30,7 +30,7 @@ interface SerializedLocationEndChangeMultiple
|
|
|
30
30
|
changes: LocationEndChangeDetails[]
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
type SerializedLocationEndChange =
|
|
33
|
+
export type SerializedLocationEndChange =
|
|
34
34
|
| SerializedLocationEndChangeSingle
|
|
35
35
|
| SerializedLocationEndChangeMultiple
|
|
36
36
|
|
|
@@ -80,7 +80,9 @@ export class LocationEndChange extends FeatureChange {
|
|
|
80
80
|
throw new Error(errMsg)
|
|
81
81
|
// throw new NotFoundException(errMsg) -- This is causing runtime error because Exception comes from @nestjs/common!!!
|
|
82
82
|
}
|
|
83
|
-
logger.debug?.(
|
|
83
|
+
logger.debug?.(
|
|
84
|
+
`*** TOP level feature found: ${JSON.stringify(topLevelFeature)}`,
|
|
85
|
+
)
|
|
84
86
|
|
|
85
87
|
const foundFeature = this.getFeatureFromId(topLevelFeature, featureId)
|
|
86
88
|
if (!foundFeature) {
|
|
@@ -89,28 +91,33 @@ export class LocationEndChange extends FeatureChange {
|
|
|
89
91
|
throw new Error(errMsg)
|
|
90
92
|
}
|
|
91
93
|
logger.debug?.(`*** Found feature: ${JSON.stringify(foundFeature)}`)
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
if (foundFeature.max === oldEnd) {
|
|
95
|
+
featuresForChanges.push({ feature: foundFeature, topLevelFeature })
|
|
96
|
+
} else {
|
|
97
|
+
if (foundFeature.children) {
|
|
98
|
+
for (const [, childFeature] of foundFeature.children) {
|
|
99
|
+
if (childFeature.max === oldEnd) {
|
|
100
|
+
logger.debug?.(
|
|
101
|
+
`*************** UPDATE CHILD FEATURE ID= ${featureId}, CHILD: ${JSON.stringify(
|
|
102
|
+
childFeature,
|
|
103
|
+
)}`,
|
|
104
|
+
)
|
|
105
|
+
featuresForChanges.push({
|
|
106
|
+
feature: childFeature,
|
|
107
|
+
topLevelFeature,
|
|
108
|
+
})
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
105
113
|
}
|
|
106
|
-
featuresForChanges.push({ feature: foundFeature, topLevelFeature })
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
// Let's update objects.
|
|
110
117
|
for (const [idx, change] of changes.entries()) {
|
|
111
118
|
const { newEnd } = change
|
|
112
119
|
const { feature, topLevelFeature } = featuresForChanges[idx]
|
|
113
|
-
feature.
|
|
120
|
+
feature.max = newEnd
|
|
114
121
|
if (topLevelFeature._id.equals(feature._id)) {
|
|
115
122
|
topLevelFeature.markModified('end') // Mark as modified. Without this save() -method is not updating data in database
|
|
116
123
|
} else {
|
|
@@ -144,7 +151,7 @@ export class LocationEndChange extends FeatureChange {
|
|
|
144
151
|
if (!feature) {
|
|
145
152
|
throw new Error(`Could not find feature with identifier "${changedId}"`)
|
|
146
153
|
}
|
|
147
|
-
feature.
|
|
154
|
+
feature.setMax(this.changes[idx].newEnd)
|
|
148
155
|
}
|
|
149
156
|
}
|
|
150
157
|
|
|
@@ -30,7 +30,7 @@ interface SerializedLocationStartChangeMultiple
|
|
|
30
30
|
changes: LocationStartChangeDetails[]
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
type SerializedLocationStartChange =
|
|
33
|
+
export type SerializedLocationStartChange =
|
|
34
34
|
| SerializedLocationStartChangeSingle
|
|
35
35
|
| SerializedLocationStartChangeMultiple
|
|
36
36
|
|
|
@@ -80,7 +80,9 @@ export class LocationStartChange extends FeatureChange {
|
|
|
80
80
|
throw new Error(errMsg)
|
|
81
81
|
// throw new NotFoundException(errMsg) -- This is causing runtime error because Exception comes from @nestjs/common!!!
|
|
82
82
|
}
|
|
83
|
-
logger.debug?.(
|
|
83
|
+
logger.debug?.(
|
|
84
|
+
`*** TOP level feature found: ${JSON.stringify(topLevelFeature)}`,
|
|
85
|
+
)
|
|
84
86
|
|
|
85
87
|
const foundFeature = this.getFeatureFromId(topLevelFeature, featureId)
|
|
86
88
|
if (!foundFeature) {
|
|
@@ -89,28 +91,33 @@ export class LocationStartChange extends FeatureChange {
|
|
|
89
91
|
throw new Error(errMsg)
|
|
90
92
|
}
|
|
91
93
|
logger.debug?.(`*** Found feature: ${JSON.stringify(foundFeature)}`)
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
if (foundFeature.min === oldStart) {
|
|
95
|
+
featuresForChanges.push({ feature: foundFeature, topLevelFeature })
|
|
96
|
+
} else {
|
|
97
|
+
if (foundFeature.children) {
|
|
98
|
+
for (const [, childFeature] of foundFeature.children) {
|
|
99
|
+
if (childFeature.min === oldStart) {
|
|
100
|
+
logger.debug?.(
|
|
101
|
+
`*** UPDATE CHILD FEATURE ID= ${featureId}, CHILD: ${JSON.stringify(
|
|
102
|
+
childFeature,
|
|
103
|
+
)}`,
|
|
104
|
+
)
|
|
105
|
+
featuresForChanges.push({
|
|
106
|
+
feature: childFeature,
|
|
107
|
+
topLevelFeature,
|
|
108
|
+
})
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
105
113
|
}
|
|
106
|
-
featuresForChanges.push({ feature: foundFeature, topLevelFeature })
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
// Let's update objects.
|
|
110
117
|
for (const [idx, change] of changes.entries()) {
|
|
111
118
|
const { newStart } = change
|
|
112
119
|
const { feature, topLevelFeature } = featuresForChanges[idx]
|
|
113
|
-
feature.
|
|
120
|
+
feature.min = newStart
|
|
114
121
|
if (topLevelFeature._id.equals(feature._id)) {
|
|
115
122
|
topLevelFeature.markModified('start') // Mark as modified. Without this save() -method is not updating data in database
|
|
116
123
|
} else {
|
|
@@ -144,7 +151,7 @@ export class LocationStartChange extends FeatureChange {
|
|
|
144
151
|
if (!feature) {
|
|
145
152
|
throw new Error(`Could not find feature with identifier "${changedId}"`)
|
|
146
153
|
}
|
|
147
|
-
feature.
|
|
154
|
+
feature.setMin(this.changes[idx].newStart)
|
|
148
155
|
}
|
|
149
156
|
}
|
|
150
157
|
|
package/src/Changes/index.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { AddAssemblyFromExternalChange } from './AddAssemblyFromExternalChange'
|
|
|
3
3
|
import { AddAssemblyFromFileChange } from './AddAssemblyFromFileChange'
|
|
4
4
|
import { AddFeatureChange } from './AddFeatureChange'
|
|
5
5
|
import { AddFeaturesFromFileChange } from './AddFeaturesFromFileChange'
|
|
6
|
+
import { AddRefSeqAliasesChange } from './AddRefSeqAliasesChange'
|
|
6
7
|
import { DeleteAssemblyChange } from './DeleteAssemblyChange'
|
|
7
8
|
import { DeleteFeatureChange } from './DeleteFeatureChange'
|
|
8
9
|
import { DeleteUserChange } from './DeleteUserChange'
|
|
9
|
-
import { DiscontinuousLocationEndChange } from './DiscontinuousLocationEndChange'
|
|
10
|
-
import { DiscontinuousLocationStartChange } from './DiscontinuousLocationStartChange'
|
|
11
10
|
import { FeatureAttributeChange } from './FeatureAttributeChange'
|
|
11
|
+
import { ImportJBrowseConfigChange } from './ImportJBrowseConfigChange'
|
|
12
12
|
import { LocationEndChange } from './LocationEndChange'
|
|
13
13
|
import { LocationStartChange } from './LocationStartChange'
|
|
14
14
|
import { StrandChange } from './StrandChange'
|
|
@@ -24,14 +24,14 @@ export const changes = {
|
|
|
24
24
|
DeleteAssemblyChange,
|
|
25
25
|
DeleteFeatureChange,
|
|
26
26
|
DeleteUserChange,
|
|
27
|
-
DiscontinuousLocationEndChange,
|
|
28
|
-
DiscontinuousLocationStartChange,
|
|
29
27
|
FeatureAttributeChange,
|
|
28
|
+
ImportJBrowseConfigChange,
|
|
30
29
|
LocationEndChange,
|
|
31
30
|
LocationStartChange,
|
|
32
31
|
StrandChange,
|
|
33
32
|
TypeChange,
|
|
34
33
|
UserChange,
|
|
34
|
+
AddRefSeqAliasesChange,
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export * from './AddAssemblyAndFeaturesFromFileChange'
|
|
@@ -42,11 +42,11 @@ export * from './AddFeaturesFromFileChange'
|
|
|
42
42
|
export * from './DeleteAssemblyChange'
|
|
43
43
|
export * from './DeleteFeatureChange'
|
|
44
44
|
export * from './DeleteUserChange'
|
|
45
|
-
export * from './DiscontinuousLocationEndChange'
|
|
46
|
-
export * from './DiscontinuousLocationStartChange'
|
|
47
45
|
export * from './FeatureAttributeChange'
|
|
46
|
+
export * from './ImportJBrowseConfigChange'
|
|
48
47
|
export * from './LocationEndChange'
|
|
49
48
|
export * from './LocationStartChange'
|
|
50
49
|
export * from './StrandChange'
|
|
51
50
|
export * from './TypeChange'
|
|
52
51
|
export * from './UserChange'
|
|
52
|
+
export * from './AddRefSeqAliasesChange'
|