@commitspark/graphql-api 0.9.4 → 0.11.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/CHANGELOG.md +17 -0
- package/README.md +96 -85
- package/dist/container.js +21 -13
- package/dist/container.js.map +1 -1
- package/dist/graphql/field-resolver/entry-reference-resolver.d.ts +10 -0
- package/dist/graphql/field-resolver/entry-reference-resolver.js +15 -0
- package/dist/graphql/field-resolver/entry-reference-resolver.js.map +1 -0
- package/dist/graphql/field-resolver/field-default-value-resolver.d.ts +14 -0
- package/dist/graphql/field-resolver/field-default-value-resolver.js +73 -0
- package/dist/graphql/field-resolver/field-default-value-resolver.js.map +1 -0
- package/dist/graphql/field-resolver/fieldResolver.d.ts +11 -0
- package/dist/graphql/field-resolver/fieldResolver.js +3 -0
- package/dist/graphql/field-resolver/fieldResolver.js.map +1 -0
- package/dist/graphql/field-resolver/union-value-resolver.d.ts +10 -0
- package/dist/graphql/field-resolver/union-value-resolver.js +17 -0
- package/dist/graphql/field-resolver/union-value-resolver.js.map +1 -0
- package/dist/graphql/input-type-generator.service.d.ts +3 -3
- package/dist/graphql/input-type-generator.service.js +18 -7
- package/dist/graphql/input-type-generator.service.js.map +1 -1
- package/dist/graphql/queries-mutations-generator.service.d.ts +7 -7
- package/dist/graphql/queries-mutations-generator.service.js +6 -6
- package/dist/graphql/queries-mutations-generator.service.js.map +1 -1
- package/dist/graphql/resolver-generators/mutation-create-resolver-generator.d.ts +6 -3
- package/dist/graphql/resolver-generators/mutation-create-resolver-generator.js +46 -4
- package/dist/graphql/resolver-generators/mutation-create-resolver-generator.js.map +1 -1
- package/dist/graphql/resolver-generators/mutation-delete-resolver-generator.d.ts +6 -3
- package/dist/graphql/resolver-generators/mutation-delete-resolver-generator.js +32 -9
- package/dist/graphql/resolver-generators/mutation-delete-resolver-generator.js.map +1 -1
- package/dist/graphql/resolver-generators/mutation-update-resolver-generator.d.ts +12 -0
- package/dist/graphql/resolver-generators/mutation-update-resolver-generator.js +53 -0
- package/dist/graphql/resolver-generators/mutation-update-resolver-generator.js.map +1 -0
- package/dist/graphql/resolver-generators/object-type-field-default-value-resolver-generator.d.ts +13 -0
- package/dist/graphql/resolver-generators/object-type-field-default-value-resolver-generator.js +58 -0
- package/dist/graphql/resolver-generators/object-type-field-default-value-resolver-generator.js.map +1 -0
- package/dist/graphql/resolver-generators/query-all-resolver-generator.d.ts +3 -2
- package/dist/graphql/resolver-generators/query-all-resolver-generator.js +4 -1
- package/dist/graphql/resolver-generators/query-all-resolver-generator.js.map +1 -1
- package/dist/graphql/resolver-generators/query-by-id-resolver-generator.d.ts +3 -2
- package/dist/graphql/resolver-generators/query-by-id-resolver-generator.js +2 -1
- package/dist/graphql/resolver-generators/query-by-id-resolver-generator.js.map +1 -1
- package/dist/graphql/resolver-generators/union-type-resolver-generator.d.ts +4 -4
- package/dist/graphql/resolver-generators/union-type-resolver-generator.js +3 -3
- package/dist/graphql/resolver-generators/union-type-resolver-generator.js.map +1 -1
- package/dist/graphql/schema-analyzer.service.d.ts +1 -9
- package/dist/graphql/schema-analyzer.service.js +6 -17
- package/dist/graphql/schema-analyzer.service.js.map +1 -1
- package/dist/graphql/schema-generator.service.d.ts +3 -5
- package/dist/graphql/schema-generator.service.js +7 -12
- package/dist/graphql/schema-generator.service.js.map +1 -1
- package/dist/graphql/schema-utils/entry-reference-util.d.ts +12 -4
- package/dist/graphql/schema-utils/entry-reference-util.js +105 -21
- package/dist/graphql/schema-utils/entry-reference-util.js.map +1 -1
- package/dist/graphql/schema-utils/entry-type-util.d.ts +6 -0
- package/dist/graphql/schema-utils/entry-type-util.js +34 -0
- package/dist/graphql/schema-utils/entry-type-util.js.map +1 -0
- package/dist/graphql/schema-utils/union-type-util.d.ts +5 -0
- package/dist/graphql/schema-utils/union-type-util.js +21 -0
- package/dist/graphql/schema-utils/union-type-util.js.map +1 -0
- package/dist/persistence/persistence.service.d.ts +1 -8
- package/dist/persistence/persistence.service.js +22 -87
- package/dist/persistence/persistence.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/container.ts +29 -15
- package/src/graphql/field-resolver/entry-reference-resolver.ts +47 -0
- package/src/graphql/field-resolver/field-default-value-resolver.ts +154 -0
- package/src/graphql/field-resolver/fieldResolver.ts +19 -0
- package/src/graphql/field-resolver/union-value-resolver.ts +46 -0
- package/src/graphql/input-type-generator.service.ts +22 -8
- package/src/graphql/queries-mutations-generator.service.ts +18 -18
- package/src/graphql/resolver-generators/mutation-create-resolver-generator.ts +82 -19
- package/src/graphql/resolver-generators/mutation-delete-resolver-generator.ts +72 -27
- package/src/graphql/resolver-generators/mutation-update-resolver-generator.ts +128 -0
- package/src/graphql/resolver-generators/object-type-field-default-value-resolver-generator.ts +119 -0
- package/src/graphql/resolver-generators/query-all-resolver-generator.ts +9 -7
- package/src/graphql/resolver-generators/query-by-id-resolver-generator.ts +7 -7
- package/src/graphql/resolver-generators/union-type-resolver-generator.ts +5 -7
- package/src/graphql/schema-analyzer.service.ts +10 -24
- package/src/graphql/schema-generator.service.ts +13 -22
- package/src/graphql/schema-utils/entry-reference-util.ts +170 -30
- package/src/graphql/schema-utils/entry-type-util.ts +42 -0
- package/src/graphql/schema-utils/union-type-util.ts +23 -0
- package/src/persistence/persistence.service.ts +30 -142
- package/dist/graphql/resolver-generators/entry-reference-resolver.generator.d.ts +0 -12
- package/dist/graphql/resolver-generators/entry-reference-resolver.generator.js +0 -29
- package/dist/graphql/resolver-generators/entry-reference-resolver.generator.js.map +0 -1
- package/dist/graphql/resolver-generators/mutation-update.resolver-generator.d.ts +0 -8
- package/dist/graphql/resolver-generators/mutation-update.resolver-generator.js +0 -29
- package/dist/graphql/resolver-generators/mutation-update.resolver-generator.js.map +0 -1
- package/dist/graphql/resolver-generators/union-value-resolver-generator.d.ts +0 -13
- package/dist/graphql/resolver-generators/union-value-resolver-generator.js +0 -80
- package/dist/graphql/resolver-generators/union-value-resolver-generator.js.map +0 -1
- package/src/graphql/resolver-generators/entry-reference-resolver.generator.ts +0 -71
- package/src/graphql/resolver-generators/mutation-update.resolver-generator.ts +0 -59
- package/src/graphql/resolver-generators/union-value-resolver-generator.ts +0 -125
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
GraphQLField,
|
|
3
2
|
GraphQLNullableType,
|
|
4
3
|
GraphQLObjectType,
|
|
5
4
|
isListType,
|
|
@@ -7,45 +6,186 @@ import {
|
|
|
7
6
|
isObjectType,
|
|
8
7
|
isUnionType,
|
|
9
8
|
} from 'graphql'
|
|
9
|
+
import { ApolloContext } from '../../app/api.service'
|
|
10
|
+
import { GraphQLError } from 'graphql/error/GraphQLError'
|
|
11
|
+
import { PersistenceService } from '../../persistence/persistence.service'
|
|
12
|
+
import { UnionTypeUtil } from './union-type-util'
|
|
13
|
+
import { EntryTypeUtil } from './entry-type-util'
|
|
10
14
|
|
|
11
15
|
export class EntryReferenceUtil {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const field: GraphQLField<any, any> = objectType.getFields()[fieldsKey]
|
|
18
|
-
if (this.buildsOnTypeWithEntryDirective(field.type)) {
|
|
19
|
-
fields.push(field)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return fields
|
|
23
|
-
}
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly persistence: PersistenceService,
|
|
18
|
+
private readonly entryTypeUtil: EntryTypeUtil,
|
|
19
|
+
private readonly unionTypeUtil: UnionTypeUtil,
|
|
20
|
+
) {}
|
|
24
21
|
|
|
25
|
-
public
|
|
22
|
+
public async getReferencedEntryIds(
|
|
23
|
+
rootType: GraphQLObjectType,
|
|
24
|
+
context: ApolloContext,
|
|
25
|
+
fieldName: string | null,
|
|
26
|
+
type: GraphQLNullableType,
|
|
27
|
+
data: any,
|
|
28
|
+
): Promise<string[]> {
|
|
26
29
|
if (isNonNullType(type)) {
|
|
27
|
-
return this.
|
|
30
|
+
return this.getReferencedEntryIds(
|
|
31
|
+
rootType,
|
|
32
|
+
context,
|
|
33
|
+
fieldName,
|
|
34
|
+
type.ofType,
|
|
35
|
+
data,
|
|
36
|
+
)
|
|
28
37
|
} else if (isListType(type)) {
|
|
29
|
-
|
|
38
|
+
let referencedEntryIds: string[] = []
|
|
39
|
+
for (const element of data) {
|
|
40
|
+
referencedEntryIds = [
|
|
41
|
+
...referencedEntryIds,
|
|
42
|
+
...(await this.getReferencedEntryIds(
|
|
43
|
+
rootType,
|
|
44
|
+
context,
|
|
45
|
+
fieldName,
|
|
46
|
+
type.ofType,
|
|
47
|
+
element,
|
|
48
|
+
)),
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
// deduplicate
|
|
52
|
+
referencedEntryIds = [...new Set(referencedEntryIds)]
|
|
53
|
+
return referencedEntryIds
|
|
30
54
|
} else if (isUnionType(type)) {
|
|
31
|
-
|
|
32
|
-
type
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
55
|
+
if (this.entryTypeUtil.isUnionOfEntryTypes(type)) {
|
|
56
|
+
await this.validateReference(context, '', type, data)
|
|
57
|
+
return [data.id]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const unionTypeName =
|
|
61
|
+
this.unionTypeUtil.getUnionTypeNameFromFieldValue(data)
|
|
62
|
+
const unionType = type
|
|
63
|
+
.getTypes()
|
|
64
|
+
.find((type) => type.name === unionTypeName)
|
|
65
|
+
if (!unionType) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Type "${unionTypeName}" found in field data is not a valid type for union type "${type.name}".`,
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
const unionValue = this.unionTypeUtil.getUnionValue(data)
|
|
71
|
+
return this.getReferencedEntryIds(
|
|
72
|
+
rootType,
|
|
73
|
+
context,
|
|
74
|
+
fieldName,
|
|
75
|
+
unionType,
|
|
76
|
+
unionValue,
|
|
36
77
|
)
|
|
37
78
|
} else if (isObjectType(type)) {
|
|
38
|
-
|
|
79
|
+
if (
|
|
80
|
+
type.name !== rootType.name &&
|
|
81
|
+
this.entryTypeUtil.hasEntryDirective(type)
|
|
82
|
+
) {
|
|
83
|
+
await this.validateReference(context, fieldName ?? '', type, data)
|
|
84
|
+
return [data.id]
|
|
85
|
+
} else {
|
|
86
|
+
let referencedEntryIds: string[] = []
|
|
87
|
+
for (const [fieldsKey, field] of Object.entries(type.getFields())) {
|
|
88
|
+
const fieldValue = data[fieldsKey] ?? undefined
|
|
89
|
+
if (fieldValue !== undefined) {
|
|
90
|
+
const nestedResult = await this.getReferencedEntryIds(
|
|
91
|
+
rootType,
|
|
92
|
+
context,
|
|
93
|
+
fieldsKey,
|
|
94
|
+
field.type,
|
|
95
|
+
fieldValue,
|
|
96
|
+
)
|
|
97
|
+
referencedEntryIds = [...referencedEntryIds, ...nestedResult]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// deduplicate
|
|
101
|
+
referencedEntryIds = [...new Set(referencedEntryIds)]
|
|
102
|
+
return referencedEntryIds
|
|
103
|
+
}
|
|
39
104
|
}
|
|
40
|
-
|
|
105
|
+
|
|
106
|
+
return []
|
|
41
107
|
}
|
|
42
108
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
109
|
+
private async validateReference(
|
|
110
|
+
context: ApolloContext,
|
|
111
|
+
fieldName: string,
|
|
112
|
+
fieldType: GraphQLNullableType,
|
|
113
|
+
fieldValue: any,
|
|
114
|
+
): Promise<void> {
|
|
115
|
+
if (isNonNullType(fieldType)) {
|
|
116
|
+
await this.validateReference(
|
|
117
|
+
context,
|
|
118
|
+
fieldName,
|
|
119
|
+
fieldType.ofType,
|
|
120
|
+
fieldValue,
|
|
121
|
+
)
|
|
122
|
+
return
|
|
123
|
+
} else if (isListType(fieldType)) {
|
|
124
|
+
if (!Array.isArray(fieldValue)) {
|
|
125
|
+
throw new Error(`Expected array value in field "${fieldName}"`)
|
|
126
|
+
}
|
|
127
|
+
for (const fieldListElement of fieldValue) {
|
|
128
|
+
await this.validateReference(
|
|
129
|
+
context,
|
|
130
|
+
fieldName,
|
|
131
|
+
fieldType.ofType,
|
|
132
|
+
fieldListElement,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
return
|
|
136
|
+
} else if (isUnionType(fieldType) || isObjectType(fieldType)) {
|
|
137
|
+
if (!('id' in fieldValue)) {
|
|
138
|
+
throw new Error('Expected key "id"')
|
|
139
|
+
}
|
|
140
|
+
const referencedId = fieldValue.id
|
|
141
|
+
let referencedTypeName
|
|
142
|
+
try {
|
|
143
|
+
referencedTypeName = await this.persistence.getTypeById(
|
|
144
|
+
context.gitAdapter,
|
|
145
|
+
context.getCurrentRef(),
|
|
146
|
+
referencedId,
|
|
147
|
+
)
|
|
148
|
+
} catch (error) {
|
|
149
|
+
throw new GraphQLError(
|
|
150
|
+
`Reference with id "${referencedId}" points to non-existing entry`,
|
|
151
|
+
{
|
|
152
|
+
extensions: {
|
|
153
|
+
code: 'BAD_USER_INPUT',
|
|
154
|
+
fieldName: fieldName,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
if (!this.isPermittedReferenceType(referencedTypeName, fieldType)) {
|
|
160
|
+
throw new GraphQLError(
|
|
161
|
+
`Reference with id "${referencedId}" points to entry of incompatible type`,
|
|
162
|
+
{
|
|
163
|
+
extensions: {
|
|
164
|
+
code: 'BAD_USER_INPUT',
|
|
165
|
+
fieldName: fieldName,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private isPermittedReferenceType(
|
|
174
|
+
referencedTypeName: string,
|
|
175
|
+
fieldType: GraphQLNullableType,
|
|
176
|
+
): boolean {
|
|
177
|
+
if (isNonNullType(fieldType)) {
|
|
178
|
+
return this.isPermittedReferenceType(referencedTypeName, fieldType.ofType)
|
|
179
|
+
} else if (isListType(fieldType)) {
|
|
180
|
+
return this.isPermittedReferenceType(referencedTypeName, fieldType.ofType)
|
|
181
|
+
} else if (isUnionType(fieldType)) {
|
|
182
|
+
return fieldType
|
|
183
|
+
.getTypes()
|
|
184
|
+
.map((concreteType) => concreteType.name)
|
|
185
|
+
.includes(referencedTypeName)
|
|
186
|
+
} else if (isObjectType(fieldType)) {
|
|
187
|
+
return fieldType.name === referencedTypeName
|
|
188
|
+
}
|
|
189
|
+
return false
|
|
50
190
|
}
|
|
51
191
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GraphQLNullableType,
|
|
3
|
+
GraphQLObjectType,
|
|
4
|
+
GraphQLUnionType,
|
|
5
|
+
isListType,
|
|
6
|
+
isNonNullType,
|
|
7
|
+
isObjectType,
|
|
8
|
+
isUnionType,
|
|
9
|
+
} from 'graphql'
|
|
10
|
+
|
|
11
|
+
export class EntryTypeUtil {
|
|
12
|
+
public buildsOnTypeWithEntryDirective(type: GraphQLNullableType): boolean {
|
|
13
|
+
if (isNonNullType(type)) {
|
|
14
|
+
return this.buildsOnTypeWithEntryDirective(type.ofType)
|
|
15
|
+
} else if (isListType(type)) {
|
|
16
|
+
return this.buildsOnTypeWithEntryDirective(type.ofType)
|
|
17
|
+
} else if (isUnionType(type)) {
|
|
18
|
+
return this.isUnionOfEntryTypes(type)
|
|
19
|
+
} else if (isObjectType(type)) {
|
|
20
|
+
return this.hasEntryDirective(type)
|
|
21
|
+
}
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public hasEntryDirective(type: GraphQLObjectType): boolean {
|
|
26
|
+
return (
|
|
27
|
+
!!type.astNode &&
|
|
28
|
+
type.astNode.directives?.find(
|
|
29
|
+
(directive) => directive.name.value === 'Entry',
|
|
30
|
+
) !== undefined
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public isUnionOfEntryTypes(type: GraphQLUnionType): boolean {
|
|
35
|
+
return (
|
|
36
|
+
type
|
|
37
|
+
.getTypes()
|
|
38
|
+
.filter((unionType) => this.buildsOnTypeWithEntryDirective(unionType))
|
|
39
|
+
.length > 0
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EntryData } from '@commitspark/git-adapter'
|
|
2
|
+
|
|
3
|
+
export class UnionTypeUtil {
|
|
4
|
+
public getUnionTypeNameFromFieldValue(fieldValue: any): string {
|
|
5
|
+
if (typeof fieldValue !== 'object') {
|
|
6
|
+
throw new Error('Expected object as union value')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Based on our @oneOf directive, we expect only one field whose name
|
|
10
|
+
// corresponds to the concrete type's name.
|
|
11
|
+
const firstKey = Object.keys(fieldValue)[0]
|
|
12
|
+
return firstKey.slice(0, 1).toUpperCase() + firstKey.slice(1)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public getUnionValue(fieldValue: any): EntryData {
|
|
16
|
+
if (typeof fieldValue !== 'object') {
|
|
17
|
+
throw new Error('Expected object as union value')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const firstKey = Object.keys(fieldValue)[0]
|
|
21
|
+
return fieldValue[firstKey]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Entry, GitAdapter } from '@commitspark/git-adapter'
|
|
2
2
|
import { GraphQLError } from 'graphql/error/GraphQLError'
|
|
3
3
|
|
|
4
4
|
export class PersistenceService {
|
|
@@ -7,12 +7,14 @@ export class PersistenceService {
|
|
|
7
7
|
commitHash: string,
|
|
8
8
|
id: string,
|
|
9
9
|
): Promise<string> {
|
|
10
|
-
const allEntries = await gitAdapter.
|
|
11
|
-
const requestedEntry = allEntries.
|
|
12
|
-
(contentEntry: ContentEntry) => contentEntry.id === id,
|
|
13
|
-
)[0]
|
|
10
|
+
const allEntries = await gitAdapter.getEntries(commitHash)
|
|
11
|
+
const requestedEntry = allEntries.find((entry: Entry) => entry.id === id)
|
|
14
12
|
if (requestedEntry === undefined) {
|
|
15
|
-
throw new
|
|
13
|
+
throw new GraphQLError(`Not found: ${id}`, {
|
|
14
|
+
extensions: {
|
|
15
|
+
code: 'NOT_FOUND',
|
|
16
|
+
},
|
|
17
|
+
})
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
return requestedEntry.metadata.type
|
|
@@ -23,15 +25,17 @@ export class PersistenceService {
|
|
|
23
25
|
commitHash: string,
|
|
24
26
|
id: string,
|
|
25
27
|
): Promise<Entry> {
|
|
26
|
-
const allEntries = await gitAdapter.
|
|
27
|
-
const requestedEntry = allEntries.
|
|
28
|
-
(contentEntry: ContentEntry) => contentEntry.id === id,
|
|
29
|
-
)[0]
|
|
28
|
+
const allEntries = await gitAdapter.getEntries(commitHash)
|
|
29
|
+
const requestedEntry = allEntries.find((entry: Entry) => entry.id === id)
|
|
30
30
|
if (requestedEntry === undefined) {
|
|
31
|
-
throw new
|
|
31
|
+
throw new GraphQLError(`Not found: ${id}`, {
|
|
32
|
+
extensions: {
|
|
33
|
+
code: 'NOT_FOUND',
|
|
34
|
+
},
|
|
35
|
+
})
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
return
|
|
38
|
+
return requestedEntry
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
public async findByType(
|
|
@@ -39,12 +43,8 @@ export class PersistenceService {
|
|
|
39
43
|
commitHash: string,
|
|
40
44
|
type: string,
|
|
41
45
|
): Promise<Entry[]> {
|
|
42
|
-
const allEntries = await gitAdapter.
|
|
43
|
-
return allEntries
|
|
44
|
-
.filter(
|
|
45
|
-
(contentEntry: ContentEntry) => contentEntry.metadata.type === type,
|
|
46
|
-
)
|
|
47
|
-
.map((value) => ({ ...value.data, id: value.id }))
|
|
46
|
+
const allEntries = await gitAdapter.getEntries(commitHash)
|
|
47
|
+
return allEntries.filter((entry: Entry) => entry.metadata.type === type)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
public async findByTypeId(
|
|
@@ -53,134 +53,22 @@ export class PersistenceService {
|
|
|
53
53
|
type: string,
|
|
54
54
|
id: string,
|
|
55
55
|
): Promise<Entry> {
|
|
56
|
-
const allEntries = await gitAdapter.
|
|
57
|
-
const requestedEntry = allEntries.
|
|
58
|
-
(
|
|
59
|
-
)
|
|
60
|
-
if (requestedEntry === undefined
|
|
61
|
-
throw new
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return { ...requestedEntry.data, id: id }
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
public async createType(
|
|
68
|
-
gitAdapter: GitAdapter,
|
|
69
|
-
branch: string,
|
|
70
|
-
commitHash: string,
|
|
71
|
-
typeName: string,
|
|
72
|
-
id: string,
|
|
73
|
-
data: Entry,
|
|
74
|
-
message: string,
|
|
75
|
-
): Promise<CommitResult> {
|
|
76
|
-
// TODO expose regex publicly to allow reuse
|
|
77
|
-
const regex = /^[a-zA-Z0-9\-_]{1,250}$/
|
|
78
|
-
if (!id.match(regex)) {
|
|
79
|
-
throw new GraphQLError(`"id" does not match regex "${regex}"`, {
|
|
80
|
-
extensions: {
|
|
81
|
-
code: 'BAD_USER_INPUT',
|
|
82
|
-
argumentName: 'id',
|
|
83
|
-
},
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const commit = await gitAdapter.createCommit({
|
|
88
|
-
ref: branch,
|
|
89
|
-
parentSha: commitHash,
|
|
90
|
-
contentEntries: [
|
|
56
|
+
const allEntries = await gitAdapter.getEntries(commitHash)
|
|
57
|
+
const requestedEntry = allEntries.find(
|
|
58
|
+
(entry: Entry) => entry.id === id && entry.metadata.type === type,
|
|
59
|
+
)
|
|
60
|
+
if (requestedEntry === undefined) {
|
|
61
|
+
throw new GraphQLError(
|
|
62
|
+
`No entry of type "${type}" with id "${id}" exists`,
|
|
91
63
|
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
64
|
+
extensions: {
|
|
65
|
+
code: 'BAD_USER_INPUT',
|
|
66
|
+
argumentName: 'id',
|
|
95
67
|
},
|
|
96
|
-
data: data,
|
|
97
|
-
deletion: false,
|
|
98
68
|
},
|
|
99
|
-
|
|
100
|
-
message: message,
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
ref: commit.ref,
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
public async updateByTypeId(
|
|
109
|
-
gitAdapter: GitAdapter,
|
|
110
|
-
branch: string,
|
|
111
|
-
commitHash: string,
|
|
112
|
-
type: string,
|
|
113
|
-
id: string,
|
|
114
|
-
data: Entry,
|
|
115
|
-
message: string,
|
|
116
|
-
): Promise<CommitResult> {
|
|
117
|
-
const allEntries = await gitAdapter.getContentEntries(commitHash)
|
|
118
|
-
const requestedEntry = allEntries.filter(
|
|
119
|
-
(contentEntry: ContentEntry) => contentEntry.id === id,
|
|
120
|
-
)[0]
|
|
121
|
-
if (requestedEntry === undefined || requestedEntry.metadata.type !== type) {
|
|
122
|
-
throw new Error(`Not found: ${type}, ${id}`)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const newData: Entry = { ...requestedEntry.data, ...data }
|
|
126
|
-
|
|
127
|
-
const commit = await gitAdapter.createCommit({
|
|
128
|
-
ref: branch,
|
|
129
|
-
parentSha: commitHash,
|
|
130
|
-
contentEntries: [
|
|
131
|
-
{
|
|
132
|
-
id: id,
|
|
133
|
-
metadata: requestedEntry.metadata,
|
|
134
|
-
data: newData,
|
|
135
|
-
deletion: false,
|
|
136
|
-
},
|
|
137
|
-
],
|
|
138
|
-
message: message,
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
ref: commit.ref,
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public async deleteByTypeId(
|
|
147
|
-
gitAdapter: GitAdapter,
|
|
148
|
-
branch: string,
|
|
149
|
-
commitHash: string,
|
|
150
|
-
type: string,
|
|
151
|
-
id: string,
|
|
152
|
-
message: string,
|
|
153
|
-
): Promise<CommitResult> {
|
|
154
|
-
const allEntries = await gitAdapter.getContentEntries(commitHash)
|
|
155
|
-
const requestedEntry = allEntries.filter(
|
|
156
|
-
(contentEntry: ContentEntry) => contentEntry.id === id,
|
|
157
|
-
)[0]
|
|
158
|
-
if (requestedEntry === undefined || requestedEntry.metadata.type !== type) {
|
|
159
|
-
throw new Error(`Not found: ${type}, ${id}`)
|
|
69
|
+
)
|
|
160
70
|
}
|
|
161
71
|
|
|
162
|
-
|
|
163
|
-
ref: branch,
|
|
164
|
-
parentSha: commitHash,
|
|
165
|
-
contentEntries: [
|
|
166
|
-
{
|
|
167
|
-
id: id,
|
|
168
|
-
metadata: requestedEntry.metadata,
|
|
169
|
-
data: {},
|
|
170
|
-
deletion: true,
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
message: message,
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
ref: commit.ref,
|
|
178
|
-
}
|
|
72
|
+
return requestedEntry
|
|
179
73
|
}
|
|
180
74
|
}
|
|
181
|
-
|
|
182
|
-
export interface CommitResult {
|
|
183
|
-
ref: string // commit sha
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export type Entry = Record<string, unknown>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { GraphQLField, GraphQLObjectType } from 'graphql';
|
|
2
|
-
import { Entry, PersistenceService } from '../../persistence/persistence.service';
|
|
3
|
-
import { ApolloContext } from '../../app/api.service';
|
|
4
|
-
import { GraphQLFieldResolver } from 'graphql/type/definition';
|
|
5
|
-
export declare class EntryReferenceResolverGenerator {
|
|
6
|
-
private readonly persistence;
|
|
7
|
-
constructor(persistence: PersistenceService);
|
|
8
|
-
createResolver(context: ApolloContext, obj: {
|
|
9
|
-
type: GraphQLObjectType;
|
|
10
|
-
fields: GraphQLField<any, any>[];
|
|
11
|
-
}): Record<string, GraphQLFieldResolver<Record<string, any>, ApolloContext, any, Promise<Entry | Entry[] | null>>>;
|
|
12
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EntryReferenceResolverGenerator = void 0;
|
|
4
|
-
class EntryReferenceResolverGenerator {
|
|
5
|
-
constructor(persistence) {
|
|
6
|
-
this.persistence = persistence;
|
|
7
|
-
}
|
|
8
|
-
createResolver(context, obj) {
|
|
9
|
-
const persistence = this.persistence;
|
|
10
|
-
const fieldResolvers = {};
|
|
11
|
-
for (const field of obj.fields) {
|
|
12
|
-
const fieldName = field.name;
|
|
13
|
-
fieldResolvers[fieldName] = async (source, args, context, info) => {
|
|
14
|
-
if (source[fieldName] === undefined || source[fieldName] === null) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
if (Array.isArray(source[fieldName])) {
|
|
18
|
-
return source[fieldName].map((el) => persistence.findById(context.gitAdapter, context.getCurrentRef(), el.id));
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
return persistence.findById(context.gitAdapter, context.getCurrentRef(), source[fieldName].id);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
return fieldResolvers;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
exports.EntryReferenceResolverGenerator = EntryReferenceResolverGenerator;
|
|
29
|
-
//# sourceMappingURL=entry-reference-resolver.generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"entry-reference-resolver.generator.js","sourceRoot":"","sources":["../../../src/graphql/resolver-generators/entry-reference-resolver.generator.ts"],"names":[],"mappings":";;;AAQA,MAAa,+BAA+B;IAC1C,YAA6B,WAA+B;QAA/B,gBAAW,GAAX,WAAW,CAAoB;IAAG,CAAC;IAEzD,cAAc,CACnB,OAAsB,EACtB,GAGC;QAUD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QAEpC,MAAM,cAAc,GAQhB,EAAE,CAAA;QAEN,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE;YAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAA;YAC5B,cAAc,CAAC,SAAS,CAAC,GAAG,KAAK,EAC/B,MAAM,EACN,IAAI,EACJ,OAAO,EACP,IAAI,EAC6B,EAAE;gBACnC,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;oBACjE,OAAO,IAAI,CAAA;iBACZ;gBAED,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE;oBACpC,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CACvC,WAAW,CAAC,QAAQ,CAClB,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,aAAa,EAAE,EACvB,EAAE,CAAC,EAAE,CACN,CACF,CAAA;iBACF;qBAAM;oBACL,OAAO,WAAW,CAAC,QAAQ,CACzB,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,aAAa,EAAE,EACvB,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CACrB,CAAA;iBACF;YACH,CAAC,CAAA;SACF;QAED,OAAO,cAAc,CAAA;IACvB,CAAC;CACF;AA9DD,0EA8DC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Entry, PersistenceService } from '../../persistence/persistence.service';
|
|
2
|
-
import { GraphQLFieldResolver } from 'graphql/type/definition';
|
|
3
|
-
import { ApolloContext } from '../../app/api.service';
|
|
4
|
-
export declare class MutationUpdateResolverGenerator {
|
|
5
|
-
private readonly persistence;
|
|
6
|
-
constructor(persistence: PersistenceService);
|
|
7
|
-
createResolver(typeName: string): GraphQLFieldResolver<any, ApolloContext, any, Promise<Entry>>;
|
|
8
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MutationUpdateResolverGenerator = void 0;
|
|
4
|
-
const GraphQLError_1 = require("graphql/error/GraphQLError");
|
|
5
|
-
class MutationUpdateResolverGenerator {
|
|
6
|
-
constructor(persistence) {
|
|
7
|
-
this.persistence = persistence;
|
|
8
|
-
}
|
|
9
|
-
createResolver(typeName) {
|
|
10
|
-
return async (source, args, context, info) => {
|
|
11
|
-
try {
|
|
12
|
-
await this.persistence.findByTypeId(context.gitAdapter, context.getCurrentRef(), typeName, args.id);
|
|
13
|
-
}
|
|
14
|
-
catch (_) {
|
|
15
|
-
throw new GraphQLError_1.GraphQLError(`No entry of type "${typeName}" with id "${args.id}" exists`, {
|
|
16
|
-
extensions: {
|
|
17
|
-
code: 'BAD_USER_INPUT',
|
|
18
|
-
argumentName: 'id',
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
const updateResult = await this.persistence.updateByTypeId(context.gitAdapter, context.branch, context.getCurrentRef(), typeName, args.id, args.data, args.message);
|
|
23
|
-
context.setCurrentRef(updateResult.ref);
|
|
24
|
-
return this.persistence.findByTypeId(context.gitAdapter, context.getCurrentRef(), typeName, args.id);
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
exports.MutationUpdateResolverGenerator = MutationUpdateResolverGenerator;
|
|
29
|
-
//# sourceMappingURL=mutation-update.resolver-generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mutation-update.resolver-generator.js","sourceRoot":"","sources":["../../../src/graphql/resolver-generators/mutation-update.resolver-generator.ts"],"names":[],"mappings":";;;AAMA,6DAAyD;AAEzD,MAAa,+BAA+B;IAC1C,YAA6B,WAA+B;QAA/B,gBAAW,GAAX,WAAW,CAAoB;IAAG,CAAC;IAEzD,cAAc,CACnB,QAAgB;QAEhB,OAAO,KAAK,EACV,MAAM,EACN,IAAI,EACJ,OAAsB,EACtB,IAAI,EACY,EAAE;YAClB,IAAI;gBACF,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CACjC,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,aAAa,EAAE,EACvB,QAAQ,EACR,IAAI,CAAC,EAAE,CACR,CAAA;aACF;YAAC,OAAO,CAAC,EAAE;gBACV,MAAM,IAAI,2BAAY,CACpB,qBAAqB,QAAQ,cAAc,IAAI,CAAC,EAAE,UAAU,EAC5D;oBACE,UAAU,EAAE;wBACV,IAAI,EAAE,gBAAgB;wBACtB,YAAY,EAAE,IAAI;qBACnB;iBACF,CACF,CAAA;aACF;YAGD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CACxD,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,aAAa,EAAE,EACvB,QAAQ,EACR,IAAI,CAAC,EAAE,EACP,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO,CACb,CAAA;YACD,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;YACvC,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAClC,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,aAAa,EAAE,EACvB,QAAQ,EACR,IAAI,CAAC,EAAE,CACR,CAAA;QACH,CAAC,CAAA;IACH,CAAC;CACF;AAlDD,0EAkDC"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { GraphQLFieldResolver } from 'graphql/type/definition';
|
|
2
|
-
import { ApolloContext } from '../../app/api.service';
|
|
3
|
-
import { Entry } from '../../persistence/persistence.service';
|
|
4
|
-
import { GraphQLSchema } from 'graphql';
|
|
5
|
-
import { EntryReferenceUtil } from '../schema-utils/entry-reference-util';
|
|
6
|
-
export declare class UnionValueResolverGenerator {
|
|
7
|
-
private readonly entryReferenceUtil;
|
|
8
|
-
constructor(entryReferenceUtil: EntryReferenceUtil);
|
|
9
|
-
createResolver(schema: GraphQLSchema): Record<string, Record<string, GraphQLFieldResolver<any, ApolloContext, any, Entry | null>>>;
|
|
10
|
-
private getFieldsWithUnionTypeNotUsingEntryTypes;
|
|
11
|
-
private buildsOnUnionType;
|
|
12
|
-
private collapseTypeField;
|
|
13
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UnionValueResolverGenerator = void 0;
|
|
4
|
-
const graphql_1 = require("graphql");
|
|
5
|
-
class UnionValueResolverGenerator {
|
|
6
|
-
constructor(entryReferenceUtil) {
|
|
7
|
-
this.entryReferenceUtil = entryReferenceUtil;
|
|
8
|
-
}
|
|
9
|
-
createResolver(schema) {
|
|
10
|
-
const resolvers = {};
|
|
11
|
-
for (const typeName of Object.keys(schema.getTypeMap())) {
|
|
12
|
-
const type = schema.getType(typeName);
|
|
13
|
-
if (!(0, graphql_1.isObjectType)(type)) {
|
|
14
|
-
continue;
|
|
15
|
-
}
|
|
16
|
-
const objectType = type;
|
|
17
|
-
const unionFieldsNotUsingEntry = this.getFieldsWithUnionTypeNotUsingEntryTypes(objectType);
|
|
18
|
-
const fieldResolvers = {};
|
|
19
|
-
for (const field of unionFieldsNotUsingEntry) {
|
|
20
|
-
fieldResolvers[field.name] = (obj, args, context, info) => {
|
|
21
|
-
const fieldValue = obj[info.fieldName];
|
|
22
|
-
return this.collapseTypeField(field.type, fieldValue);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
if (Object.keys(fieldResolvers).length > 0) {
|
|
26
|
-
resolvers[typeName] = fieldResolvers;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return resolvers;
|
|
30
|
-
}
|
|
31
|
-
getFieldsWithUnionTypeNotUsingEntryTypes(objectType) {
|
|
32
|
-
const fields = [];
|
|
33
|
-
for (const fieldsKey in objectType.getFields()) {
|
|
34
|
-
const field = objectType.getFields()[fieldsKey];
|
|
35
|
-
if (this.buildsOnUnionType(field.type) &&
|
|
36
|
-
!this.entryReferenceUtil.buildsOnTypeWithEntryDirective(field.type)) {
|
|
37
|
-
fields.push(field);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return fields;
|
|
41
|
-
}
|
|
42
|
-
buildsOnUnionType(type) {
|
|
43
|
-
if ((0, graphql_1.isNonNullType)(type)) {
|
|
44
|
-
return this.buildsOnUnionType(type.ofType);
|
|
45
|
-
}
|
|
46
|
-
else if ((0, graphql_1.isListType)(type)) {
|
|
47
|
-
return this.buildsOnUnionType(type.ofType);
|
|
48
|
-
}
|
|
49
|
-
else if ((0, graphql_1.isUnionType)(type)) {
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
else if ((0, graphql_1.isObjectType)(type)) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
collapseTypeField(type, fieldValue) {
|
|
58
|
-
if ((0, graphql_1.isNonNullType)(type)) {
|
|
59
|
-
return this.collapseTypeField(type.ofType, fieldValue);
|
|
60
|
-
}
|
|
61
|
-
else if (fieldValue === null) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
else if ((0, graphql_1.isListType)(type)) {
|
|
65
|
-
if (!Array.isArray(fieldValue)) {
|
|
66
|
-
throw new Error('Expected array value');
|
|
67
|
-
}
|
|
68
|
-
return fieldValue.map((item) => this.collapseTypeField(type.ofType, item));
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
const firstKey = Object.keys(fieldValue)[0];
|
|
72
|
-
if (Array.isArray(fieldValue)) {
|
|
73
|
-
throw new Error('Did not expect array value');
|
|
74
|
-
}
|
|
75
|
-
return Object.assign(Object.assign({}, fieldValue[firstKey]), { __typename: firstKey.slice(0, 1).toUpperCase() + firstKey.slice(1) });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
exports.UnionValueResolverGenerator = UnionValueResolverGenerator;
|
|
80
|
-
//# sourceMappingURL=union-value-resolver-generator.js.map
|