@apollo-annotation/shared 0.3.6 → 0.3.8

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.
Files changed (94) hide show
  1. package/dist/Changes/AddAssemblyAliasesChange.d.ts +16 -0
  2. package/dist/Changes/AddAssemblyAliasesChange.js +50 -0
  3. package/dist/Changes/AddAssemblyAliasesChange.js.map +1 -0
  4. package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js +1 -1
  5. package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js.map +1 -1
  6. package/dist/Changes/AddAssemblyFromFileChange.js +1 -1
  7. package/dist/Changes/AddAssemblyFromFileChange.js.map +1 -1
  8. package/dist/Changes/AddFeatureChange.d.ts +1 -0
  9. package/dist/Changes/AddFeatureChange.js +5 -25
  10. package/dist/Changes/AddFeatureChange.js.map +1 -1
  11. package/dist/Changes/AddRefSeqAliasesChange.js +2 -4
  12. package/dist/Changes/AddRefSeqAliasesChange.js.map +1 -1
  13. package/dist/Changes/DeleteFeatureChange.d.ts +9 -8
  14. package/dist/Changes/DeleteFeatureChange.js +37 -32
  15. package/dist/Changes/DeleteFeatureChange.js.map +1 -1
  16. package/dist/Changes/FeatureAttributeChange.d.ts +2 -1
  17. package/dist/Changes/FeatureAttributeChange.js +14 -6
  18. package/dist/Changes/FeatureAttributeChange.js.map +1 -1
  19. package/dist/Changes/ImportJBrowseConfigChange.d.ts +3 -0
  20. package/dist/Changes/ImportJBrowseConfigChange.js +17 -13
  21. package/dist/Changes/ImportJBrowseConfigChange.js.map +1 -1
  22. package/dist/Changes/LocationEndChange.js +40 -37
  23. package/dist/Changes/LocationEndChange.js.map +1 -1
  24. package/dist/Changes/LocationStartChange.js +40 -37
  25. package/dist/Changes/LocationStartChange.js.map +1 -1
  26. package/dist/Changes/MergeExonsChange.d.ts +29 -0
  27. package/dist/Changes/MergeExonsChange.js +114 -0
  28. package/dist/Changes/MergeExonsChange.js.map +1 -0
  29. package/dist/Changes/MergeTranscriptsChange.d.ts +34 -0
  30. package/dist/Changes/MergeTranscriptsChange.js +245 -0
  31. package/dist/Changes/MergeTranscriptsChange.js.map +1 -0
  32. package/dist/Changes/SplitExonChange.d.ts +33 -0
  33. package/dist/Changes/SplitExonChange.js +142 -0
  34. package/dist/Changes/SplitExonChange.js.map +1 -0
  35. package/dist/Changes/UndoMergeExonsChange.d.ts +27 -0
  36. package/dist/Changes/UndoMergeExonsChange.js +104 -0
  37. package/dist/Changes/UndoMergeExonsChange.js.map +1 -0
  38. package/dist/Changes/UndoMergeTranscriptsChange.d.ts +27 -0
  39. package/dist/Changes/UndoMergeTranscriptsChange.js +104 -0
  40. package/dist/Changes/UndoMergeTranscriptsChange.js.map +1 -0
  41. package/dist/Changes/UndoSplitExonChange.d.ts +32 -0
  42. package/dist/Changes/UndoSplitExonChange.js +111 -0
  43. package/dist/Changes/UndoSplitExonChange.js.map +1 -0
  44. package/dist/Changes/index.d.ts +21 -0
  45. package/dist/Changes/index.js +21 -0
  46. package/dist/Changes/index.js.map +1 -1
  47. package/dist/Checks/CDSCheck.d.ts +1 -1
  48. package/dist/Checks/CDSCheck.js +8 -9
  49. package/dist/Checks/CDSCheck.js.map +1 -1
  50. package/dist/Checks/TranscriptCheck.d.ts +9 -0
  51. package/dist/Checks/TranscriptCheck.js +109 -0
  52. package/dist/Checks/TranscriptCheck.js.map +1 -0
  53. package/dist/Checks/index.d.ts +1 -0
  54. package/dist/Checks/index.js +1 -0
  55. package/dist/Checks/index.js.map +1 -1
  56. package/dist/GFF3/annotationFeatureToGFF3.js +7 -1
  57. package/dist/GFF3/annotationFeatureToGFF3.js.map +1 -1
  58. package/dist/GFF3/gff3ToAnnotationFeature.test.js +1 -1
  59. package/dist/GFF3/gff3ToAnnotationFeature.test.js.map +1 -1
  60. package/dist/Validations/ParentChildValidation.js +3 -1
  61. package/dist/Validations/ParentChildValidation.js.map +1 -1
  62. package/dist/tsconfig.tsbuildinfo +1 -1
  63. package/dist/util.d.ts +5 -0
  64. package/dist/util.js +46 -0
  65. package/dist/util.js.map +1 -1
  66. package/package.json +7 -7
  67. package/src/Changes/AddAssemblyAliasesChange.ts +69 -0
  68. package/src/Changes/AddAssemblyAndFeaturesFromFileChange.ts +2 -1
  69. package/src/Changes/AddAssemblyFromFileChange.ts +1 -1
  70. package/src/Changes/AddFeatureChange.ts +5 -29
  71. package/src/Changes/AddRefSeqAliasesChange.ts +2 -4
  72. package/src/Changes/DeleteFeatureChange.ts +42 -36
  73. package/src/Changes/FeatureAttributeChange.ts +16 -7
  74. package/src/Changes/ImportJBrowseConfigChange.ts +33 -18
  75. package/src/Changes/LocationEndChange.ts +41 -50
  76. package/src/Changes/LocationStartChange.ts +41 -50
  77. package/src/Changes/MergeExonsChange.ts +201 -0
  78. package/src/Changes/MergeTranscriptsChange.ts +394 -0
  79. package/src/Changes/SplitExonChange.ts +249 -0
  80. package/src/Changes/UndoMergeExonsChange.ts +149 -0
  81. package/src/Changes/UndoMergeTranscriptsChange.ts +153 -0
  82. package/src/Changes/UndoSplitExonChange.ts +174 -0
  83. package/src/Changes/index.ts +21 -0
  84. package/src/Checks/CDSCheck.ts +10 -10
  85. package/src/Checks/TranscriptCheck.ts +139 -0
  86. package/src/Checks/index.ts +1 -0
  87. package/src/GFF3/annotationFeatureToGFF3.ts +7 -1
  88. package/src/GFF3/gff3ToAnnotationFeature.test.ts +1 -1
  89. package/src/Validations/ParentChildValidation.ts +3 -2
  90. package/src/util.ts +53 -0
  91. package/test_data/example01.json +20 -20
  92. package/test_data/example02.json +38 -38
  93. package/test_data/example04.json +57 -57
  94. package/test_data/gene_representations.gff3 +1054 -276
@@ -0,0 +1,149 @@
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'
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
+ }
@@ -0,0 +1,153 @@
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'
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
+ }
@@ -0,0 +1,174 @@
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'
14
+ import { SplitExonChange } from './SplitExonChange'
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
+ }
@@ -1,3 +1,4 @@
1
+ import { AddAssemblyAliasesChange } from './AddAssemblyAliasesChange'
1
2
  import { AddAssemblyAndFeaturesFromFileChange } from './AddAssemblyAndFeaturesFromFileChange'
2
3
  import { AddAssemblyFromExternalChange } from './AddAssemblyFromExternalChange'
3
4
  import { AddAssemblyFromFileChange } from './AddAssemblyFromFileChange'
@@ -11,8 +12,14 @@ import { FeatureAttributeChange } from './FeatureAttributeChange'
11
12
  import { ImportJBrowseConfigChange } from './ImportJBrowseConfigChange'
12
13
  import { LocationEndChange } from './LocationEndChange'
13
14
  import { LocationStartChange } from './LocationStartChange'
15
+ import { MergeExonsChange } from './MergeExonsChange'
16
+ import { MergeTranscriptsChange } from './MergeTranscriptsChange'
17
+ import { SplitExonChange } from './SplitExonChange'
14
18
  import { StrandChange } from './StrandChange'
15
19
  import { TypeChange } from './TypeChange'
20
+ import { UndoMergeExonsChange } from './UndoMergeExonsChange'
21
+ import { UndoMergeTranscriptsChange } from './UndoMergeTranscriptsChange'
22
+ import { UndoSplitExonChange } from './UndoSplitExonChange'
16
23
  import { UserChange } from './UserChange'
17
24
 
18
25
  export const changes = {
@@ -28,10 +35,17 @@ export const changes = {
28
35
  ImportJBrowseConfigChange,
29
36
  LocationEndChange,
30
37
  LocationStartChange,
38
+ MergeExonsChange,
39
+ SplitExonChange,
40
+ MergeTranscriptsChange,
41
+ UndoMergeExonsChange,
42
+ UndoSplitExonChange,
43
+ UndoMergeTranscriptsChange,
31
44
  StrandChange,
32
45
  TypeChange,
33
46
  UserChange,
34
47
  AddRefSeqAliasesChange,
48
+ AddAssemblyAliasesChange,
35
49
  }
36
50
 
37
51
  export * from './AddAssemblyAndFeaturesFromFileChange'
@@ -46,7 +60,14 @@ export * from './FeatureAttributeChange'
46
60
  export * from './ImportJBrowseConfigChange'
47
61
  export * from './LocationEndChange'
48
62
  export * from './LocationStartChange'
63
+ export * from './MergeExonsChange'
64
+ export * from './SplitExonChange'
65
+ export * from './MergeTranscriptsChange'
66
+ export * from './UndoMergeExonsChange'
67
+ export * from './UndoSplitExonChange'
68
+ export * from './UndoMergeTranscriptsChange'
49
69
  export * from './StrandChange'
50
70
  export * from './TypeChange'
51
71
  export * from './UserChange'
52
72
  export * from './AddRefSeqAliasesChange'
73
+ export * from './AddAssemblyAliasesChange'
@@ -22,7 +22,6 @@ enum CAUSES {
22
22
  'InternalStopCodon',
23
23
  'MissingStartCodon',
24
24
  'MissingStopCodon',
25
- 'MultipleOfThree',
26
25
  }
27
26
 
28
27
  const iupacComplements: Record<string, string | undefined> = {
@@ -156,6 +155,10 @@ async function checkMRNA(
156
155
  for (const cdsLocation of cdsLocations) {
157
156
  const sequence = await getCDSSequence(cdsLocation, strand, getSequence)
158
157
  const codons = splitSequenceInCodons(sequence)
158
+ const cdsEnd =
159
+ strand === -1
160
+ ? cdsLocation.at(0)?.min ?? min
161
+ : cdsLocation.at(-1)?.max ?? max
159
162
  if (sequence.length % 3 === 0) {
160
163
  const start_codon = codons.at(0)
161
164
  if (start_codon && !(start_codon.toUpperCase() in START_CODONS)) {
@@ -175,12 +178,9 @@ async function checkMRNA(
175
178
  message: `Unexpected start codon in feature "${_id}": ${start_codon}`,
176
179
  })
177
180
  }
181
+
178
182
  const lastCodon = codons.at(-1) // Last codon is supposed to be a stop
179
183
  if (lastCodon && !(lastCodon.toUpperCase() in STOP_CODONS)) {
180
- const cdsEnd =
181
- strand === -1
182
- ? cdsLocation.at(0)?.min ?? min
183
- : cdsLocation.at(-1)?.max ?? max
184
184
  checkResults.push({
185
185
  _id: new ObjectID().toHexString(),
186
186
  name: CHECK_NAME,
@@ -196,12 +196,12 @@ async function checkMRNA(
196
196
  checkResults.push({
197
197
  _id: new ObjectID().toHexString(),
198
198
  name: CHECK_NAME,
199
- cause: CAUSES[CAUSES.MultipleOfThree],
199
+ cause: CAUSES[CAUSES.MissingStopCodon],
200
200
  ids,
201
201
  refSeq: refSeq.toString(),
202
- start: min,
203
- end: max,
204
- message: `The coding sequence for feature "${_id}" is not a multiple of three`,
202
+ start: cdsEnd,
203
+ end: cdsEnd,
204
+ message: `Missing stop codon: The coding sequence for feature "${_id}" is not a multiple of three`,
205
205
  })
206
206
  }
207
207
  for (const [idx, codon] of codons.entries()) {
@@ -285,7 +285,7 @@ export class CDSCheck extends Check {
285
285
  name = CHECK_NAME
286
286
  causes = getCauses()
287
287
  version = 1
288
- default = true
288
+ isDefault = true
289
289
 
290
290
  async checkFeature(
291
291
  feature: AnnotationFeatureSnapshot,