@contember/engine-content-api 1.3.4 → 1.4.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/ExecutionContainer.d.ts +4 -4
- package/dist/src/ExecutionContainer.d.ts.map +1 -1
- package/dist/src/ExecutionContainer.js +5 -2
- package/dist/src/ExecutionContainer.js.map +1 -1
- package/dist/src/extensions/EntityFieldsProvider.d.ts +1 -1
- package/dist/src/extensions/EntityFieldsProvider.d.ts.map +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducer.d.ts +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducer.d.ts.map +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducer.js +12 -2
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducer.js.map +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneRelationReducerVisitor.d.ts +16 -9
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneRelationReducerVisitor.d.ts.map +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneRelationReducerVisitor.js +21 -13
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneRelationReducerVisitor.js.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProvider.d.ts +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProvider.d.ts.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProvider.js +8 -2
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProvider.js.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProviderVisitor.d.ts +16 -9
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProviderVisitor.d.ts.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProviderVisitor.js +17 -12
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyFieldProviderVisitor.js.map +1 -1
- package/dist/src/introspection/IntrospectionSchemaDefinitionFactory.d.ts +5 -2
- package/dist/src/introspection/IntrospectionSchemaDefinitionFactory.d.ts.map +1 -1
- package/dist/src/introspection/IntrospectionSchemaDefinitionFactory.js +164 -14
- package/dist/src/introspection/IntrospectionSchemaDefinitionFactory.js.map +1 -1
- package/dist/src/introspection/index.d.ts +1 -2
- package/dist/src/introspection/index.d.ts.map +1 -1
- package/dist/src/introspection/index.js +4 -4
- package/dist/src/introspection/index.js.map +1 -1
- package/dist/src/mapper/ErrorUtils.d.ts +3 -3
- package/dist/src/mapper/ErrorUtils.d.ts.map +1 -1
- package/dist/src/mapper/ErrorUtils.js +2 -2
- package/dist/src/mapper/ErrorUtils.js.map +1 -1
- package/dist/src/mapper/Mapper.d.ts +2 -3
- package/dist/src/mapper/Mapper.d.ts.map +1 -1
- package/dist/src/mapper/Mapper.js +1 -1
- package/dist/src/mapper/Mapper.js.map +1 -1
- package/dist/src/mapper/MapperFactory.d.ts +3 -3
- package/dist/src/mapper/MapperFactory.d.ts.map +1 -1
- package/dist/src/mapper/MapperFactory.js.map +1 -1
- package/dist/src/mapper/Result.d.ts +2 -2
- package/dist/src/mapper/Result.d.ts.map +1 -1
- package/dist/src/mapper/Result.js.map +1 -1
- package/dist/src/mapper/delete/DeleteExecutor.js +1 -1
- package/dist/src/mapper/delete/DeleteExecutor.js.map +1 -1
- package/dist/src/mapper/insert/Inserter.d.ts +3 -2
- package/dist/src/mapper/insert/Inserter.d.ts.map +1 -1
- package/dist/src/mapper/insert/Inserter.js.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.d.ts.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.js +8 -7
- package/dist/src/mapper/select/RelationFetcher.js.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitor.d.ts +3 -5
- package/dist/src/mapper/select/handlers/FieldsVisitor.d.ts.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitor.js +8 -4
- package/dist/src/mapper/select/handlers/FieldsVisitor.js.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitorFactory.d.ts +3 -5
- package/dist/src/mapper/select/handlers/FieldsVisitorFactory.d.ts.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitorFactory.js +3 -4
- package/dist/src/mapper/select/handlers/FieldsVisitorFactory.js.map +1 -1
- package/dist/src/mapper/update/Updater.d.ts +2 -2
- package/dist/src/mapper/update/Updater.d.ts.map +1 -1
- package/dist/src/mapper/update/Updater.js.map +1 -1
- package/dist/src/resolvers/MutationResolver.d.ts +3 -2
- package/dist/src/resolvers/MutationResolver.d.ts.map +1 -1
- package/dist/src/resolvers/MutationResolver.js +20 -18
- package/dist/src/resolvers/MutationResolver.js.map +1 -1
- package/dist/src/schema/EntityTypeProvider.d.ts.map +1 -1
- package/dist/src/schema/EntityTypeProvider.js +23 -26
- package/dist/src/schema/EntityTypeProvider.js.map +1 -1
- package/dist/src/schema/GraphQlSchemaBuilder.d.ts +10 -2
- package/dist/src/schema/GraphQlSchemaBuilder.d.ts.map +1 -1
- package/dist/src/schema/GraphQlSchemaBuilder.js +47 -37
- package/dist/src/schema/GraphQlSchemaBuilder.js.map +1 -1
- package/dist/src/schema/ResultSchemaTypeProvider.d.ts +4 -0
- package/dist/src/schema/ResultSchemaTypeProvider.d.ts.map +1 -1
- package/dist/src/schema/ResultSchemaTypeProvider.js +27 -23
- package/dist/src/schema/ResultSchemaTypeProvider.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/deferedConstraints.test.js +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/deferedConstraints.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlDb/update/deferredUniqueConstraints.test.d.ts +2 -0
- package/dist/tests/cases/integration/graphQlDb/update/deferredUniqueConstraints.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/graphQlDb/update/deferredUniqueConstraints.test.js +170 -0
- package/dist/tests/cases/integration/graphQlDb/update/deferredUniqueConstraints.test.js.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.js +44 -0
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js +20 -0
- package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js.map +1 -1
- package/dist/tests/src/test.js +1 -1
- package/dist/tests/src/test.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/graphql.codegen.yml +1 -1
- package/package.json +12 -14
- package/src/ExecutionContainer.ts +13 -6
- package/src/extensions/EntityFieldsProvider.ts +1 -1
- package/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducer.ts +12 -5
- package/src/extensions/hasManyToHasOneReducer/HasManyToHasOneRelationReducerVisitor.ts +33 -24
- package/src/extensions/paginatedHasMany/PaginatedHasManyFieldProvider.ts +8 -5
- package/src/extensions/paginatedHasMany/PaginatedHasManyFieldProviderVisitor.ts +28 -17
- package/src/introspection/IntrospectionSchemaDefinitionFactory.ts +202 -13
- package/src/introspection/index.ts +1 -2
- package/src/mapper/ErrorUtils.ts +8 -7
- package/src/mapper/Mapper.ts +4 -4
- package/src/mapper/MapperFactory.ts +3 -3
- package/src/mapper/Result.ts +2 -3
- package/src/mapper/delete/DeleteExecutor.ts +1 -1
- package/src/mapper/insert/Inserter.ts +3 -2
- package/src/mapper/select/RelationFetcher.ts +8 -4
- package/src/mapper/select/handlers/FieldsVisitor.ts +9 -5
- package/src/mapper/select/handlers/FieldsVisitorFactory.ts +3 -6
- package/src/mapper/update/Updater.ts +3 -2
- package/src/resolvers/MutationResolver.ts +29 -22
- package/src/schema/EntityTypeProvider.ts +32 -41
- package/src/schema/GraphQlSchemaBuilder.ts +61 -40
- package/src/schema/ResultSchemaTypeProvider.ts +29 -27
- package/tests/cases/integration/graphQlDb/update/deferedConstraints.test.ts +1 -1
- package/tests/cases/integration/graphQlDb/update/deferredUniqueConstraints.test.ts +169 -0
- package/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.ts +45 -0
- package/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.ts +24 -0
- package/tests/cases/integration/graphQlSchema/schema-acl-allowed.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-acl-create-only.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-acl-restricted-create.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-acl-restricted-delete.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-acl-restricted-update.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-acl.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-aliased-type.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-basic.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-bug-66.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-custom-primary.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-has-many-reduction.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-new-builder.gql +1 -0
- package/tests/cases/integration/graphQlSchema/schema-read-only.gql +116 -0
- package/tests/src/test.ts +3 -3
- package/dist/src/introspection/content-schema.graphql.d.ts +0 -4
- package/dist/src/introspection/content-schema.graphql.d.ts.map +0 -1
- package/dist/src/introspection/content-schema.graphql.js +0 -113
- package/dist/src/introspection/content-schema.graphql.js.map +0 -1
- package/src/introspection/content-schema.graphql.ts +0 -113
package/graphql.codegen.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/engine-content-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0-alpha.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"typings": "dist/src/index.d.ts",
|
|
@@ -13,21 +13,19 @@
|
|
|
13
13
|
"test": "vitest --dir ./tests/cases --no-threads"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@contember/database": "1.
|
|
17
|
-
"@contember/dic": "1.
|
|
18
|
-
"@contember/graphql-utils": "1.
|
|
19
|
-
"@contember/logger": "1.
|
|
20
|
-
"@contember/schema": "1.
|
|
21
|
-
"@contember/schema-definition": "1.
|
|
22
|
-
"@contember/schema-utils": "1.
|
|
23
|
-
"
|
|
24
|
-
"fast-deep-equal": "^3.1.3",
|
|
25
|
-
"graphql-tag": "^2.12.5"
|
|
16
|
+
"@contember/database": "1.4.0-alpha.1",
|
|
17
|
+
"@contember/dic": "1.4.0-alpha.1",
|
|
18
|
+
"@contember/graphql-utils": "1.4.0-alpha.1",
|
|
19
|
+
"@contember/logger": "1.4.0-alpha.1",
|
|
20
|
+
"@contember/schema": "1.4.0-alpha.1",
|
|
21
|
+
"@contember/schema-definition": "1.4.0-alpha.1",
|
|
22
|
+
"@contember/schema-utils": "1.4.0-alpha.1",
|
|
23
|
+
"fast-deep-equal": "^3.1.3"
|
|
26
24
|
},
|
|
27
25
|
"devDependencies": {
|
|
28
|
-
"@contember/database-tester": "1.
|
|
29
|
-
"@contember/engine-api-tester": "1.
|
|
30
|
-
"@contember/schema-definition": "1.
|
|
26
|
+
"@contember/database-tester": "1.4.0-alpha.1",
|
|
27
|
+
"@contember/engine-api-tester": "1.4.0-alpha.1",
|
|
28
|
+
"@contember/schema-definition": "1.4.0-alpha.1",
|
|
31
29
|
"@graphql-codegen/cli": "^2.6.2",
|
|
32
30
|
"@graphql-codegen/typescript": "^2.5.1",
|
|
33
31
|
"@graphql-codegen/typescript-operations": "^2.4.2",
|
|
@@ -27,8 +27,8 @@ import {
|
|
|
27
27
|
} from './mapper'
|
|
28
28
|
import { Builder } from '@contember/dic'
|
|
29
29
|
import { Acl, Model, Schema } from '@contember/schema'
|
|
30
|
-
import { Client, SelectBuilder as DbSelectBuilder } from '@contember/database'
|
|
31
|
-
import { Providers
|
|
30
|
+
import { Client, DatabaseMetadata, SelectBuilder as DbSelectBuilder } from '@contember/database'
|
|
31
|
+
import { Providers } from '@contember/schema-utils'
|
|
32
32
|
import { PaginatedHasManyExecutionHandler } from './extensions/paginatedHasMany/PaginatedHasManyExecutionHandler'
|
|
33
33
|
import { PaginatedHasManyFieldProvider } from './extensions/paginatedHasMany/PaginatedHasManyFieldProvider'
|
|
34
34
|
import { WhereOptimizer } from './mapper/select/optimizer/WhereOptimizer'
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
|
|
45
45
|
export type ExecutionContainerArgs = {
|
|
46
46
|
schema: Schema & { id: number }
|
|
47
|
-
schemaDatabaseMetadata:
|
|
47
|
+
schemaDatabaseMetadata: DatabaseMetadata
|
|
48
48
|
db: Client
|
|
49
49
|
identityId: string
|
|
50
50
|
identityVariables: Acl.VariablesMap
|
|
@@ -107,13 +107,20 @@ export class ExecutionContainerFactory {
|
|
|
107
107
|
.addService('whereOptimized', ({ schema }) =>
|
|
108
108
|
new WhereOptimizer(schema.model, new ConditionOptimizer()))
|
|
109
109
|
.addService('whereBuilder', ({ joinBuilder, conditionBuilder, pathFactory, whereOptimized, schema }) =>
|
|
110
|
-
new WhereBuilder(
|
|
110
|
+
new WhereBuilder(
|
|
111
|
+
schema.model,
|
|
112
|
+
joinBuilder,
|
|
113
|
+
conditionBuilder,
|
|
114
|
+
pathFactory,
|
|
115
|
+
whereOptimized,
|
|
116
|
+
(schema.settings.content?.useExistsInHasManyFilter ?? schema.settings.useExistsInHasManyFilter) === true,
|
|
117
|
+
))
|
|
111
118
|
.addService('orderByBuilder', ({ joinBuilder, schema }) =>
|
|
112
119
|
new OrderByBuilder(schema.model, joinBuilder))
|
|
113
120
|
.addService('relationFetcher', ({ whereBuilder, orderByBuilder, predicatesInjector, pathFactory }) =>
|
|
114
121
|
new RelationFetcher(whereBuilder, orderByBuilder, predicatesInjector, pathFactory))
|
|
115
|
-
.addService('fieldsVisitorFactory', ({ relationFetcher, predicateFactory,
|
|
116
|
-
new FieldsVisitorFactory(
|
|
122
|
+
.addService('fieldsVisitorFactory', ({ relationFetcher, predicateFactory, schema }) =>
|
|
123
|
+
new FieldsVisitorFactory(relationFetcher, predicateFactory, schema.settings.content ?? {}))
|
|
117
124
|
.addService('metaHandler', ({ whereBuilder, predicateFactory }) =>
|
|
118
125
|
new MetaHandler(whereBuilder, predicateFactory))
|
|
119
126
|
.addService('uniqueWhereExpander', ({ schema }) =>
|
|
@@ -2,7 +2,7 @@ import { GraphQLFieldConfig } from 'graphql'
|
|
|
2
2
|
import { Model } from '@contember/schema'
|
|
3
3
|
|
|
4
4
|
export interface EntityFieldsProvider<ExtensionArg extends object = {}> {
|
|
5
|
-
getFields(entity: Model.Entity, accessibleFields:
|
|
5
|
+
getFields(entity: Model.Entity, accessibleFields: Model.AnyField[]): FieldMap<ExtensionArg>
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export type FieldMap<ExtensionArg extends object> = {
|
|
@@ -11,11 +11,18 @@ export class HasManyToHasOneReducer implements EntityFieldsProvider<HasManyToHas
|
|
|
11
11
|
private readonly visitor: HasManyToHasOneRelationReducerFieldVisitor,
|
|
12
12
|
) {}
|
|
13
13
|
|
|
14
|
-
getFields(entity: Model.Entity,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
|
|
14
|
+
getFields(entity: Model.Entity, accessibleFields: Model.AnyField[]): FieldMap<HasManyToHasOneReducerExtension> {
|
|
15
|
+
const fieldMap: FieldMap<HasManyToHasOneReducerExtension> = {}
|
|
16
|
+
for (const field of accessibleFields) {
|
|
17
|
+
if (field.type !== Model.RelationType.OneHasMany) {
|
|
18
|
+
continue
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (const [name, resultField] of acceptFieldVisitor(this.schema, entity, field, this.visitor)) {
|
|
22
|
+
fieldMap[name] = resultField
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return fieldMap
|
|
19
26
|
}
|
|
20
27
|
}
|
|
21
28
|
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { GraphQLInputObjectType, GraphQLNonNull } from 'graphql'
|
|
2
2
|
import { Acl, Model } from '@contember/schema'
|
|
3
|
-
import {
|
|
4
|
-
aliasAwareResolver,
|
|
5
|
-
EntityTypeProvider,
|
|
6
|
-
FieldAccessVisitor,
|
|
7
|
-
GqlTypeName,
|
|
8
|
-
WhereTypeProvider,
|
|
9
|
-
} from '../../schema'
|
|
3
|
+
import { aliasAwareResolver, EntityTypeProvider, FieldAccessVisitor, GqlTypeName, WhereTypeProvider } from '../../schema'
|
|
10
4
|
import { acceptFieldVisitor } from '@contember/schema-utils'
|
|
11
5
|
import { Authorizator } from '../../acl'
|
|
12
6
|
import { getFieldsForUniqueWhere } from '../../utils'
|
|
13
|
-
import { HasManyToHasOneReducerExtension } from './HasManyToHasOneReducer'
|
|
14
|
-
import {
|
|
7
|
+
import { HasManyToHasOneReducer, HasManyToHasOneReducerExtension } from './HasManyToHasOneReducer'
|
|
8
|
+
import { GraphQLFieldConfig } from 'graphql'
|
|
9
|
+
|
|
10
|
+
type Result = [
|
|
11
|
+
string,
|
|
12
|
+
GraphQLFieldConfig<any, any> & {
|
|
13
|
+
extensions: HasManyToHasOneReducerExtension
|
|
14
|
+
}
|
|
15
|
+
]
|
|
15
16
|
|
|
16
17
|
export class HasManyToHasOneRelationReducerFieldVisitor implements
|
|
17
|
-
Model.ColumnVisitor<
|
|
18
|
-
Model.RelationByTypeVisitor<
|
|
18
|
+
Model.ColumnVisitor<Result[]>,
|
|
19
|
+
Model.RelationByTypeVisitor<Result[]> {
|
|
19
20
|
|
|
20
21
|
constructor(
|
|
21
22
|
private readonly schema: Model.Schema,
|
|
@@ -25,32 +26,32 @@ export class HasManyToHasOneRelationReducerFieldVisitor implements
|
|
|
25
26
|
) {}
|
|
26
27
|
|
|
27
28
|
public visitColumn() {
|
|
28
|
-
return
|
|
29
|
+
return []
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
public visitOneHasOneOwning() {
|
|
32
|
-
return
|
|
33
|
+
return []
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
public visitOneHasOneInverse() {
|
|
36
|
-
return
|
|
37
|
+
return []
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
public visitManyHasOne() {
|
|
40
|
-
return
|
|
41
|
+
return []
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
public visitManyHasManyInverse() {
|
|
44
|
-
return
|
|
45
|
+
return []
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
public visitManyHasManyOwning() {
|
|
48
|
-
return
|
|
49
|
+
return []
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
public visitOneHasMany({ entity, targetEntity, targetRelation, relation }: Model.OneHasManyContext) {
|
|
52
53
|
if (!targetRelation) {
|
|
53
|
-
return
|
|
54
|
+
return []
|
|
54
55
|
}
|
|
55
56
|
const uniqueConstraints = getFieldsForUniqueWhere(this.schema, targetEntity)
|
|
56
57
|
const composedUnique = uniqueConstraints
|
|
@@ -63,6 +64,8 @@ export class HasManyToHasOneRelationReducerFieldVisitor implements
|
|
|
63
64
|
.map(fields => fields[0])
|
|
64
65
|
.filter(it => it !== targetRelation.name)
|
|
65
66
|
|
|
67
|
+
|
|
68
|
+
const existing = new Set<string>()
|
|
66
69
|
return [...composedUnique, ...singleUnique]
|
|
67
70
|
.filter(field =>
|
|
68
71
|
acceptFieldVisitor(
|
|
@@ -72,7 +75,11 @@ export class HasManyToHasOneRelationReducerFieldVisitor implements
|
|
|
72
75
|
new FieldAccessVisitor(Acl.Operation.read, this.authorizator),
|
|
73
76
|
),
|
|
74
77
|
)
|
|
75
|
-
.
|
|
78
|
+
.map<Result | null>(fieldName => {
|
|
79
|
+
if (existing.has(fieldName)) {
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
existing.add(fieldName)
|
|
76
83
|
const graphQlName = relation.name + GqlTypeName`By${fieldName}`
|
|
77
84
|
const uniqueWhere: GraphQLInputObjectType = new GraphQLInputObjectType({
|
|
78
85
|
//todo this can be simplified to ${targetEntity.name}By${fieldName}, but singleton must be used
|
|
@@ -84,12 +91,13 @@ export class HasManyToHasOneRelationReducerFieldVisitor implements
|
|
|
84
91
|
|
|
85
92
|
const entityType = this.entityTypeProvider.getEntity(targetEntity.name)
|
|
86
93
|
|
|
87
|
-
return
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
return [
|
|
95
|
+
graphQlName,
|
|
96
|
+
{
|
|
90
97
|
type: entityType,
|
|
91
98
|
extensions: {
|
|
92
99
|
relationName: relation.name,
|
|
100
|
+
extensionKey: HasManyToHasOneReducer.extensionName,
|
|
93
101
|
},
|
|
94
102
|
args: {
|
|
95
103
|
by: { type: new GraphQLNonNull(uniqueWhere) },
|
|
@@ -97,7 +105,8 @@ export class HasManyToHasOneRelationReducerFieldVisitor implements
|
|
|
97
105
|
},
|
|
98
106
|
resolve: aliasAwareResolver,
|
|
99
107
|
},
|
|
100
|
-
|
|
101
|
-
}
|
|
108
|
+
]
|
|
109
|
+
})
|
|
110
|
+
.filter((it): it is Result => it !== null)
|
|
102
111
|
}
|
|
103
112
|
}
|
|
@@ -8,11 +8,14 @@ export class PaginatedHasManyFieldProvider implements EntityFieldsProvider<Pagin
|
|
|
8
8
|
|
|
9
9
|
constructor(private readonly schema: Model.Schema, private readonly visitor: PaginatedHasManyFieldProviderVisitor) {}
|
|
10
10
|
|
|
11
|
-
getFields(entity: Model.Entity,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
|
|
11
|
+
getFields(entity: Model.Entity, accessibleFields: Model.AnyField[]): FieldMap<PaginatedHasManyFieldProviderExtension> {
|
|
12
|
+
const fields: FieldMap<PaginatedHasManyFieldProviderExtension> = {}
|
|
13
|
+
for (const field of accessibleFields) {
|
|
14
|
+
for (const [name, fieldConfig] of acceptFieldVisitor(this.schema, entity, field, this.visitor)) {
|
|
15
|
+
fields[name] = fieldConfig
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return fields
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { Model } from '@contember/schema'
|
|
2
|
-
import {
|
|
3
|
-
import { PaginatedHasManyFieldProviderExtension } from './PaginatedHasManyFieldProvider'
|
|
2
|
+
import { PaginatedHasManyFieldProvider, PaginatedHasManyFieldProviderExtension } from './PaginatedHasManyFieldProvider'
|
|
4
3
|
import { capitalizeFirstLetter } from '../../utils'
|
|
5
4
|
import { PaginatedFieldConfigFactory } from '../../schema/PaginatedFieldConfigFactory'
|
|
6
5
|
import { aliasAwareResolver } from '../../schema'
|
|
6
|
+
import { GraphQLFieldConfig } from 'graphql'
|
|
7
|
+
|
|
8
|
+
type Result = [
|
|
9
|
+
string,
|
|
10
|
+
GraphQLFieldConfig<any, any> & {
|
|
11
|
+
extensions: PaginatedHasManyFieldProviderExtension
|
|
12
|
+
}
|
|
13
|
+
]
|
|
7
14
|
|
|
8
15
|
export class PaginatedHasManyFieldProviderVisitor implements
|
|
9
|
-
Model.ColumnVisitor<
|
|
10
|
-
Model.RelationByTypeVisitor<
|
|
16
|
+
Model.ColumnVisitor<Result[]>,
|
|
17
|
+
Model.RelationByTypeVisitor<Result[]> {
|
|
11
18
|
|
|
12
19
|
constructor(private readonly paginatedFieldFactory: PaginatedFieldConfigFactory) {}
|
|
13
20
|
|
|
@@ -23,31 +30,35 @@ export class PaginatedHasManyFieldProviderVisitor implements
|
|
|
23
30
|
return this.createField(targetEntity, relation)
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
private createField(entity: Model.Entity, relation: Model.Relation):
|
|
27
|
-
return
|
|
28
|
-
[
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
private createField(entity: Model.Entity, relation: Model.Relation): Result[] {
|
|
34
|
+
return [
|
|
35
|
+
[
|
|
36
|
+
`paginate${capitalizeFirstLetter(relation.name)}`,
|
|
37
|
+
{
|
|
38
|
+
...this.paginatedFieldFactory.createFieldConfig(entity),
|
|
39
|
+
extensions: {
|
|
40
|
+
relationName: relation.name,
|
|
41
|
+
extensionKey: PaginatedHasManyFieldProvider.extensionName,
|
|
42
|
+
},
|
|
43
|
+
resolve: aliasAwareResolver,
|
|
32
44
|
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
45
|
+
],
|
|
46
|
+
]
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
visitColumn() {
|
|
39
|
-
return
|
|
50
|
+
return []
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
visitManyHasOne() {
|
|
43
|
-
return
|
|
54
|
+
return []
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
visitOneHasOneInverse() {
|
|
47
|
-
return
|
|
58
|
+
return []
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
visitOneHasOneOwning() {
|
|
51
|
-
return
|
|
62
|
+
return []
|
|
52
63
|
}
|
|
53
64
|
}
|
|
@@ -1,21 +1,210 @@
|
|
|
1
|
-
import { IExecutableSchemaDefinition } from '@graphql-tools/schema'
|
|
2
|
-
import schema from './content-schema.graphql'
|
|
3
1
|
import * as ContentSchema from './content-schema.types'
|
|
4
2
|
import { IntrospectionSchemaFactory } from './IntrospectionSchemaFactory'
|
|
3
|
+
import { JSONType } from '@contember/graphql-utils'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import {
|
|
6
|
+
GraphQLBoolean,
|
|
7
|
+
GraphQLEnumType,
|
|
8
|
+
GraphQLFieldResolver,
|
|
9
|
+
GraphQLInt,
|
|
10
|
+
GraphQLInterfaceType,
|
|
11
|
+
GraphQLList,
|
|
12
|
+
GraphQLNonNull,
|
|
13
|
+
GraphQLObjectType,
|
|
14
|
+
GraphQLSchema,
|
|
15
|
+
GraphQLSchemaConfig,
|
|
16
|
+
GraphQLString,
|
|
17
|
+
GraphQLUnionType,
|
|
18
|
+
} from 'graphql'
|
|
19
|
+
|
|
20
|
+
const _RuleMessage = new GraphQLObjectType({
|
|
21
|
+
name: '_RuleMessage',
|
|
22
|
+
fields: {
|
|
23
|
+
text: { type: GraphQLString },
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const _ValidatorArgument = new GraphQLObjectType({
|
|
28
|
+
name: '_ValidatorArgument',
|
|
29
|
+
fields: {
|
|
30
|
+
validator: { type: new GraphQLNonNull(GraphQLInt) },
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const _PathArgument = new GraphQLObjectType({
|
|
35
|
+
name: '_PathArgument',
|
|
36
|
+
fields: {
|
|
37
|
+
path: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString))) },
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const _LiteralArgument = new GraphQLObjectType({
|
|
42
|
+
name: '_LiteralArgument',
|
|
43
|
+
fields: {
|
|
44
|
+
value: { type: JSONType },
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const _Argument = new GraphQLUnionType({
|
|
49
|
+
name: '_Argument',
|
|
50
|
+
types: [_ValidatorArgument, _PathArgument, _LiteralArgument],
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const _Validator = new GraphQLObjectType({
|
|
54
|
+
name: '_Validator',
|
|
55
|
+
fields: {
|
|
56
|
+
operation: { type: new GraphQLNonNull(GraphQLString) },
|
|
57
|
+
arguments: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Argument))) },
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const _Rule = new GraphQLObjectType({
|
|
62
|
+
name: '_Rule',
|
|
63
|
+
fields: {
|
|
64
|
+
message: { type: _RuleMessage },
|
|
65
|
+
validator: { type: new GraphQLNonNull(GraphQLInt) },
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const _FieldInterface = new GraphQLInterfaceType({
|
|
70
|
+
name: '_Field',
|
|
71
|
+
fields: {
|
|
72
|
+
name: { type: new GraphQLNonNull(GraphQLString) },
|
|
73
|
+
type: { type: new GraphQLNonNull(GraphQLString) },
|
|
74
|
+
nullable: { type: GraphQLBoolean },
|
|
75
|
+
rules: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Rule))) },
|
|
76
|
+
validators: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Validator))) },
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const _OrderByDirection = new GraphQLEnumType({
|
|
81
|
+
name: '_OrderByDirection',
|
|
82
|
+
values: {
|
|
83
|
+
asc: {},
|
|
84
|
+
desc: {},
|
|
85
|
+
},
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const _OrderBy = new GraphQLObjectType({
|
|
89
|
+
name: '_OrderBy',
|
|
90
|
+
fields: {
|
|
91
|
+
path: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString))) },
|
|
92
|
+
direction: { type: new GraphQLNonNull(_OrderByDirection) },
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const _OnDeleteBehaviour = new GraphQLEnumType({
|
|
97
|
+
name: '_OnDeleteBehaviour',
|
|
98
|
+
values: {
|
|
99
|
+
restrict: {},
|
|
100
|
+
cascade: {},
|
|
101
|
+
setNull: {},
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const _RelationSide = new GraphQLEnumType({
|
|
106
|
+
name: '_RelationSide',
|
|
107
|
+
values: {
|
|
108
|
+
owning: {},
|
|
109
|
+
inverse: {},
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const _Relation = new GraphQLObjectType({
|
|
114
|
+
name: '_Relation',
|
|
115
|
+
interfaces: [_FieldInterface],
|
|
116
|
+
fields: {
|
|
117
|
+
name: { type: new GraphQLNonNull(GraphQLString) },
|
|
118
|
+
type: { type: new GraphQLNonNull(GraphQLString) },
|
|
119
|
+
side: { type: new GraphQLNonNull(_RelationSide) },
|
|
120
|
+
targetEntity: { type: new GraphQLNonNull(GraphQLString) },
|
|
121
|
+
ownedBy: { type: GraphQLString },
|
|
122
|
+
inversedBy: { type: GraphQLString },
|
|
123
|
+
nullable: { type: GraphQLBoolean },
|
|
124
|
+
onDelete: { type: _OnDeleteBehaviour },
|
|
125
|
+
orphanRemoval: { type: GraphQLBoolean },
|
|
126
|
+
orderBy: { type: new GraphQLList(new GraphQLNonNull(_OrderBy)) },
|
|
127
|
+
rules: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Rule))) },
|
|
128
|
+
validators: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Validator))) },
|
|
129
|
+
},
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const _Column = new GraphQLObjectType({
|
|
133
|
+
name: '_Column',
|
|
134
|
+
interfaces: [_FieldInterface],
|
|
135
|
+
fields: {
|
|
136
|
+
name: { type: new GraphQLNonNull(GraphQLString) },
|
|
137
|
+
type: { type: new GraphQLNonNull(GraphQLString) },
|
|
138
|
+
enumName: { type: GraphQLString },
|
|
139
|
+
defaultValue: { type: JSONType },
|
|
140
|
+
nullable: { type: new GraphQLNonNull(GraphQLBoolean) },
|
|
141
|
+
rules: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Rule))) },
|
|
142
|
+
validators: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Validator))) },
|
|
143
|
+
},
|
|
144
|
+
})
|
|
8
145
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
146
|
+
const _UniqueConstraint = new GraphQLObjectType({
|
|
147
|
+
name: '_UniqueConstraint',
|
|
148
|
+
fields: {
|
|
149
|
+
fields: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString))) },
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const _Entity = new GraphQLObjectType({
|
|
154
|
+
name: '_Entity',
|
|
155
|
+
fields: {
|
|
156
|
+
name: { type: new GraphQLNonNull(GraphQLString) },
|
|
157
|
+
customPrimaryAllowed: { type: new GraphQLNonNull(GraphQLBoolean) },
|
|
158
|
+
fields: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_FieldInterface))) },
|
|
159
|
+
unique: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_UniqueConstraint))) },
|
|
160
|
+
},
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const _Enum = new GraphQLObjectType({
|
|
164
|
+
name: '_Enum',
|
|
165
|
+
fields: {
|
|
166
|
+
name: { type: new GraphQLNonNull(GraphQLString) },
|
|
167
|
+
values: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString))) },
|
|
168
|
+
},
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
const _Schema = new GraphQLObjectType({
|
|
172
|
+
name: '_Schema',
|
|
173
|
+
fields: {
|
|
174
|
+
enums: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Enum))) },
|
|
175
|
+
entities: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(_Entity))) },
|
|
176
|
+
},
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
const createSchemaConfig = (resolver?: GraphQLFieldResolver<any, any>): GraphQLSchemaConfig => {
|
|
181
|
+
return {
|
|
182
|
+
query: new GraphQLObjectType({
|
|
183
|
+
name: 'Query',
|
|
184
|
+
fields: {
|
|
185
|
+
schema: {
|
|
186
|
+
type: _Schema,
|
|
187
|
+
resolve: resolver,
|
|
17
188
|
},
|
|
18
189
|
},
|
|
19
|
-
}
|
|
190
|
+
}),
|
|
191
|
+
types: [_Column, _Relation],
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
export default new GraphQLSchema(createSchemaConfig())
|
|
197
|
+
|
|
198
|
+
export class IntrospectionSchemaDefinitionFactory {
|
|
199
|
+
constructor(private readonly introspectionSchemaFactory: IntrospectionSchemaFactory) {}
|
|
200
|
+
|
|
201
|
+
public create(): GraphQLSchema {
|
|
202
|
+
return new GraphQLSchema(this.createConfig())
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public createConfig(): GraphQLSchemaConfig {
|
|
206
|
+
return createSchemaConfig((): ContentSchema._Schema => {
|
|
207
|
+
return this.introspectionSchemaFactory.create()
|
|
208
|
+
})
|
|
20
209
|
}
|
|
21
210
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { default as ContentSchema } from './content-schema.graphql'
|
|
2
1
|
export * as ContentSchemaTypes from './content-schema.types'
|
|
3
|
-
export
|
|
2
|
+
export { IntrospectionSchemaDefinitionFactory, default as ContentSchema } from './IntrospectionSchemaDefinitionFactory'
|
|
4
3
|
export * from './IntrospectionSchemaFactory'
|
package/src/mapper/ErrorUtils.ts
CHANGED
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
import * as Database from '@contember/database'
|
|
12
12
|
import { UniqueWhereError } from '../inputProcessing'
|
|
13
13
|
import { Model } from '@contember/schema'
|
|
14
|
-
import { acceptFieldVisitor,
|
|
14
|
+
import { acceptFieldVisitor, tryGetColumnName } from '@contember/schema-utils'
|
|
15
15
|
import { logger } from '@contember/logger'
|
|
16
|
+
import { DatabaseMetadata } from '@contember/database'
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
type UniqueConstraintResult = {
|
|
@@ -22,8 +23,8 @@ type UniqueConstraintResult = {
|
|
|
22
23
|
|
|
23
24
|
const getEntityByTableName = (model: Model.Schema, tableName: string) => Object.values(model.entities).find(it => it.tableName === tableName)
|
|
24
25
|
|
|
25
|
-
const findUniqueConstraint = (model: Model.Schema, databaseMetadata:
|
|
26
|
-
const constraint = databaseMetadata.
|
|
26
|
+
const findUniqueConstraint = (model: Model.Schema, databaseMetadata: DatabaseMetadata, tableName: string, constraintName: string): UniqueConstraintResult | null => {
|
|
27
|
+
const constraint = databaseMetadata.uniqueConstraints.filter({ tableName, constraintName }).first()
|
|
27
28
|
if (!constraint) {
|
|
28
29
|
return null
|
|
29
30
|
}
|
|
@@ -50,8 +51,8 @@ type RelationInfo = {
|
|
|
50
51
|
targetEntity: Model.Entity
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
const findForeignConstraint = (model: Model.Schema, databaseMetadata:
|
|
54
|
-
const constraint = databaseMetadata.
|
|
54
|
+
const findForeignConstraint = (model: Model.Schema, databaseMetadata: DatabaseMetadata, tableName: string, constraintName: string): RelationInfo | null => {
|
|
55
|
+
const constraint = databaseMetadata.foreignKeys.filter({ fromTable: tableName, constraintName }).first()
|
|
55
56
|
if (!constraint) {
|
|
56
57
|
return null
|
|
57
58
|
}
|
|
@@ -88,7 +89,7 @@ const findForeignConstraint = (model: Model.Schema, databaseMetadata: SchemaData
|
|
|
88
89
|
|
|
89
90
|
export const convertError = (
|
|
90
91
|
schema: Model.Schema,
|
|
91
|
-
databaseMetadata:
|
|
92
|
+
databaseMetadata: DatabaseMetadata,
|
|
92
93
|
e: any,
|
|
93
94
|
): MutationResult => {
|
|
94
95
|
|
|
@@ -140,7 +141,7 @@ export const convertError = (
|
|
|
140
141
|
throw e
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
export const tryMutation = async (schema: Model.Schema, databaseMetadata:
|
|
144
|
+
export const tryMutation = async (schema: Model.Schema, databaseMetadata: DatabaseMetadata, cb: () => Promise<MutationResultList>): Promise<MutationResultList> => {
|
|
144
145
|
try {
|
|
145
146
|
return await cb()
|
|
146
147
|
} catch (e) {
|
package/src/mapper/Mapper.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Input, Model } from '@contember/schema'
|
|
2
|
-
import { acceptFieldVisitor, getColumnName
|
|
2
|
+
import { acceptFieldVisitor, getColumnName } from '@contember/schema-utils'
|
|
3
3
|
import {
|
|
4
4
|
OrderByHelper,
|
|
5
5
|
PathFactory,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
SelectResultObject,
|
|
11
11
|
WhereBuilder,
|
|
12
12
|
} from './select'
|
|
13
|
-
import { Client, Connection, ConstraintHelper, SelectBuilder } from '@contember/database'
|
|
13
|
+
import { Client, Connection, ConstraintHelper, DatabaseMetadata, SelectBuilder } from '@contember/database'
|
|
14
14
|
import { PredicatesInjector } from '../acl'
|
|
15
15
|
import { JunctionTableManager } from './JunctionTableManager'
|
|
16
16
|
import { DeletedEntitiesStorage, DeleteExecutor } from './delete'
|
|
@@ -38,7 +38,7 @@ export class Mapper<ConnectionType extends Connection.ConnectionLike = Connectio
|
|
|
38
38
|
public readonly identityId: string,
|
|
39
39
|
public readonly transactionId: string,
|
|
40
40
|
private readonly schema: Model.Schema,
|
|
41
|
-
private readonly schemaDatabaseMetadata:
|
|
41
|
+
private readonly schemaDatabaseMetadata: DatabaseMetadata,
|
|
42
42
|
private readonly predicatesInjector: PredicatesInjector,
|
|
43
43
|
private readonly selectBuilderFactory: SelectBuilderFactory,
|
|
44
44
|
private readonly uniqueWhereExpander: UniqueWhereExpander,
|
|
@@ -49,7 +49,7 @@ export class Mapper<ConnectionType extends Connection.ConnectionLike = Connectio
|
|
|
49
49
|
private readonly inserter: Inserter,
|
|
50
50
|
private readonly pathFactory: PathFactory,
|
|
51
51
|
) {
|
|
52
|
-
this.constraintHelper = new ConstraintHelper(db)
|
|
52
|
+
this.constraintHelper = new ConstraintHelper(db, this.schemaDatabaseMetadata)
|
|
53
53
|
this.eventManager = new EventManager(this)
|
|
54
54
|
}
|
|
55
55
|
|