@apollo-annotation/shared 0.3.13 → 1.0.1
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/{DeleteFeatureChange.d.ts → AddAndDeleteFeatureChanges.d.ts} +26 -11
- package/dist/Changes/AddAndDeleteFeatureChanges.d.ts.map +1 -0
- package/dist/Changes/AddAndDeleteFeatureChanges.js +117 -0
- package/dist/Changes/AddAndDeleteFeatureChanges.js.map +1 -0
- package/dist/Changes/AddAssemblyAliasesChange.d.ts +1 -4
- package/dist/Changes/AddAssemblyAliasesChange.d.ts.map +1 -1
- package/dist/Changes/AddAssemblyAliasesChange.js +0 -27
- package/dist/Changes/AddAssemblyAliasesChange.js.map +1 -1
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.d.ts +2 -11
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.d.ts.map +1 -1
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js +2 -82
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js.map +1 -1
- package/dist/Changes/AddAssemblyFromExternalChange.d.ts +1 -9
- package/dist/Changes/AddAssemblyFromExternalChange.d.ts.map +1 -1
- package/dist/Changes/AddAssemblyFromExternalChange.js +0 -72
- package/dist/Changes/AddAssemblyFromExternalChange.js.map +1 -1
- package/dist/Changes/AddAssemblyFromFileChange.d.ts +2 -17
- package/dist/Changes/AddAssemblyFromFileChange.d.ts.map +1 -1
- package/dist/Changes/AddAssemblyFromFileChange.js +2 -119
- package/dist/Changes/AddAssemblyFromFileChange.js.map +1 -1
- package/dist/Changes/AddFeaturesFromFileChange.d.ts +2 -11
- package/dist/Changes/AddFeaturesFromFileChange.d.ts.map +1 -1
- package/dist/Changes/AddFeaturesFromFileChange.js +2 -66
- package/dist/Changes/AddFeaturesFromFileChange.js.map +1 -1
- package/dist/Changes/AddRefSeqAliasesChange.d.ts +1 -4
- package/dist/Changes/AddRefSeqAliasesChange.d.ts.map +1 -1
- package/dist/Changes/AddRefSeqAliasesChange.js +0 -34
- package/dist/Changes/AddRefSeqAliasesChange.js.map +1 -1
- package/dist/Changes/DeleteAssemblyChange.d.ts +1 -9
- package/dist/Changes/DeleteAssemblyChange.d.ts.map +1 -1
- package/dist/Changes/DeleteAssemblyChange.js +0 -53
- package/dist/Changes/DeleteAssemblyChange.js.map +1 -1
- package/dist/Changes/DeleteUserChange.d.ts +1 -4
- package/dist/Changes/DeleteUserChange.d.ts.map +1 -1
- package/dist/Changes/DeleteUserChange.js +0 -19
- package/dist/Changes/DeleteUserChange.js.map +1 -1
- package/dist/Changes/FeatureAttributeChange.d.ts +1 -9
- package/dist/Changes/FeatureAttributeChange.d.ts.map +1 -1
- package/dist/Changes/FeatureAttributeChange.js +0 -82
- package/dist/Changes/FeatureAttributeChange.js.map +1 -1
- package/dist/Changes/ImportJBrowseConfigChange.d.ts +1 -4
- package/dist/Changes/ImportJBrowseConfigChange.d.ts.map +1 -1
- package/dist/Changes/ImportJBrowseConfigChange.js +1 -18
- package/dist/Changes/ImportJBrowseConfigChange.js.map +1 -1
- package/dist/Changes/LocationEndChange.d.ts +1 -9
- package/dist/Changes/LocationEndChange.d.ts.map +1 -1
- package/dist/Changes/LocationEndChange.js +0 -90
- package/dist/Changes/LocationEndChange.js.map +1 -1
- package/dist/Changes/LocationStartChange.d.ts +1 -9
- package/dist/Changes/LocationStartChange.d.ts.map +1 -1
- package/dist/Changes/LocationStartChange.js +0 -90
- package/dist/Changes/LocationStartChange.js.map +1 -1
- package/dist/Changes/MergeAndUndoMergeExonsChanges.d.ts +46 -0
- package/dist/Changes/MergeAndUndoMergeExonsChanges.d.ts.map +1 -0
- package/dist/Changes/MergeAndUndoMergeExonsChanges.js +83 -0
- package/dist/Changes/MergeAndUndoMergeExonsChanges.js.map +1 -0
- package/dist/Changes/{MergeTranscriptsChange.d.ts → MergeAndUndoMergeTranscriptsChanges.d.ts} +22 -6
- package/dist/Changes/MergeAndUndoMergeTranscriptsChanges.d.ts.map +1 -0
- package/dist/Changes/{MergeTranscriptsChange.js → MergeAndUndoMergeTranscriptsChanges.js} +40 -50
- package/dist/Changes/MergeAndUndoMergeTranscriptsChanges.js.map +1 -0
- package/dist/Changes/SplitAndUndoSplitExonChanges.d.ts +55 -0
- package/dist/Changes/SplitAndUndoSplitExonChanges.d.ts.map +1 -0
- package/dist/Changes/SplitAndUndoSplitExonChanges.js +115 -0
- package/dist/Changes/SplitAndUndoSplitExonChanges.js.map +1 -0
- package/dist/Changes/StrandChange.d.ts +1 -9
- package/dist/Changes/StrandChange.d.ts.map +1 -1
- package/dist/Changes/StrandChange.js +0 -77
- package/dist/Changes/StrandChange.js.map +1 -1
- package/dist/Changes/TypeChange.d.ts +1 -9
- package/dist/Changes/TypeChange.d.ts.map +1 -1
- package/dist/Changes/TypeChange.js +0 -77
- package/dist/Changes/TypeChange.js.map +1 -1
- package/dist/Changes/UserChange.d.ts +1 -4
- package/dist/Changes/UserChange.d.ts.map +1 -1
- package/dist/Changes/UserChange.js +0 -23
- package/dist/Changes/UserChange.js.map +1 -1
- package/dist/Changes/index.d.ts +29 -22
- package/dist/Changes/index.d.ts.map +1 -1
- package/dist/Changes/index.js +19 -24
- package/dist/Changes/index.js.map +1 -1
- package/dist/Validations/Validation.d.ts +2 -2
- package/dist/Validations/Validation.d.ts.map +1 -1
- package/dist/Validations/Validation.js +1 -1
- package/dist/Validations/Validation.js.map +1 -1
- package/dist/Validations/ValidationSet.d.ts +2 -2
- package/dist/Validations/ValidationSet.d.ts.map +1 -1
- package/dist/Validations/ValidationSet.js +2 -2
- package/dist/Validations/ValidationSet.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -4
- package/src/Changes/{DeleteFeatureChange.ts → AddAndDeleteFeatureChanges.ts} +77 -107
- package/src/Changes/AddAssemblyAliasesChange.ts +0 -35
- package/src/Changes/AddAssemblyAndFeaturesFromFileChange.ts +5 -108
- package/src/Changes/AddAssemblyFromExternalChange.ts +0 -87
- package/src/Changes/AddAssemblyFromFileChange.ts +5 -169
- package/src/Changes/AddFeaturesFromFileChange.ts +5 -86
- package/src/Changes/AddRefSeqAliasesChange.ts +0 -44
- package/src/Changes/DeleteAssemblyChange.ts +0 -72
- package/src/Changes/DeleteUserChange.ts +0 -25
- package/src/Changes/FeatureAttributeChange.ts +0 -104
- package/src/Changes/ImportJBrowseConfigChange.ts +1 -27
- package/src/Changes/LocationEndChange.ts +0 -100
- package/src/Changes/LocationStartChange.ts +0 -100
- package/src/Changes/{MergeExonsChange.ts → MergeAndUndoMergeExonsChanges.ts} +70 -90
- package/src/Changes/{MergeTranscriptsChange.ts → MergeAndUndoMergeTranscriptsChanges.ts} +74 -66
- package/src/Changes/{SplitExonChange.ts → SplitAndUndoSplitExonChanges.ts} +95 -122
- package/src/Changes/StrandChange.ts +0 -94
- package/src/Changes/TypeChange.ts +0 -94
- package/src/Changes/UserChange.ts +0 -30
- package/src/Changes/index.ts +32 -24
- package/src/Validations/Validation.ts +2 -5
- package/src/Validations/ValidationSet.ts +3 -6
- package/src/index.ts +0 -1
- package/dist/Changes/AddFeatureChange.d.ts +0 -37
- package/dist/Changes/AddFeatureChange.d.ts.map +0 -1
- package/dist/Changes/AddFeatureChange.js +0 -169
- package/dist/Changes/AddFeatureChange.js.map +0 -1
- package/dist/Changes/DeleteFeatureChange.d.ts.map +0 -1
- package/dist/Changes/DeleteFeatureChange.js +0 -161
- package/dist/Changes/DeleteFeatureChange.js.map +0 -1
- package/dist/Changes/FromFileBaseChange.d.ts +0 -12
- package/dist/Changes/FromFileBaseChange.d.ts.map +0 -1
- package/dist/Changes/FromFileBaseChange.js +0 -196
- package/dist/Changes/FromFileBaseChange.js.map +0 -1
- package/dist/Changes/MergeExonsChange.d.ts +0 -30
- package/dist/Changes/MergeExonsChange.d.ts.map +0 -1
- package/dist/Changes/MergeExonsChange.js +0 -110
- package/dist/Changes/MergeExonsChange.js.map +0 -1
- package/dist/Changes/MergeTranscriptsChange.d.ts.map +0 -1
- package/dist/Changes/MergeTranscriptsChange.js.map +0 -1
- package/dist/Changes/SplitExonChange.d.ts +0 -34
- package/dist/Changes/SplitExonChange.d.ts.map +0 -1
- package/dist/Changes/SplitExonChange.js +0 -138
- package/dist/Changes/SplitExonChange.js.map +0 -1
- package/dist/Changes/UndoMergeExonsChange.d.ts +0 -28
- package/dist/Changes/UndoMergeExonsChange.d.ts.map +0 -1
- package/dist/Changes/UndoMergeExonsChange.js +0 -100
- package/dist/Changes/UndoMergeExonsChange.js.map +0 -1
- package/dist/Changes/UndoMergeTranscriptsChange.d.ts +0 -28
- package/dist/Changes/UndoMergeTranscriptsChange.d.ts.map +0 -1
- package/dist/Changes/UndoMergeTranscriptsChange.js +0 -100
- package/dist/Changes/UndoMergeTranscriptsChange.js.map +0 -1
- package/dist/Changes/UndoSplitExonChange.d.ts +0 -33
- package/dist/Changes/UndoSplitExonChange.d.ts.map +0 -1
- package/dist/Changes/UndoSplitExonChange.js +0 -107
- package/dist/Changes/UndoSplitExonChange.js.map +0 -1
- package/dist/Operations/GetAssembliesOperation.d.ts +0 -12
- package/dist/Operations/GetAssembliesOperation.d.ts.map +0 -1
- package/dist/Operations/GetAssembliesOperation.js +0 -16
- package/dist/Operations/GetAssembliesOperation.js.map +0 -1
- package/dist/Operations/GetFeaturesOperation.d.ts +0 -27
- package/dist/Operations/GetFeaturesOperation.d.ts.map +0 -1
- package/dist/Operations/GetFeaturesOperation.js +0 -38
- package/dist/Operations/GetFeaturesOperation.js.map +0 -1
- package/dist/Operations/index.d.ts +0 -9
- package/dist/Operations/index.d.ts.map +0 -1
- package/dist/Operations/index.js +0 -6
- package/dist/Operations/index.js.map +0 -1
- package/src/Changes/AddFeatureChange.ts +0 -236
- package/src/Changes/FromFileBaseChange.ts +0 -231
- package/src/Changes/UndoMergeExonsChange.ts +0 -149
- package/src/Changes/UndoMergeTranscriptsChange.ts +0 -153
- package/src/Changes/UndoSplitExonChange.ts +0 -174
- package/src/Operations/GetAssembliesOperation.ts +0 -28
- package/src/Operations/GetFeaturesOperation.ts +0 -58
- package/src/Operations/index.ts +0 -6
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
3
|
-
import {
|
|
4
|
-
AssemblySpecificChange,
|
|
5
|
-
type ServerDataStore,
|
|
6
|
-
} from '@apollo-annotation/common'
|
|
7
|
-
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
8
|
-
import type { FileDocument, RefSeqDocument } from '@apollo-annotation/schemas'
|
|
9
|
-
import type { GFF3Feature } from '@gmod/gff'
|
|
10
|
-
|
|
11
|
-
import { gff3ToAnnotationFeature } from '../GFF3/index.js'
|
|
12
|
-
|
|
13
|
-
export abstract class FromFileBaseChange extends AssemblySpecificChange {
|
|
14
|
-
async addRefSeqIntoDb(
|
|
15
|
-
fileDoc: FileDocument,
|
|
16
|
-
assembly: string,
|
|
17
|
-
backend: ServerDataStore,
|
|
18
|
-
) {
|
|
19
|
-
const { logger } = this
|
|
20
|
-
const { filesService, refSeqChunkModel, refSeqModel, user } = backend
|
|
21
|
-
const { CHUNK_SIZE } = process.env
|
|
22
|
-
const customChunkSize = CHUNK_SIZE && Number(CHUNK_SIZE)
|
|
23
|
-
let chunkIndex = 0
|
|
24
|
-
let refSeqLen = 0
|
|
25
|
-
let refSeqDoc: RefSeqDocument | undefined
|
|
26
|
-
let fastaInfoStarted = fileDoc.type !== 'text/x-gff3'
|
|
27
|
-
|
|
28
|
-
// Read data from compressed file and parse the content
|
|
29
|
-
const sequenceStream = filesService.getFileStream(fileDoc)
|
|
30
|
-
let sequenceBuffer = ''
|
|
31
|
-
let incompleteLine = ''
|
|
32
|
-
let lastLineIsIncomplete = true
|
|
33
|
-
let parsingStarted = false
|
|
34
|
-
logger.debug?.('starting sequence stream')
|
|
35
|
-
let lineCount = 0
|
|
36
|
-
const decoder = new TextDecoder()
|
|
37
|
-
for await (const data of sequenceStream) {
|
|
38
|
-
const chunk = decoder.decode(data)
|
|
39
|
-
lastLineIsIncomplete = !chunk.endsWith('\n')
|
|
40
|
-
// chunk is small enough that you can split the whole thing into lines without having to make it into smaller chunks first.
|
|
41
|
-
const lines = chunk.split(/\r?\n/)
|
|
42
|
-
if (incompleteLine) {
|
|
43
|
-
lines[0] = `${incompleteLine}${lines[0]}`
|
|
44
|
-
incompleteLine = ''
|
|
45
|
-
}
|
|
46
|
-
if (lastLineIsIncomplete) {
|
|
47
|
-
incompleteLine = lines.pop() ?? ''
|
|
48
|
-
}
|
|
49
|
-
for (const line of lines) {
|
|
50
|
-
lineCount++
|
|
51
|
-
if (lineCount % 1_000_000 === 0) {
|
|
52
|
-
logger.debug?.(`Processed ${lineCount} lines`)
|
|
53
|
-
}
|
|
54
|
-
// In case of GFF3 file we start to read sequence after '##FASTA' is found
|
|
55
|
-
if (!fastaInfoStarted) {
|
|
56
|
-
if (line.trim() === '##FASTA') {
|
|
57
|
-
fastaInfoStarted = true
|
|
58
|
-
}
|
|
59
|
-
continue
|
|
60
|
-
}
|
|
61
|
-
const refSeqInfoLine = /^>\s*(\S+)\s*(.*)/.exec(line)
|
|
62
|
-
// Add new ref sequence info if we are reference seq info line
|
|
63
|
-
if (refSeqInfoLine) {
|
|
64
|
-
parsingStarted = true
|
|
65
|
-
logger.debug?.(
|
|
66
|
-
`Reference sequence information line "${refSeqInfoLine[0]}"`,
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
// If there is sequence from previous reference sequence then we need to add it to previous ref seq
|
|
70
|
-
if (sequenceBuffer !== '') {
|
|
71
|
-
if (!refSeqDoc) {
|
|
72
|
-
throw new Error('No refSeq document found')
|
|
73
|
-
}
|
|
74
|
-
refSeqLen += sequenceBuffer.length
|
|
75
|
-
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
76
|
-
await refSeqChunkModel.create([
|
|
77
|
-
{
|
|
78
|
-
refSeq: refSeqDoc._id,
|
|
79
|
-
n: chunkIndex,
|
|
80
|
-
sequence: sequenceBuffer,
|
|
81
|
-
user,
|
|
82
|
-
status: -1,
|
|
83
|
-
},
|
|
84
|
-
])
|
|
85
|
-
sequenceBuffer = ''
|
|
86
|
-
}
|
|
87
|
-
await refSeqDoc?.updateOne({ length: refSeqLen })
|
|
88
|
-
// await refSeqDoc?.updateOne({ length: refSeqLen }, { session })
|
|
89
|
-
refSeqLen = 0
|
|
90
|
-
chunkIndex = 0
|
|
91
|
-
|
|
92
|
-
const name = refSeqInfoLine[1].trim()
|
|
93
|
-
const description = refSeqInfoLine[2] ? refSeqInfoLine[2].trim() : ''
|
|
94
|
-
|
|
95
|
-
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
96
|
-
const [newRefSeqDoc] = await refSeqModel.create([
|
|
97
|
-
{
|
|
98
|
-
name,
|
|
99
|
-
description,
|
|
100
|
-
assembly,
|
|
101
|
-
length: 0,
|
|
102
|
-
...(customChunkSize ? { chunkSize: customChunkSize } : null),
|
|
103
|
-
user,
|
|
104
|
-
status: -1,
|
|
105
|
-
},
|
|
106
|
-
])
|
|
107
|
-
logger.debug?.(
|
|
108
|
-
`Added new refSeq "${name}", desc "${description}", docId "${newRefSeqDoc._id}"`,
|
|
109
|
-
)
|
|
110
|
-
refSeqDoc = newRefSeqDoc
|
|
111
|
-
} else if (/\S/.test(line)) {
|
|
112
|
-
if (!refSeqDoc) {
|
|
113
|
-
throw new Error('No refSeq document found')
|
|
114
|
-
}
|
|
115
|
-
const { _id, chunkSize } = refSeqDoc
|
|
116
|
-
sequenceBuffer += line.replaceAll(/\s/g, '')
|
|
117
|
-
// If sequence block > chunk size then save chunk into Mongo
|
|
118
|
-
while (sequenceBuffer.length >= chunkSize) {
|
|
119
|
-
const sequence = sequenceBuffer.slice(0, chunkSize)
|
|
120
|
-
refSeqLen += sequence.length
|
|
121
|
-
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
122
|
-
await refSeqChunkModel.create([
|
|
123
|
-
{ refSeq: _id, n: chunkIndex, sequence, user, status: -1 },
|
|
124
|
-
])
|
|
125
|
-
chunkIndex++
|
|
126
|
-
// Set remaining sequence
|
|
127
|
-
sequenceBuffer = sequenceBuffer.slice(chunkSize)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (!parsingStarted) {
|
|
133
|
-
throw new Error('No reference sequences found in file')
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (sequenceBuffer || lastLineIsIncomplete) {
|
|
137
|
-
if (!refSeqDoc) {
|
|
138
|
-
throw new Error('No refSeq document found')
|
|
139
|
-
}
|
|
140
|
-
// If the file did not end with line break so the last line is incomplete
|
|
141
|
-
if (lastLineIsIncomplete) {
|
|
142
|
-
sequenceBuffer += incompleteLine
|
|
143
|
-
}
|
|
144
|
-
refSeqLen += sequenceBuffer.length
|
|
145
|
-
logger.verbose?.(
|
|
146
|
-
`*** Add the very last chunk to ref seq ("${refSeqDoc._id}", index ${chunkIndex} and total length for ref seq is ${refSeqLen}): "${sequenceBuffer}"`,
|
|
147
|
-
)
|
|
148
|
-
logger.debug?.(
|
|
149
|
-
`Creating refSeq chunk number ${chunkIndex} of "${refSeqDoc._id}"`,
|
|
150
|
-
)
|
|
151
|
-
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
152
|
-
await refSeqChunkModel.create([
|
|
153
|
-
{
|
|
154
|
-
refSeq: refSeqDoc._id,
|
|
155
|
-
n: chunkIndex,
|
|
156
|
-
sequence: sequenceBuffer,
|
|
157
|
-
user,
|
|
158
|
-
status: -1,
|
|
159
|
-
},
|
|
160
|
-
])
|
|
161
|
-
await refSeqDoc.updateOne({ length: refSeqLen })
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
private refSeqCache = new Map<string, RefSeqDocument>()
|
|
166
|
-
|
|
167
|
-
async removeExistingFeatures(backend: ServerDataStore) {
|
|
168
|
-
const { featureModel, refSeqModel } = backend
|
|
169
|
-
const { assembly, logger } = this
|
|
170
|
-
logger.debug?.(`Removing existing features for assembly = ${assembly}`)
|
|
171
|
-
|
|
172
|
-
const refSeqs: RefSeqDocument[] = await refSeqModel
|
|
173
|
-
.find({ assembly })
|
|
174
|
-
.exec()
|
|
175
|
-
|
|
176
|
-
for (const refSeq of refSeqs) {
|
|
177
|
-
await featureModel.deleteMany({ refSeq: refSeq._id })
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async addFeatureIntoDb(gff3Feature: GFF3Feature, backend: ServerDataStore) {
|
|
182
|
-
const { INDEXED_IDS } = process.env
|
|
183
|
-
let idsToIndex: string[] | undefined
|
|
184
|
-
if (INDEXED_IDS) {
|
|
185
|
-
idsToIndex = INDEXED_IDS.split(',')
|
|
186
|
-
}
|
|
187
|
-
const { assembly, refSeqCache } = this
|
|
188
|
-
const { featureModel, refSeqModel, user } = backend
|
|
189
|
-
|
|
190
|
-
const [{ seq_id: refName }] = gff3Feature
|
|
191
|
-
if (!refName) {
|
|
192
|
-
throw new Error(
|
|
193
|
-
`Valid seq_id not found in feature ${JSON.stringify(gff3Feature)}`,
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
let refSeqDoc = refSeqCache.get(refName)
|
|
197
|
-
if (!refSeqDoc) {
|
|
198
|
-
refSeqDoc =
|
|
199
|
-
(await refSeqModel.findOne({ assembly, name: refName }).exec()) ??
|
|
200
|
-
undefined
|
|
201
|
-
if (refSeqDoc) {
|
|
202
|
-
refSeqCache.set(refName, refSeqDoc)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (!refSeqDoc) {
|
|
206
|
-
throw new Error(
|
|
207
|
-
`RefSeq was not found by assembly "${assembly}" and seq_id "${refName}" not found`,
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
const newFeature = gff3ToAnnotationFeature(gff3Feature, refSeqDoc._id)
|
|
211
|
-
const allIds = this.getAllIds(newFeature)
|
|
212
|
-
const indexedIds = this.getIndexedIds(newFeature, idsToIndex)
|
|
213
|
-
|
|
214
|
-
// Add into Mongo
|
|
215
|
-
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
|
|
216
|
-
await featureModel.create([
|
|
217
|
-
{ allIds, indexedIds, ...newFeature, user, status: -1 },
|
|
218
|
-
])
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
getAllIds(feature: AnnotationFeatureSnapshot): string[] {
|
|
222
|
-
const allIds = [feature._id]
|
|
223
|
-
if (feature.children) {
|
|
224
|
-
for (const child of Object.values(feature.children)) {
|
|
225
|
-
const childIds = this.getAllIds(child)
|
|
226
|
-
allIds.push(...childIds)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return allIds
|
|
230
|
-
}
|
|
231
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
type ChangeOptions,
|
|
5
|
-
type ClientDataStore,
|
|
6
|
-
FeatureChange,
|
|
7
|
-
type LocalGFF3DataStore,
|
|
8
|
-
type SerializedFeatureChange,
|
|
9
|
-
type ServerDataStore,
|
|
10
|
-
} from '@apollo-annotation/common'
|
|
11
|
-
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
12
|
-
|
|
13
|
-
import { MergeExonsChange } from './MergeExonsChange.js'
|
|
14
|
-
|
|
15
|
-
interface SerializedUndoMergeExonsChangeBase extends SerializedFeatureChange {
|
|
16
|
-
typeName: 'UndoMergeExonsChange'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface UndoMergeExonsChangeDetails {
|
|
20
|
-
exonsToRestore: AnnotationFeatureSnapshot[]
|
|
21
|
-
parentFeatureId: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface SerializedUndoMergeExonsChangeSingle
|
|
25
|
-
extends SerializedUndoMergeExonsChangeBase,
|
|
26
|
-
UndoMergeExonsChangeDetails {}
|
|
27
|
-
|
|
28
|
-
interface SerializedUndoMergeExonsChangeMultiple
|
|
29
|
-
extends SerializedUndoMergeExonsChangeBase {
|
|
30
|
-
changes: UndoMergeExonsChangeDetails[]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type SerializedUndoMergeExonsChange =
|
|
34
|
-
| SerializedUndoMergeExonsChangeSingle
|
|
35
|
-
| SerializedUndoMergeExonsChangeMultiple
|
|
36
|
-
export class UndoMergeExonsChange extends FeatureChange {
|
|
37
|
-
typeName = 'UndoMergeExonsChange' as const
|
|
38
|
-
changes: UndoMergeExonsChangeDetails[]
|
|
39
|
-
|
|
40
|
-
constructor(json: SerializedUndoMergeExonsChange, options?: ChangeOptions) {
|
|
41
|
-
super(json, options)
|
|
42
|
-
this.changes = 'changes' in json ? json.changes : [json]
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
toJSON(): SerializedUndoMergeExonsChange {
|
|
46
|
-
const { assembly, changedIds, changes, typeName } = this
|
|
47
|
-
if (changes.length === 1) {
|
|
48
|
-
const [{ exonsToRestore, parentFeatureId }] = changes
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
typeName,
|
|
52
|
-
changedIds,
|
|
53
|
-
assembly,
|
|
54
|
-
exonsToRestore,
|
|
55
|
-
parentFeatureId,
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return { typeName, changedIds, assembly, changes }
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
62
|
-
const { featureModel, session } = backend
|
|
63
|
-
const { changes } = this
|
|
64
|
-
for (const change of changes) {
|
|
65
|
-
const { exonsToRestore, parentFeatureId } = change
|
|
66
|
-
if (exonsToRestore.length !== 2) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Expected exactly two exons to restore. Got :${exonsToRestore.length}`,
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
const topLevelFeature = await featureModel
|
|
72
|
-
.findOne({ allIds: parentFeatureId })
|
|
73
|
-
.session(session)
|
|
74
|
-
.exec()
|
|
75
|
-
if (!topLevelFeature) {
|
|
76
|
-
throw new Error(`Could not find feature with ID "${parentFeatureId}"`)
|
|
77
|
-
}
|
|
78
|
-
const parentFeature = this.getFeatureFromId(
|
|
79
|
-
topLevelFeature,
|
|
80
|
-
parentFeatureId,
|
|
81
|
-
)
|
|
82
|
-
if (!parentFeature) {
|
|
83
|
-
throw new Error(
|
|
84
|
-
`Could not find feature with ID "${parentFeatureId}" in feature "${topLevelFeature._id.toString()}"`,
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
if (!parentFeature.children) {
|
|
88
|
-
parentFeature.children = new Map()
|
|
89
|
-
}
|
|
90
|
-
for (const exon of exonsToRestore) {
|
|
91
|
-
this.addChild(parentFeature, exon)
|
|
92
|
-
const childIds = this.getChildFeatureIds(exon)
|
|
93
|
-
topLevelFeature.allIds.push(exon._id, ...childIds)
|
|
94
|
-
}
|
|
95
|
-
await topLevelFeature.save()
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
100
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async executeOnClient(dataStore: ClientDataStore) {
|
|
104
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
105
|
-
if (!dataStore) {
|
|
106
|
-
throw new Error('No data store')
|
|
107
|
-
}
|
|
108
|
-
const { changes } = this
|
|
109
|
-
for (const change of changes) {
|
|
110
|
-
const { exonsToRestore, parentFeatureId } = change
|
|
111
|
-
if (!parentFeatureId) {
|
|
112
|
-
throw new Error('Parent ID is missing')
|
|
113
|
-
}
|
|
114
|
-
const parentFeature = dataStore.getFeature(parentFeatureId)
|
|
115
|
-
if (!parentFeature) {
|
|
116
|
-
throw new Error(`Could not find parent feature "${parentFeatureId}"`)
|
|
117
|
-
}
|
|
118
|
-
// create an ID for the parent feature if it does not have one
|
|
119
|
-
if (!parentFeature.attributes.get('_id')) {
|
|
120
|
-
parentFeature.setAttribute('_id', [parentFeature._id])
|
|
121
|
-
}
|
|
122
|
-
for (const exon of exonsToRestore) {
|
|
123
|
-
parentFeature.addChild(exon)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
getInverse() {
|
|
129
|
-
const { assembly, changedIds, changes, logger } = this
|
|
130
|
-
const inverseChangedIds = [...changedIds].reverse()
|
|
131
|
-
const inverseChanges = [...changes]
|
|
132
|
-
.reverse()
|
|
133
|
-
.map((undoMergeExonsChange) => ({
|
|
134
|
-
firstExon: undoMergeExonsChange.exonsToRestore[0],
|
|
135
|
-
secondExon: undoMergeExonsChange.exonsToRestore[1],
|
|
136
|
-
parentFeatureId: undoMergeExonsChange.parentFeatureId,
|
|
137
|
-
}))
|
|
138
|
-
|
|
139
|
-
return new MergeExonsChange(
|
|
140
|
-
{
|
|
141
|
-
changedIds: inverseChangedIds,
|
|
142
|
-
typeName: 'MergeExonsChange',
|
|
143
|
-
changes: inverseChanges,
|
|
144
|
-
assembly,
|
|
145
|
-
},
|
|
146
|
-
{ logger },
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
type ChangeOptions,
|
|
5
|
-
type ClientDataStore,
|
|
6
|
-
FeatureChange,
|
|
7
|
-
type LocalGFF3DataStore,
|
|
8
|
-
type SerializedFeatureChange,
|
|
9
|
-
type ServerDataStore,
|
|
10
|
-
} from '@apollo-annotation/common'
|
|
11
|
-
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
12
|
-
|
|
13
|
-
import { MergeTranscriptsChange } from './MergeTranscriptsChange.js'
|
|
14
|
-
|
|
15
|
-
interface SerializedUndoMergeTranscriptsChangeBase
|
|
16
|
-
extends SerializedFeatureChange {
|
|
17
|
-
typeName: 'UndoMergeTranscriptsChange'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface UndoMergeTranscriptsChangeDetails {
|
|
21
|
-
transcriptsToRestore: AnnotationFeatureSnapshot[]
|
|
22
|
-
parentFeatureId: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface SerializedUndoMergeTranscriptsChangeSingle
|
|
26
|
-
extends SerializedUndoMergeTranscriptsChangeBase,
|
|
27
|
-
UndoMergeTranscriptsChangeDetails {}
|
|
28
|
-
|
|
29
|
-
interface SerializedUndoMergeTranscriptsChangeMultiple
|
|
30
|
-
extends SerializedUndoMergeTranscriptsChangeBase {
|
|
31
|
-
changes: UndoMergeTranscriptsChangeDetails[]
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type SerializedUndoMergeTranscriptsChange =
|
|
35
|
-
| SerializedUndoMergeTranscriptsChangeSingle
|
|
36
|
-
| SerializedUndoMergeTranscriptsChangeMultiple
|
|
37
|
-
export class UndoMergeTranscriptsChange extends FeatureChange {
|
|
38
|
-
typeName = 'UndoMergeTranscriptsChange' as const
|
|
39
|
-
changes: UndoMergeTranscriptsChangeDetails[]
|
|
40
|
-
|
|
41
|
-
constructor(
|
|
42
|
-
json: SerializedUndoMergeTranscriptsChange,
|
|
43
|
-
options?: ChangeOptions,
|
|
44
|
-
) {
|
|
45
|
-
super(json, options)
|
|
46
|
-
this.changes = 'changes' in json ? json.changes : [json]
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
toJSON(): SerializedUndoMergeTranscriptsChange {
|
|
50
|
-
const { assembly, changedIds, changes, typeName } = this
|
|
51
|
-
if (changes.length === 1) {
|
|
52
|
-
const [{ transcriptsToRestore, parentFeatureId }] = changes
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
typeName,
|
|
56
|
-
changedIds,
|
|
57
|
-
assembly,
|
|
58
|
-
transcriptsToRestore,
|
|
59
|
-
parentFeatureId,
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return { typeName, changedIds, assembly, changes }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
66
|
-
const { featureModel, session } = backend
|
|
67
|
-
const { changes } = this
|
|
68
|
-
for (const change of changes) {
|
|
69
|
-
const { transcriptsToRestore, parentFeatureId } = change
|
|
70
|
-
if (transcriptsToRestore.length !== 2) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
`Expected exactly two transcripts to restore. Got :${transcriptsToRestore.length}`,
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
const topLevelFeature = await featureModel
|
|
76
|
-
.findOne({ allIds: parentFeatureId })
|
|
77
|
-
.session(session)
|
|
78
|
-
.exec()
|
|
79
|
-
if (!topLevelFeature) {
|
|
80
|
-
throw new Error(`Could not find feature with ID "${parentFeatureId}"`)
|
|
81
|
-
}
|
|
82
|
-
const parentFeature = this.getFeatureFromId(
|
|
83
|
-
topLevelFeature,
|
|
84
|
-
parentFeatureId,
|
|
85
|
-
)
|
|
86
|
-
if (!parentFeature) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
`Could not find feature with ID "${parentFeatureId}" in feature "${topLevelFeature._id.toString()}"`,
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
if (!parentFeature.children) {
|
|
92
|
-
parentFeature.children = new Map()
|
|
93
|
-
}
|
|
94
|
-
for (const transcript of transcriptsToRestore) {
|
|
95
|
-
this.addChild(parentFeature, transcript)
|
|
96
|
-
const childIds = this.getChildFeatureIds(transcript)
|
|
97
|
-
topLevelFeature.allIds.push(transcript._id, ...childIds)
|
|
98
|
-
}
|
|
99
|
-
await topLevelFeature.save()
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
104
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async executeOnClient(dataStore: ClientDataStore) {
|
|
108
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
109
|
-
if (!dataStore) {
|
|
110
|
-
throw new Error('No data store')
|
|
111
|
-
}
|
|
112
|
-
const { changes } = this
|
|
113
|
-
for (const change of changes) {
|
|
114
|
-
const { transcriptsToRestore, parentFeatureId } = change
|
|
115
|
-
if (!parentFeatureId) {
|
|
116
|
-
throw new Error('Parent ID is missing')
|
|
117
|
-
}
|
|
118
|
-
const parentFeature = dataStore.getFeature(parentFeatureId)
|
|
119
|
-
if (!parentFeature) {
|
|
120
|
-
throw new Error(`Could not find parent feature "${parentFeatureId}"`)
|
|
121
|
-
}
|
|
122
|
-
// create an ID for the parent feature if it does not have one
|
|
123
|
-
if (!parentFeature.attributes.get('_id')) {
|
|
124
|
-
parentFeature.setAttribute('_id', [parentFeature._id])
|
|
125
|
-
}
|
|
126
|
-
for (const transcript of transcriptsToRestore) {
|
|
127
|
-
parentFeature.addChild(transcript)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
getInverse() {
|
|
133
|
-
const { assembly, changedIds, changes, logger } = this
|
|
134
|
-
const inverseChangedIds = [...changedIds].reverse()
|
|
135
|
-
const inverseChanges = [...changes]
|
|
136
|
-
.reverse()
|
|
137
|
-
.map((undoMergeTranscriptsChange) => ({
|
|
138
|
-
firstTranscript: undoMergeTranscriptsChange.transcriptsToRestore[0],
|
|
139
|
-
secondTranscript: undoMergeTranscriptsChange.transcriptsToRestore[1],
|
|
140
|
-
parentFeatureId: undoMergeTranscriptsChange.parentFeatureId,
|
|
141
|
-
}))
|
|
142
|
-
|
|
143
|
-
return new MergeTranscriptsChange(
|
|
144
|
-
{
|
|
145
|
-
changedIds: inverseChangedIds,
|
|
146
|
-
typeName: 'MergeTranscriptsChange',
|
|
147
|
-
changes: inverseChanges,
|
|
148
|
-
assembly,
|
|
149
|
-
},
|
|
150
|
-
{ logger },
|
|
151
|
-
)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
type ChangeOptions,
|
|
5
|
-
type ClientDataStore,
|
|
6
|
-
FeatureChange,
|
|
7
|
-
type LocalGFF3DataStore,
|
|
8
|
-
type SerializedFeatureChange,
|
|
9
|
-
type ServerDataStore,
|
|
10
|
-
} from '@apollo-annotation/common'
|
|
11
|
-
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
12
|
-
|
|
13
|
-
import { findAndDeleteChildFeature } from './DeleteFeatureChange.js'
|
|
14
|
-
import { SplitExonChange } from './SplitExonChange.js'
|
|
15
|
-
|
|
16
|
-
interface SerializedUndoSplitExonChangeBase extends SerializedFeatureChange {
|
|
17
|
-
typeName: 'UndoSplitExonChange'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface UndoSplitExonChangeDetails {
|
|
21
|
-
exonToRestore: AnnotationFeatureSnapshot
|
|
22
|
-
parentFeatureId: string
|
|
23
|
-
idsToDelete: string[]
|
|
24
|
-
upstreamCut: number
|
|
25
|
-
downstreamCut: number
|
|
26
|
-
leftExonId: string
|
|
27
|
-
rightExonId: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface SerializedUndoSplitExonChangeSingle
|
|
31
|
-
extends SerializedUndoSplitExonChangeBase,
|
|
32
|
-
UndoSplitExonChangeDetails {}
|
|
33
|
-
|
|
34
|
-
interface SerializedUndoSplitExonChangeMultiple
|
|
35
|
-
extends SerializedUndoSplitExonChangeBase {
|
|
36
|
-
changes: UndoSplitExonChangeDetails[]
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type SerializedUndoSplitExonChange =
|
|
40
|
-
| SerializedUndoSplitExonChangeSingle
|
|
41
|
-
| SerializedUndoSplitExonChangeMultiple
|
|
42
|
-
export class UndoSplitExonChange extends FeatureChange {
|
|
43
|
-
typeName = 'UndoSplitExonChange' as const
|
|
44
|
-
changes: UndoSplitExonChangeDetails[]
|
|
45
|
-
|
|
46
|
-
constructor(json: SerializedUndoSplitExonChange, options?: ChangeOptions) {
|
|
47
|
-
super(json, options)
|
|
48
|
-
this.changes = 'changes' in json ? json.changes : [json]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
toJSON(): SerializedUndoSplitExonChange {
|
|
52
|
-
const { assembly, changedIds, changes, typeName } = this
|
|
53
|
-
if (changes.length === 1) {
|
|
54
|
-
const [
|
|
55
|
-
{
|
|
56
|
-
exonToRestore,
|
|
57
|
-
parentFeatureId,
|
|
58
|
-
idsToDelete,
|
|
59
|
-
upstreamCut,
|
|
60
|
-
downstreamCut,
|
|
61
|
-
leftExonId,
|
|
62
|
-
rightExonId,
|
|
63
|
-
},
|
|
64
|
-
] = changes
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
typeName,
|
|
68
|
-
changedIds,
|
|
69
|
-
assembly,
|
|
70
|
-
exonToRestore,
|
|
71
|
-
parentFeatureId,
|
|
72
|
-
idsToDelete,
|
|
73
|
-
upstreamCut,
|
|
74
|
-
downstreamCut,
|
|
75
|
-
leftExonId,
|
|
76
|
-
rightExonId,
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return { typeName, changedIds, assembly, changes }
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
83
|
-
const { featureModel, session } = backend
|
|
84
|
-
const { changes } = this
|
|
85
|
-
for (const change of changes) {
|
|
86
|
-
const { exonToRestore, parentFeatureId, idsToDelete } = change
|
|
87
|
-
const topLevelFeature = await featureModel
|
|
88
|
-
.findOne({ allIds: parentFeatureId })
|
|
89
|
-
.session(session)
|
|
90
|
-
.exec()
|
|
91
|
-
if (!topLevelFeature) {
|
|
92
|
-
throw new Error(`Could not find feature with ID "${parentFeatureId}"`)
|
|
93
|
-
}
|
|
94
|
-
const parentFeature = this.getFeatureFromId(
|
|
95
|
-
topLevelFeature,
|
|
96
|
-
parentFeatureId,
|
|
97
|
-
)
|
|
98
|
-
if (!parentFeature) {
|
|
99
|
-
throw new Error(
|
|
100
|
-
`Could not find feature with ID "${parentFeatureId}" in feature "${topLevelFeature._id.toString()}"`,
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
if (!parentFeature.children) {
|
|
104
|
-
parentFeature.children = new Map()
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
this.addChild(parentFeature, exonToRestore)
|
|
108
|
-
const childIds = this.getChildFeatureIds(exonToRestore)
|
|
109
|
-
topLevelFeature.allIds.push(exonToRestore._id, ...childIds)
|
|
110
|
-
topLevelFeature.allIds = topLevelFeature.allIds.filter(
|
|
111
|
-
(id) => !idsToDelete.includes(id),
|
|
112
|
-
)
|
|
113
|
-
idsToDelete.map((id) =>
|
|
114
|
-
findAndDeleteChildFeature(topLevelFeature, id, this),
|
|
115
|
-
)
|
|
116
|
-
await topLevelFeature.save()
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
121
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async executeOnClient(dataStore: ClientDataStore) {
|
|
125
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
126
|
-
if (!dataStore) {
|
|
127
|
-
throw new Error('No data store')
|
|
128
|
-
}
|
|
129
|
-
const { changes } = this
|
|
130
|
-
for (const change of changes) {
|
|
131
|
-
const { exonToRestore, parentFeatureId, idsToDelete } = change
|
|
132
|
-
if (!parentFeatureId) {
|
|
133
|
-
throw new Error('Parent ID is missing')
|
|
134
|
-
}
|
|
135
|
-
const parentFeature = dataStore.getFeature(parentFeatureId)
|
|
136
|
-
if (!parentFeature) {
|
|
137
|
-
throw new Error(`Could not find parent feature "${parentFeatureId}"`)
|
|
138
|
-
}
|
|
139
|
-
// create an ID for the parent feature if it does not have one
|
|
140
|
-
if (!parentFeature.attributes.get('_id')) {
|
|
141
|
-
parentFeature.setAttribute('_id', [parentFeature._id])
|
|
142
|
-
}
|
|
143
|
-
parentFeature.addChild(exonToRestore)
|
|
144
|
-
idsToDelete.map((id) => {
|
|
145
|
-
parentFeature.deleteChild(id)
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
getInverse() {
|
|
151
|
-
const { assembly, changedIds, changes, logger } = this
|
|
152
|
-
const inverseChangedIds = [...changedIds].reverse()
|
|
153
|
-
const inverseChanges = [...changes]
|
|
154
|
-
.reverse()
|
|
155
|
-
.map((undoSplitExonChange) => ({
|
|
156
|
-
parentFeatureId: undoSplitExonChange.parentFeatureId,
|
|
157
|
-
exonToBeSplit: undoSplitExonChange.exonToRestore,
|
|
158
|
-
upstreamCut: undoSplitExonChange.upstreamCut,
|
|
159
|
-
downstreamCut: undoSplitExonChange.downstreamCut,
|
|
160
|
-
leftExonId: undoSplitExonChange.leftExonId,
|
|
161
|
-
rightExonId: undoSplitExonChange.rightExonId,
|
|
162
|
-
}))
|
|
163
|
-
|
|
164
|
-
return new SplitExonChange(
|
|
165
|
-
{
|
|
166
|
-
changedIds: inverseChangedIds,
|
|
167
|
-
typeName: 'SplitExonChange',
|
|
168
|
-
changes: inverseChanges,
|
|
169
|
-
assembly,
|
|
170
|
-
},
|
|
171
|
-
{ logger },
|
|
172
|
-
)
|
|
173
|
-
}
|
|
174
|
-
}
|