@apollo-annotation/shared 0.1.11

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 (36) hide show
  1. package/README.md +1 -0
  2. package/package.json +49 -0
  3. package/src/Changes/AddAssemblyAndFeaturesFromFileChange.ts +135 -0
  4. package/src/Changes/AddAssemblyFromExternalChange.ts +145 -0
  5. package/src/Changes/AddAssemblyFromFileChange.ts +125 -0
  6. package/src/Changes/AddFeatureChange.ts +233 -0
  7. package/src/Changes/AddFeaturesFromFileChange.ts +120 -0
  8. package/src/Changes/DeleteAssemblyChange.ts +100 -0
  9. package/src/Changes/DeleteFeatureChange.ts +200 -0
  10. package/src/Changes/DeleteUserChange.ts +83 -0
  11. package/src/Changes/DiscontinuousLocationEndChange.ts +182 -0
  12. package/src/Changes/DiscontinuousLocationStartChange.ts +182 -0
  13. package/src/Changes/FeatureAttributeChange.ts +164 -0
  14. package/src/Changes/LocationEndChange.ts +175 -0
  15. package/src/Changes/LocationStartChange.ts +175 -0
  16. package/src/Changes/StrandChange.ts +159 -0
  17. package/src/Changes/TypeChange.ts +159 -0
  18. package/src/Changes/UserChange.ts +82 -0
  19. package/src/Changes/index.ts +52 -0
  20. package/src/Checks/CDSCheck.ts +275 -0
  21. package/src/Checks/index.ts +1 -0
  22. package/src/Common/index.ts +1 -0
  23. package/src/Common/jwtPayload.ts +25 -0
  24. package/src/Messages.ts +32 -0
  25. package/src/Operations/GetAssembliesOperation.ts +28 -0
  26. package/src/Operations/GetFeaturesOperation.ts +58 -0
  27. package/src/Operations/index.ts +6 -0
  28. package/src/Validations/CoreValidation.ts +37 -0
  29. package/src/Validations/ParentChildValidation.ts +88 -0
  30. package/src/Validations/Validation.ts +55 -0
  31. package/src/Validations/ValidationSet.ts +106 -0
  32. package/src/Validations/index.ts +4 -0
  33. package/src/Validations/soSequenceTypes.ts +1865 -0
  34. package/src/index.ts +7 -0
  35. package/src/util.ts +109 -0
  36. package/tsconfig.json +19 -0
@@ -0,0 +1,159 @@
1
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */
2
+ /* eslint-disable @typescript-eslint/require-await */
3
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
4
+ import {
5
+ ChangeOptions,
6
+ ClientDataStore,
7
+ FeatureChange,
8
+ LocalGFF3DataStore,
9
+ SerializedFeatureChange,
10
+ ServerDataStore,
11
+ } from '@apollo-annotation/common'
12
+ import { Feature, FeatureDocument } from '@apollo-annotation/schemas'
13
+
14
+ interface SerializedStrandChangeBase extends SerializedFeatureChange {
15
+ typeName: 'StrandChange'
16
+ }
17
+
18
+ interface StrandChangeDetails {
19
+ featureId: string
20
+ oldStrand: -1 | 1 | undefined
21
+ newStrand: -1 | 1 | undefined
22
+ }
23
+
24
+ interface SerializedStrandChangeSingle
25
+ extends SerializedStrandChangeBase,
26
+ StrandChangeDetails {}
27
+
28
+ interface SerializedStrandChangeMultiple extends SerializedStrandChangeBase {
29
+ changes: StrandChangeDetails[]
30
+ }
31
+
32
+ type SerializedStrandChange =
33
+ | SerializedStrandChangeSingle
34
+ | SerializedStrandChangeMultiple
35
+
36
+ export class StrandChange extends FeatureChange {
37
+ typeName = 'StrandChange' as const
38
+ changes: StrandChangeDetails[]
39
+
40
+ constructor(json: SerializedStrandChange, options?: ChangeOptions) {
41
+ super(json, options)
42
+ this.changes = 'changes' in json ? json.changes : [json]
43
+ }
44
+
45
+ toJSON(): SerializedStrandChange {
46
+ const { assembly, changedIds, changes, typeName } = this
47
+ if (changes.length === 1) {
48
+ const [{ featureId, newStrand, oldStrand }] = changes
49
+ return { typeName, changedIds, assembly, featureId, oldStrand, newStrand }
50
+ }
51
+ return { typeName, changedIds, assembly, changes }
52
+ }
53
+
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
+ getInverse() {
142
+ const { assembly, changedIds, changes, logger, typeName } = this
143
+ const inverseChangedIds = [...changedIds].reverse()
144
+ const inverseChanges = [...changes].reverse().map((endChange) => ({
145
+ featureId: endChange.featureId,
146
+ oldStrand: endChange.newStrand,
147
+ newStrand: endChange.oldStrand,
148
+ }))
149
+ return new StrandChange(
150
+ {
151
+ changedIds: inverseChangedIds,
152
+ typeName,
153
+ changes: inverseChanges,
154
+ assembly,
155
+ },
156
+ { logger },
157
+ )
158
+ }
159
+ }
@@ -0,0 +1,159 @@
1
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */
2
+ /* eslint-disable @typescript-eslint/require-await */
3
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
4
+ import {
5
+ ChangeOptions,
6
+ ClientDataStore,
7
+ FeatureChange,
8
+ LocalGFF3DataStore,
9
+ SerializedFeatureChange,
10
+ ServerDataStore,
11
+ } from '@apollo-annotation/common'
12
+ import { Feature, FeatureDocument } from '@apollo-annotation/schemas'
13
+
14
+ interface SerializedTypeChangeBase extends SerializedFeatureChange {
15
+ typeName: 'TypeChange'
16
+ }
17
+
18
+ interface TypeChangeDetails {
19
+ featureId: string
20
+ oldType: string
21
+ newType: string
22
+ }
23
+
24
+ interface SerializedTypeChangeSingle
25
+ extends SerializedTypeChangeBase,
26
+ TypeChangeDetails {}
27
+
28
+ interface SerializedTypeChangeMultiple extends SerializedTypeChangeBase {
29
+ changes: TypeChangeDetails[]
30
+ }
31
+
32
+ type SerializedTypeChange =
33
+ | SerializedTypeChangeSingle
34
+ | SerializedTypeChangeMultiple
35
+
36
+ export class TypeChange extends FeatureChange {
37
+ typeName = 'TypeChange' as const
38
+ changes: TypeChangeDetails[]
39
+
40
+ constructor(json: SerializedTypeChange, options?: ChangeOptions) {
41
+ super(json, options)
42
+ this.changes = 'changes' in json ? json.changes : [json]
43
+ }
44
+
45
+ toJSON(): SerializedTypeChange {
46
+ const { assembly, changedIds, changes, typeName } = this
47
+ if (changes.length === 1) {
48
+ const [{ featureId, newType, oldType }] = changes
49
+ return { typeName, changedIds, assembly, featureId, oldType, newType }
50
+ }
51
+ return { typeName, changedIds, assembly, changes }
52
+ }
53
+
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
+ getInverse() {
142
+ const { assembly, changedIds, changes, logger, typeName } = this
143
+ const inverseChangedIds = [...changedIds].reverse()
144
+ const inverseChanges = [...changes].reverse().map((endChange) => ({
145
+ featureId: endChange.featureId,
146
+ oldType: endChange.newType,
147
+ newType: endChange.oldType,
148
+ }))
149
+ return new TypeChange(
150
+ {
151
+ changedIds: inverseChangedIds,
152
+ typeName,
153
+ changes: inverseChanges,
154
+ assembly,
155
+ },
156
+ { logger },
157
+ )
158
+ }
159
+ }
@@ -0,0 +1,82 @@
1
+ /* eslint-disable @typescript-eslint/require-await */
2
+ import {
3
+ Change,
4
+ ChangeOptions,
5
+ ClientDataStore,
6
+ LocalGFF3DataStore,
7
+ SerializedChange,
8
+ ServerDataStore,
9
+ } from '@apollo-annotation/common'
10
+
11
+ export interface SerializedUserChangeBase extends SerializedChange {
12
+ typeName: 'UserChange'
13
+ userId: string
14
+ }
15
+
16
+ export interface UserChangeDetails {
17
+ role: 'admin' | 'user' | 'readOnly'
18
+ }
19
+
20
+ export interface SerializedUserChangeSingle
21
+ extends SerializedUserChangeBase,
22
+ UserChangeDetails {}
23
+
24
+ export interface SerializedUserChangeMultiple extends SerializedUserChangeBase {
25
+ changes: UserChangeDetails[]
26
+ }
27
+
28
+ export type SerializedUserChange =
29
+ | SerializedUserChangeSingle
30
+ | SerializedUserChangeMultiple
31
+
32
+ export class UserChange extends Change {
33
+ typeName = 'UserChange' as const
34
+ changes: UserChangeDetails[]
35
+ userId: string
36
+
37
+ constructor(json: SerializedUserChange, options?: ChangeOptions) {
38
+ super(json, options)
39
+ this.changes = 'changes' in json ? json.changes : [json]
40
+ this.userId = json.userId
41
+ }
42
+
43
+ toJSON(): SerializedUserChange {
44
+ const { changes, typeName, userId } = this
45
+ if (changes.length === 1) {
46
+ const [{ role }] = changes
47
+ return { typeName, userId, role }
48
+ }
49
+ return { typeName, userId, changes }
50
+ }
51
+
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
+ getInverse() {
79
+ const { changes, logger, typeName, userId } = this
80
+ return new UserChange({ typeName, changes, userId }, { logger })
81
+ }
82
+ }
@@ -0,0 +1,52 @@
1
+ import { AddAssemblyAndFeaturesFromFileChange } from './AddAssemblyAndFeaturesFromFileChange'
2
+ import { AddAssemblyFromExternalChange } from './AddAssemblyFromExternalChange'
3
+ import { AddAssemblyFromFileChange } from './AddAssemblyFromFileChange'
4
+ import { AddFeatureChange } from './AddFeatureChange'
5
+ import { AddFeaturesFromFileChange } from './AddFeaturesFromFileChange'
6
+ import { DeleteAssemblyChange } from './DeleteAssemblyChange'
7
+ import { DeleteFeatureChange } from './DeleteFeatureChange'
8
+ import { DeleteUserChange } from './DeleteUserChange'
9
+ import { DiscontinuousLocationEndChange } from './DiscontinuousLocationEndChange'
10
+ import { DiscontinuousLocationStartChange } from './DiscontinuousLocationStartChange'
11
+ import { FeatureAttributeChange } from './FeatureAttributeChange'
12
+ import { LocationEndChange } from './LocationEndChange'
13
+ import { LocationStartChange } from './LocationStartChange'
14
+ import { StrandChange } from './StrandChange'
15
+ import { TypeChange } from './TypeChange'
16
+ import { UserChange } from './UserChange'
17
+
18
+ export const changes = {
19
+ AddAssemblyAndFeaturesFromFileChange,
20
+ AddAssemblyFromFileChange,
21
+ AddAssemblyFromExternalChange,
22
+ AddFeatureChange,
23
+ AddFeaturesFromFileChange,
24
+ DeleteAssemblyChange,
25
+ DeleteFeatureChange,
26
+ DeleteUserChange,
27
+ DiscontinuousLocationEndChange,
28
+ DiscontinuousLocationStartChange,
29
+ FeatureAttributeChange,
30
+ LocationEndChange,
31
+ LocationStartChange,
32
+ StrandChange,
33
+ TypeChange,
34
+ UserChange,
35
+ }
36
+
37
+ export * from './AddAssemblyAndFeaturesFromFileChange'
38
+ export * from './AddAssemblyFromFileChange'
39
+ export * from './AddAssemblyFromExternalChange'
40
+ export * from './AddFeatureChange'
41
+ export * from './AddFeaturesFromFileChange'
42
+ export * from './DeleteAssemblyChange'
43
+ export * from './DeleteFeatureChange'
44
+ export * from './DeleteUserChange'
45
+ export * from './DiscontinuousLocationEndChange'
46
+ export * from './DiscontinuousLocationStartChange'
47
+ export * from './FeatureAttributeChange'
48
+ export * from './LocationEndChange'
49
+ export * from './LocationStartChange'
50
+ export * from './StrandChange'
51
+ export * from './TypeChange'
52
+ export * from './UserChange'