@apollo-annotation/shared 0.3.12 → 1.0.0
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,19 +1,11 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
2
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
-
|
|
4
2
|
import {
|
|
5
3
|
type ChangeOptions,
|
|
6
|
-
type ClientDataStore,
|
|
7
4
|
FeatureChange,
|
|
8
|
-
type LocalGFF3DataStore,
|
|
9
5
|
type SerializedFeatureChange,
|
|
10
|
-
type ServerDataStore,
|
|
11
6
|
} from '@apollo-annotation/common'
|
|
12
7
|
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
13
8
|
|
|
14
|
-
import { findAndDeleteChildFeature } from './DeleteFeatureChange.js'
|
|
15
|
-
import { UndoSplitExonChange } from './UndoSplitExonChange.js'
|
|
16
|
-
|
|
17
9
|
interface SerializedSplitExonChangeBase extends SerializedFeatureChange {
|
|
18
10
|
typeName: 'SplitExonChange'
|
|
19
11
|
}
|
|
@@ -39,6 +31,34 @@ interface SerializedSplitExonChangeMultiple
|
|
|
39
31
|
export type SerializedSplitExonChange =
|
|
40
32
|
| SerializedSplitExonChangeSingle
|
|
41
33
|
| SerializedSplitExonChangeMultiple
|
|
34
|
+
|
|
35
|
+
interface SerializedUndoSplitExonChangeBase extends SerializedFeatureChange {
|
|
36
|
+
typeName: 'UndoSplitExonChange'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UndoSplitExonChangeDetails {
|
|
40
|
+
exonToRestore: AnnotationFeatureSnapshot
|
|
41
|
+
parentFeatureId: string
|
|
42
|
+
idsToDelete: string[]
|
|
43
|
+
upstreamCut: number
|
|
44
|
+
downstreamCut: number
|
|
45
|
+
leftExonId: string
|
|
46
|
+
rightExonId: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface SerializedUndoSplitExonChangeSingle
|
|
50
|
+
extends SerializedUndoSplitExonChangeBase,
|
|
51
|
+
UndoSplitExonChangeDetails {}
|
|
52
|
+
|
|
53
|
+
interface SerializedUndoSplitExonChangeMultiple
|
|
54
|
+
extends SerializedUndoSplitExonChangeBase {
|
|
55
|
+
changes: UndoSplitExonChangeDetails[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type SerializedUndoSplitExonChange =
|
|
59
|
+
| SerializedUndoSplitExonChangeSingle
|
|
60
|
+
| SerializedUndoSplitExonChangeMultiple
|
|
61
|
+
|
|
42
62
|
export class SplitExonChange extends FeatureChange {
|
|
43
63
|
typeName = 'SplitExonChange' as const
|
|
44
64
|
changes: SplitExonChangeDetails[]
|
|
@@ -81,119 +101,6 @@ export class SplitExonChange extends FeatureChange {
|
|
|
81
101
|
return { typeName, changedIds, assembly, changes }
|
|
82
102
|
}
|
|
83
103
|
|
|
84
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
85
|
-
const { featureModel, session } = backend
|
|
86
|
-
const { changes, logger } = this
|
|
87
|
-
for (const change of changes) {
|
|
88
|
-
const {
|
|
89
|
-
exonToBeSplit,
|
|
90
|
-
parentFeatureId,
|
|
91
|
-
upstreamCut,
|
|
92
|
-
downstreamCut,
|
|
93
|
-
leftExonId,
|
|
94
|
-
rightExonId,
|
|
95
|
-
} = change
|
|
96
|
-
const topLevelFeature = await featureModel
|
|
97
|
-
.findOne({ allIds: exonToBeSplit._id })
|
|
98
|
-
.session(session)
|
|
99
|
-
.exec()
|
|
100
|
-
if (!topLevelFeature) {
|
|
101
|
-
const errMsg = `*** ERROR: The following featureId was not found in database ='${exonToBeSplit._id}'`
|
|
102
|
-
logger.error(errMsg)
|
|
103
|
-
throw new Error(errMsg)
|
|
104
|
-
}
|
|
105
|
-
const tx = this.getFeatureFromId(topLevelFeature, parentFeatureId)
|
|
106
|
-
if (!tx?.children) {
|
|
107
|
-
throw new Error(
|
|
108
|
-
'ERROR: There should be at least one child (i.e. the exon to be split)',
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const [leftExon, rightExon] = this.makeSplitExons(
|
|
113
|
-
exonToBeSplit,
|
|
114
|
-
upstreamCut,
|
|
115
|
-
downstreamCut,
|
|
116
|
-
leftExonId,
|
|
117
|
-
rightExonId,
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
tx.children.set(leftExon._id, {
|
|
121
|
-
allIds: [],
|
|
122
|
-
...leftExon,
|
|
123
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
124
|
-
// @ts-expect-error
|
|
125
|
-
_id: leftExon._id,
|
|
126
|
-
})
|
|
127
|
-
tx.children.set(rightExon._id, {
|
|
128
|
-
allIds: [],
|
|
129
|
-
...rightExon,
|
|
130
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
131
|
-
// @ts-expect-error
|
|
132
|
-
_id: rightExon._id,
|
|
133
|
-
})
|
|
134
|
-
// Child features should be sorted for click and drag of gene glyphs to work properly
|
|
135
|
-
tx.children = new Map(
|
|
136
|
-
[...tx.children.entries()].sort((a, b) => a[1].min - b[1].min),
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
const deletedIds = findAndDeleteChildFeature(
|
|
140
|
-
topLevelFeature,
|
|
141
|
-
exonToBeSplit._id,
|
|
142
|
-
this,
|
|
143
|
-
)
|
|
144
|
-
deletedIds.push(exonToBeSplit._id)
|
|
145
|
-
topLevelFeature.allIds = topLevelFeature.allIds.filter(
|
|
146
|
-
(id) => !deletedIds.includes(id),
|
|
147
|
-
)
|
|
148
|
-
topLevelFeature.allIds.push(leftExon._id, rightExon._id)
|
|
149
|
-
await topLevelFeature.save()
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
154
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
async executeOnClient(dataStore: ClientDataStore) {
|
|
158
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
159
|
-
if (!dataStore) {
|
|
160
|
-
throw new Error('No data store')
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
for (const [idx] of this.changedIds.entries()) {
|
|
164
|
-
const {
|
|
165
|
-
exonToBeSplit,
|
|
166
|
-
parentFeatureId,
|
|
167
|
-
upstreamCut,
|
|
168
|
-
downstreamCut,
|
|
169
|
-
leftExonId,
|
|
170
|
-
rightExonId,
|
|
171
|
-
} = this.changes[idx]
|
|
172
|
-
if (!parentFeatureId) {
|
|
173
|
-
throw new Error('TODO: Split exon without parent')
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const [leftExon, rightExon] = this.makeSplitExons(
|
|
177
|
-
exonToBeSplit,
|
|
178
|
-
upstreamCut,
|
|
179
|
-
downstreamCut,
|
|
180
|
-
leftExonId,
|
|
181
|
-
rightExonId,
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
const parentFeature = dataStore.getFeature(parentFeatureId)
|
|
185
|
-
if (!parentFeature) {
|
|
186
|
-
throw new Error(`Could not find parent feature "${parentFeatureId}"`)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
parentFeature.addChild(leftExon)
|
|
190
|
-
parentFeature.addChild(rightExon)
|
|
191
|
-
if (dataStore.getFeature(exonToBeSplit._id)) {
|
|
192
|
-
dataStore.deleteFeature(exonToBeSplit._id)
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
104
|
getInverse() {
|
|
198
105
|
const { assembly, changedIds, changes, logger } = this
|
|
199
106
|
const inverseChangedIds = [...changedIds].reverse()
|
|
@@ -224,7 +131,7 @@ export class SplitExonChange extends FeatureChange {
|
|
|
224
131
|
downstreamCut: number,
|
|
225
132
|
leftExonId: string,
|
|
226
133
|
rightExonId: string,
|
|
227
|
-
): AnnotationFeatureSnapshot
|
|
134
|
+
): [AnnotationFeatureSnapshot, AnnotationFeatureSnapshot] {
|
|
228
135
|
// eslint-disable-next-line unicorn/prefer-structured-clone
|
|
229
136
|
const exon = JSON.parse(JSON.stringify(exonToBeSplit))
|
|
230
137
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
@@ -247,3 +154,69 @@ export class SplitExonChange extends FeatureChange {
|
|
|
247
154
|
return [leftExon, rightExon]
|
|
248
155
|
}
|
|
249
156
|
}
|
|
157
|
+
|
|
158
|
+
export class UndoSplitExonChange extends FeatureChange {
|
|
159
|
+
typeName = 'UndoSplitExonChange' as const
|
|
160
|
+
changes: UndoSplitExonChangeDetails[]
|
|
161
|
+
|
|
162
|
+
constructor(json: SerializedUndoSplitExonChange, options?: ChangeOptions) {
|
|
163
|
+
super(json, options)
|
|
164
|
+
this.changes = 'changes' in json ? json.changes : [json]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
toJSON(): SerializedUndoSplitExonChange {
|
|
168
|
+
const { assembly, changedIds, changes, typeName } = this
|
|
169
|
+
if (changes.length === 1) {
|
|
170
|
+
const [
|
|
171
|
+
{
|
|
172
|
+
exonToRestore,
|
|
173
|
+
parentFeatureId,
|
|
174
|
+
idsToDelete,
|
|
175
|
+
upstreamCut,
|
|
176
|
+
downstreamCut,
|
|
177
|
+
leftExonId,
|
|
178
|
+
rightExonId,
|
|
179
|
+
},
|
|
180
|
+
] = changes
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
typeName,
|
|
184
|
+
changedIds,
|
|
185
|
+
assembly,
|
|
186
|
+
exonToRestore,
|
|
187
|
+
parentFeatureId,
|
|
188
|
+
idsToDelete,
|
|
189
|
+
upstreamCut,
|
|
190
|
+
downstreamCut,
|
|
191
|
+
leftExonId,
|
|
192
|
+
rightExonId,
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { typeName, changedIds, assembly, changes }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
getInverse() {
|
|
199
|
+
const { assembly, changedIds, changes, logger } = this
|
|
200
|
+
const inverseChangedIds = [...changedIds].reverse()
|
|
201
|
+
const inverseChanges = [...changes]
|
|
202
|
+
.reverse()
|
|
203
|
+
.map((undoSplitExonChange) => ({
|
|
204
|
+
parentFeatureId: undoSplitExonChange.parentFeatureId,
|
|
205
|
+
exonToBeSplit: undoSplitExonChange.exonToRestore,
|
|
206
|
+
upstreamCut: undoSplitExonChange.upstreamCut,
|
|
207
|
+
downstreamCut: undoSplitExonChange.downstreamCut,
|
|
208
|
+
leftExonId: undoSplitExonChange.leftExonId,
|
|
209
|
+
rightExonId: undoSplitExonChange.rightExonId,
|
|
210
|
+
}))
|
|
211
|
+
|
|
212
|
+
return new SplitExonChange(
|
|
213
|
+
{
|
|
214
|
+
changedIds: inverseChangedIds,
|
|
215
|
+
typeName: 'SplitExonChange',
|
|
216
|
+
changes: inverseChanges,
|
|
217
|
+
assembly,
|
|
218
|
+
},
|
|
219
|
+
{ logger },
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
2
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
4
1
|
import {
|
|
5
2
|
type ChangeOptions,
|
|
6
|
-
type ClientDataStore,
|
|
7
3
|
FeatureChange,
|
|
8
|
-
type LocalGFF3DataStore,
|
|
9
4
|
type SerializedFeatureChange,
|
|
10
|
-
type ServerDataStore,
|
|
11
5
|
} from '@apollo-annotation/common'
|
|
12
|
-
import type { Feature, FeatureDocument } from '@apollo-annotation/schemas'
|
|
13
6
|
|
|
14
7
|
interface SerializedStrandChangeBase extends SerializedFeatureChange {
|
|
15
8
|
typeName: 'StrandChange'
|
|
@@ -51,93 +44,6 @@ export class StrandChange extends FeatureChange {
|
|
|
51
44
|
return { typeName, changedIds, assembly, changes }
|
|
52
45
|
}
|
|
53
46
|
|
|
54
|
-
/**
|
|
55
|
-
* Applies the required change to database
|
|
56
|
-
* @param backend - parameters from backend
|
|
57
|
-
* @returns
|
|
58
|
-
*/
|
|
59
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
60
|
-
const { featureModel, session } = backend
|
|
61
|
-
const { changes, logger } = this
|
|
62
|
-
const featuresForChanges: {
|
|
63
|
-
feature: Feature
|
|
64
|
-
topLevelFeature: FeatureDocument
|
|
65
|
-
}[] = []
|
|
66
|
-
// Let's first check that all features are found and those old values match with expected ones. We do this just to be sure that all changes can be done.
|
|
67
|
-
for (const entry of changes) {
|
|
68
|
-
const { featureId, oldStrand } = entry
|
|
69
|
-
|
|
70
|
-
// Search correct feature
|
|
71
|
-
const topLevelFeature = await featureModel
|
|
72
|
-
.findOne({ allIds: featureId })
|
|
73
|
-
.session(session)
|
|
74
|
-
.exec()
|
|
75
|
-
|
|
76
|
-
if (!topLevelFeature) {
|
|
77
|
-
const errMsg = `*** ERROR: The following featureId was not found in database ='${featureId}'`
|
|
78
|
-
logger.error(errMsg)
|
|
79
|
-
throw new Error(errMsg)
|
|
80
|
-
// throw new NotFoundException(errMsg) -- This is causing runtime error because Exception comes from @nestjs/common!!!
|
|
81
|
-
}
|
|
82
|
-
logger.debug?.(`*** Feature found: ${JSON.stringify(topLevelFeature)}`)
|
|
83
|
-
|
|
84
|
-
const foundFeature = this.getFeatureFromId(topLevelFeature, featureId)
|
|
85
|
-
if (!foundFeature) {
|
|
86
|
-
const errMsg = 'ERROR when searching feature by featureId'
|
|
87
|
-
logger.error(errMsg)
|
|
88
|
-
throw new Error(errMsg)
|
|
89
|
-
}
|
|
90
|
-
logger.debug?.(`*** Found feature: ${JSON.stringify(foundFeature)}`)
|
|
91
|
-
if (foundFeature.strand !== oldStrand) {
|
|
92
|
-
const errMsg = `*** ERROR: Feature's current strand "${topLevelFeature.strand}" doesn't match with expected value "${oldStrand}"`
|
|
93
|
-
logger.error(errMsg)
|
|
94
|
-
throw new Error(errMsg)
|
|
95
|
-
}
|
|
96
|
-
featuresForChanges.push({ feature: foundFeature, topLevelFeature })
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Let's update objects.
|
|
100
|
-
for (const [idx, change] of changes.entries()) {
|
|
101
|
-
const { newStrand } = change
|
|
102
|
-
const { feature, topLevelFeature } = featuresForChanges[idx]
|
|
103
|
-
feature.strand = newStrand
|
|
104
|
-
if (topLevelFeature._id.equals(feature._id)) {
|
|
105
|
-
topLevelFeature.markModified('strand') // Mark as modified. Without this save() -method is not updating data in database
|
|
106
|
-
} else {
|
|
107
|
-
topLevelFeature.markModified('children') // Mark as modified. Without this save() -method is not updating data in database
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
await topLevelFeature.save()
|
|
112
|
-
} catch (error) {
|
|
113
|
-
logger.debug?.(`*** FAILED: ${error}`)
|
|
114
|
-
throw error
|
|
115
|
-
}
|
|
116
|
-
logger.debug?.(
|
|
117
|
-
`*** Object updated in Mongo. New object: ${JSON.stringify(
|
|
118
|
-
topLevelFeature,
|
|
119
|
-
)}`,
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
125
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async executeOnClient(dataStore: ClientDataStore) {
|
|
129
|
-
if (!dataStore) {
|
|
130
|
-
throw new Error('No data store')
|
|
131
|
-
}
|
|
132
|
-
for (const [idx, changedId] of this.changedIds.entries()) {
|
|
133
|
-
const feature = dataStore.getFeature(changedId)
|
|
134
|
-
if (!feature) {
|
|
135
|
-
throw new Error(`Could not find feature with identifier "${changedId}"`)
|
|
136
|
-
}
|
|
137
|
-
feature.setStrand(this.changes[idx].newStrand)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
47
|
getInverse() {
|
|
142
48
|
const { assembly, changedIds, changes, logger, typeName } = this
|
|
143
49
|
const inverseChangedIds = [...changedIds].reverse()
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
2
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
4
1
|
import {
|
|
5
2
|
type ChangeOptions,
|
|
6
|
-
type ClientDataStore,
|
|
7
3
|
FeatureChange,
|
|
8
|
-
type LocalGFF3DataStore,
|
|
9
4
|
type SerializedFeatureChange,
|
|
10
|
-
type ServerDataStore,
|
|
11
5
|
} from '@apollo-annotation/common'
|
|
12
|
-
import type { Feature, FeatureDocument } from '@apollo-annotation/schemas'
|
|
13
6
|
|
|
14
7
|
interface SerializedTypeChangeBase extends SerializedFeatureChange {
|
|
15
8
|
typeName: 'TypeChange'
|
|
@@ -51,93 +44,6 @@ export class TypeChange extends FeatureChange {
|
|
|
51
44
|
return { typeName, changedIds, assembly, changes }
|
|
52
45
|
}
|
|
53
46
|
|
|
54
|
-
/**
|
|
55
|
-
* Applies the required change to database
|
|
56
|
-
* @param backend - parameters from backend
|
|
57
|
-
* @returns
|
|
58
|
-
*/
|
|
59
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
60
|
-
const { featureModel, session } = backend
|
|
61
|
-
const { changes, logger } = this
|
|
62
|
-
const featuresForChanges: {
|
|
63
|
-
feature: Feature
|
|
64
|
-
topLevelFeature: FeatureDocument
|
|
65
|
-
}[] = []
|
|
66
|
-
// Let's first check that all features are found and those old values match with expected ones. We do this just to be sure that all changes can be done.
|
|
67
|
-
for (const entry of changes) {
|
|
68
|
-
const { featureId, oldType } = entry
|
|
69
|
-
|
|
70
|
-
// Search correct feature
|
|
71
|
-
const topLevelFeature = await featureModel
|
|
72
|
-
.findOne({ allIds: featureId })
|
|
73
|
-
.session(session)
|
|
74
|
-
.exec()
|
|
75
|
-
|
|
76
|
-
if (!topLevelFeature) {
|
|
77
|
-
const errMsg = `*** ERROR: The following featureId was not found in database ='${featureId}'`
|
|
78
|
-
logger.error(errMsg)
|
|
79
|
-
throw new Error(errMsg)
|
|
80
|
-
// throw new NotFoundException(errMsg) -- This is causing runtime error because Exception comes from @nestjs/common!!!
|
|
81
|
-
}
|
|
82
|
-
logger.debug?.(`*** Feature found: ${JSON.stringify(topLevelFeature)}`)
|
|
83
|
-
|
|
84
|
-
const foundFeature = this.getFeatureFromId(topLevelFeature, featureId)
|
|
85
|
-
if (!foundFeature) {
|
|
86
|
-
const errMsg = 'ERROR when searching feature by featureId'
|
|
87
|
-
logger.error(errMsg)
|
|
88
|
-
throw new Error(errMsg)
|
|
89
|
-
}
|
|
90
|
-
logger.debug?.(`*** Found feature: ${JSON.stringify(foundFeature)}`)
|
|
91
|
-
if (foundFeature.type !== oldType) {
|
|
92
|
-
const errMsg = `*** ERROR: Feature's current type "${topLevelFeature.type}" doesn't match with expected value "${oldType}"`
|
|
93
|
-
logger.error(errMsg)
|
|
94
|
-
throw new Error(errMsg)
|
|
95
|
-
}
|
|
96
|
-
featuresForChanges.push({ feature: foundFeature, topLevelFeature })
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Let's update objects.
|
|
100
|
-
for (const [idx, change] of changes.entries()) {
|
|
101
|
-
const { newType } = change
|
|
102
|
-
const { feature, topLevelFeature } = featuresForChanges[idx]
|
|
103
|
-
feature.type = newType
|
|
104
|
-
if (topLevelFeature._id.equals(feature._id)) {
|
|
105
|
-
topLevelFeature.markModified('type') // Mark as modified. Without this save() -method is not updating data in database
|
|
106
|
-
} else {
|
|
107
|
-
topLevelFeature.markModified('children') // Mark as modified. Without this save() -method is not updating data in database
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
await topLevelFeature.save()
|
|
112
|
-
} catch (error) {
|
|
113
|
-
logger.debug?.(`*** FAILED: ${error}`)
|
|
114
|
-
throw error
|
|
115
|
-
}
|
|
116
|
-
logger.debug?.(
|
|
117
|
-
`*** Object updated in Mongo. New object: ${JSON.stringify(
|
|
118
|
-
topLevelFeature,
|
|
119
|
-
)}`,
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
125
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async executeOnClient(dataStore: ClientDataStore) {
|
|
129
|
-
if (!dataStore) {
|
|
130
|
-
throw new Error('No data store')
|
|
131
|
-
}
|
|
132
|
-
for (const [idx, changedId] of this.changedIds.entries()) {
|
|
133
|
-
const feature = dataStore.getFeature(changedId)
|
|
134
|
-
if (!feature) {
|
|
135
|
-
throw new Error(`Could not find feature with identifier "${changedId}"`)
|
|
136
|
-
}
|
|
137
|
-
feature.setType(this.changes[idx].newType)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
47
|
getInverse() {
|
|
142
48
|
const { assembly, changedIds, changes, logger, typeName } = this
|
|
143
49
|
const inverseChangedIds = [...changedIds].reverse()
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
2
1
|
import {
|
|
3
2
|
Change,
|
|
4
3
|
type ChangeOptions,
|
|
5
|
-
type ClientDataStore,
|
|
6
|
-
type LocalGFF3DataStore,
|
|
7
4
|
type SerializedChange,
|
|
8
|
-
type ServerDataStore,
|
|
9
5
|
} from '@apollo-annotation/common'
|
|
10
6
|
|
|
11
7
|
export interface SerializedUserChangeBase extends SerializedChange {
|
|
@@ -49,32 +45,6 @@ export class UserChange extends Change {
|
|
|
49
45
|
return { typeName, userId, changes }
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
async executeOnServer(backend: ServerDataStore) {
|
|
53
|
-
const { session, userModel } = backend
|
|
54
|
-
const { changes, logger, userId } = this
|
|
55
|
-
|
|
56
|
-
for (const change of changes) {
|
|
57
|
-
logger.debug?.(`change: ${JSON.stringify(changes)}`)
|
|
58
|
-
const { role } = change
|
|
59
|
-
const user = await userModel
|
|
60
|
-
.findByIdAndUpdate(userId, { role })
|
|
61
|
-
.session(session)
|
|
62
|
-
.exec()
|
|
63
|
-
if (!user) {
|
|
64
|
-
const errMsg = `*** ERROR: User with id "${userId}" not found`
|
|
65
|
-
logger.error(errMsg)
|
|
66
|
-
throw new Error(errMsg)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async executeOnLocalGFF3(_backend: LocalGFF3DataStore) {
|
|
72
|
-
throw new Error('executeOnLocalGFF3 not implemented')
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
76
|
-
async executeOnClient(_dataStore: ClientDataStore) {}
|
|
77
|
-
|
|
78
48
|
getInverse() {
|
|
79
49
|
const { changes, logger, typeName, userId } = this
|
|
80
50
|
return new UserChange({ typeName, changes, userId }, { logger })
|
package/src/Changes/index.ts
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AddFeatureChange,
|
|
3
|
+
DeleteFeatureChange,
|
|
4
|
+
} from './AddAndDeleteFeatureChanges.js'
|
|
1
5
|
import { AddAssemblyAliasesChange } from './AddAssemblyAliasesChange.js'
|
|
2
6
|
import { AddAssemblyAndFeaturesFromFileChange } from './AddAssemblyAndFeaturesFromFileChange.js'
|
|
3
7
|
import { AddAssemblyFromExternalChange } from './AddAssemblyFromExternalChange.js'
|
|
4
8
|
import { AddAssemblyFromFileChange } from './AddAssemblyFromFileChange.js'
|
|
5
|
-
import { AddFeatureChange } from './AddFeatureChange.js'
|
|
6
9
|
import { AddFeaturesFromFileChange } from './AddFeaturesFromFileChange.js'
|
|
7
10
|
import { AddRefSeqAliasesChange } from './AddRefSeqAliasesChange.js'
|
|
8
11
|
import { DeleteAssemblyChange } from './DeleteAssemblyChange.js'
|
|
9
|
-
import { DeleteFeatureChange } from './DeleteFeatureChange.js'
|
|
10
12
|
import { DeleteUserChange } from './DeleteUserChange.js'
|
|
11
13
|
import { FeatureAttributeChange } from './FeatureAttributeChange.js'
|
|
12
14
|
import { ImportJBrowseConfigChange } from './ImportJBrowseConfigChange.js'
|
|
13
15
|
import { LocationEndChange } from './LocationEndChange.js'
|
|
14
16
|
import { LocationStartChange } from './LocationStartChange.js'
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
import {
|
|
18
|
+
MergeExonsChange,
|
|
19
|
+
UndoMergeExonsChange,
|
|
20
|
+
} from './MergeAndUndoMergeExonsChanges.js'
|
|
21
|
+
import {
|
|
22
|
+
MergeTranscriptsChange,
|
|
23
|
+
UndoMergeTranscriptsChange,
|
|
24
|
+
} from './MergeAndUndoMergeTranscriptsChanges.js'
|
|
25
|
+
import {
|
|
26
|
+
SplitExonChange,
|
|
27
|
+
UndoSplitExonChange,
|
|
28
|
+
} from './SplitAndUndoSplitExonChanges.js'
|
|
18
29
|
import { StrandChange } from './StrandChange.js'
|
|
19
30
|
import { TypeChange } from './TypeChange.js'
|
|
20
|
-
import { UndoMergeExonsChange } from './UndoMergeExonsChange.js'
|
|
21
|
-
import { UndoMergeTranscriptsChange } from './UndoMergeTranscriptsChange.js'
|
|
22
|
-
import { UndoSplitExonChange } from './UndoSplitExonChange.js'
|
|
23
31
|
import { UserChange } from './UserChange.js'
|
|
24
32
|
|
|
25
|
-
export const
|
|
26
|
-
AddAssemblyAndFeaturesFromFileChange,
|
|
27
|
-
AddAssemblyFromFileChange,
|
|
28
|
-
AddAssemblyFromExternalChange,
|
|
33
|
+
export const localChanges = {
|
|
29
34
|
AddFeatureChange,
|
|
30
|
-
AddFeaturesFromFileChange,
|
|
31
|
-
DeleteAssemblyChange,
|
|
32
35
|
DeleteFeatureChange,
|
|
33
|
-
DeleteUserChange,
|
|
34
36
|
FeatureAttributeChange,
|
|
35
|
-
ImportJBrowseConfigChange,
|
|
36
37
|
LocationEndChange,
|
|
37
38
|
LocationStartChange,
|
|
38
39
|
MergeExonsChange,
|
|
@@ -43,6 +44,17 @@ export const changes = {
|
|
|
43
44
|
UndoMergeTranscriptsChange,
|
|
44
45
|
StrandChange,
|
|
45
46
|
TypeChange,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const changes = {
|
|
50
|
+
...localChanges,
|
|
51
|
+
AddAssemblyAndFeaturesFromFileChange,
|
|
52
|
+
AddAssemblyFromFileChange,
|
|
53
|
+
AddAssemblyFromExternalChange,
|
|
54
|
+
AddFeaturesFromFileChange,
|
|
55
|
+
DeleteAssemblyChange,
|
|
56
|
+
DeleteUserChange,
|
|
57
|
+
ImportJBrowseConfigChange,
|
|
46
58
|
UserChange,
|
|
47
59
|
AddRefSeqAliasesChange,
|
|
48
60
|
AddAssemblyAliasesChange,
|
|
@@ -51,21 +63,17 @@ export const changes = {
|
|
|
51
63
|
export * from './AddAssemblyAndFeaturesFromFileChange.js'
|
|
52
64
|
export * from './AddAssemblyFromFileChange.js'
|
|
53
65
|
export * from './AddAssemblyFromExternalChange.js'
|
|
54
|
-
export * from './
|
|
66
|
+
export * from './AddAndDeleteFeatureChanges.js'
|
|
55
67
|
export * from './AddFeaturesFromFileChange.js'
|
|
56
68
|
export * from './DeleteAssemblyChange.js'
|
|
57
|
-
export * from './DeleteFeatureChange.js'
|
|
58
69
|
export * from './DeleteUserChange.js'
|
|
59
70
|
export * from './FeatureAttributeChange.js'
|
|
60
71
|
export * from './ImportJBrowseConfigChange.js'
|
|
61
72
|
export * from './LocationEndChange.js'
|
|
62
73
|
export * from './LocationStartChange.js'
|
|
63
|
-
export * from './
|
|
64
|
-
export * from './
|
|
65
|
-
export * from './
|
|
66
|
-
export * from './UndoMergeExonsChange.js'
|
|
67
|
-
export * from './UndoSplitExonChange.js'
|
|
68
|
-
export * from './UndoMergeTranscriptsChange.js'
|
|
74
|
+
export * from './MergeAndUndoMergeExonsChanges.js'
|
|
75
|
+
export * from './MergeAndUndoMergeTranscriptsChanges.js'
|
|
76
|
+
export * from './SplitAndUndoSplitExonChanges.js'
|
|
69
77
|
export * from './StrandChange.js'
|
|
70
78
|
export * from './TypeChange.js'
|
|
71
79
|
export * from './UserChange.js'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
2
2
|
/* eslint-disable @typescript-eslint/require-await */
|
|
3
|
-
import type { Change
|
|
3
|
+
import type { Change } from '@apollo-annotation/common'
|
|
4
4
|
import type { FeatureDocument } from '@apollo-annotation/schemas'
|
|
5
5
|
import type { ExecutionContext } from '@nestjs/common'
|
|
6
6
|
import type { Reflector } from '@nestjs/core'
|
|
@@ -29,10 +29,7 @@ export abstract class Validation {
|
|
|
29
29
|
return { validationName: this.name }
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async frontendPostValidate(
|
|
33
|
-
_change: Change,
|
|
34
|
-
_dataStore: ClientDataStore,
|
|
35
|
-
): Promise<ValidationResult> {
|
|
32
|
+
async frontendPostValidate(_change: Change): Promise<ValidationResult> {
|
|
36
33
|
return { validationName: this.name }
|
|
37
34
|
}
|
|
38
35
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Change
|
|
1
|
+
import type { Change } from '@apollo-annotation/common'
|
|
2
2
|
import type { FeatureDocument } from '@apollo-annotation/schemas'
|
|
3
3
|
import type { ClientSession, Model } from 'mongoose'
|
|
4
4
|
|
|
@@ -41,13 +41,10 @@ export class ValidationSet {
|
|
|
41
41
|
return results
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
async frontendPostValidate(
|
|
45
|
-
change: Change,
|
|
46
|
-
dataStore: ClientDataStore,
|
|
47
|
-
): Promise<ValidationResultSet> {
|
|
44
|
+
async frontendPostValidate(change: Change): Promise<ValidationResultSet> {
|
|
48
45
|
const results = new ValidationResultSet()
|
|
49
46
|
for (const v of this.validations) {
|
|
50
|
-
const result = await v.frontendPostValidate(change
|
|
47
|
+
const result = await v.frontendPostValidate(change)
|
|
51
48
|
results.add(result)
|
|
52
49
|
if (result.error) {
|
|
53
50
|
break
|