sasat 0.17.4 → 0.18.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/lib/db/sql/createTable/createTableParser.js +1 -1
- package/lib/generator/ts/code/factory.d.ts +1 -1
- package/lib/generator/ts/code/node/type/intersectionType.d.ts +2 -3
- package/lib/generator/ts/db/generatedRepositoryGenerator.js +12 -13
- package/lib/generator/ts/fieldGenerator.js +1 -1
- package/lib/generator/ts/gql/queryGenerator.js +27 -18
- package/lib/generator/ts/gql/resolverGenerator.js +11 -10
- package/lib/generator/ts/gql/typeDefGenerator.js +1 -1
- package/lib/generator/ts/relationMapGenerator.d.ts +1 -0
- package/lib/generator/ts/relationMapGenerator.js +14 -11
- package/lib/generator/ts/staticFiles.js +6 -5
- package/lib/generator/ts/tsValueString.js +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/migration/creators/tableCreator.d.ts +5 -1
- package/lib/migration/creators/tableCreator.js +11 -0
- package/lib/migration/data/{gqlOption.d.ts → GQLOption.d.ts} +8 -3
- package/lib/migration/data/{gqlOption.js → GQLOption.js} +5 -0
- package/lib/migration/front/tableMigrator.d.ts +6 -1
- package/lib/migration/front/tableMigrator.js +14 -0
- package/lib/migration/serializable/table.d.ts +4 -2
- package/lib/migration/serializable/table.js +4 -1
- package/lib/migration/serialized/serializedStore.d.ts +2 -2
- package/lib/parser/node/entityNode.d.ts +1 -0
- package/lib/parser/node/entityNode.js +10 -4
- package/lib/parser/node/gql/queryNode.d.ts +3 -1
- package/lib/parser/node/gql/queryNode.js +2 -1
- package/lib/parser/node/gql/typeDefNode.d.ts +1 -1
- package/lib/parser/node/gql/typeDefNode.js +2 -1
- package/lib/parser/node/relationNode.d.ts +17 -7
- package/lib/parser/node/relationNode.js +17 -11
- package/lib/parser/node/repositoryNode.d.ts +2 -0
- package/lib/parser/node/repositoryNode.js +6 -5
- package/lib/parser/node/rootNode.js +1 -1
- package/lib/parser/node/typeNode.d.ts +1 -1
- package/lib/parser/node/typeNode.js +1 -1
- package/lib/parser/nodeFactory/mutationNodeFactory.js +2 -0
- package/lib/parser/nodeFactory/queryNodeFactory.d.ts +2 -1
- package/lib/parser/nodeFactory/queryNodeFactory.js +13 -4
- package/lib/runtime/dsl/factory.d.ts +2 -2
- package/lib/runtime/dsl/factory.js +2 -1
- package/lib/runtime/dsl/query/query.d.ts +2 -0
- package/lib/runtime/dsl/query/sql/queryToSql.js +9 -1
- package/lib/runtime/sasatDBDatasource.d.ts +12 -18
- package/lib/runtime/sql/runQuery.d.ts +2 -8
- package/lib/runtime/sql/runQuery.js +7 -3
- package/lib/runtime/util.d.ts +1 -0
- package/lib/runtime/util.js +1 -0
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { TokenKind } from './lexer/lexer.js';
|
|
|
2
2
|
import { camelize } from '../../../util/stringUtil.js';
|
|
3
3
|
import { columnTypeToGqlPrimitive } from '../../../generator/gql/columnToGqlType.js';
|
|
4
4
|
import { GqlPrimitive } from '../../../generator/gql/types.js';
|
|
5
|
-
import { getDefaultGqlOption } from '../../../migration/data/
|
|
5
|
+
import { getDefaultGqlOption } from '../../../migration/data/GQLOption.js';
|
|
6
6
|
const splitArray = (array, callback) => {
|
|
7
7
|
const indexes = [];
|
|
8
8
|
array.forEach((it, i) => {
|
|
@@ -45,7 +45,7 @@ export declare const tsg: {
|
|
|
45
45
|
methodModifiers: () => MethodModifiers;
|
|
46
46
|
propertyModifiers: () => PropertyModifiers;
|
|
47
47
|
arrayType: (type: import("./node/type/type.js").TsType) => ArrayType;
|
|
48
|
-
intersectionType: (...args: (
|
|
48
|
+
intersectionType: (...args: import("./node/type/type.js").TsType[]) => IntersectionType;
|
|
49
49
|
unionType: (types: import("./node/type/type.js").TsType[]) => UnionType;
|
|
50
50
|
typeAlias: (alias: string, type: import("./node/type/type.js").TsType) => TypeAliasDeclaration;
|
|
51
51
|
typeLiteral: (properties?: PropertySignature[] | undefined) => TypeLiteral;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { TsCode } from '../../abstruct/tsCode.js';
|
|
2
|
-
import {
|
|
3
|
-
import { TypeReference } from './typeReference.js';
|
|
2
|
+
import { TsType } from "./type.js";
|
|
4
3
|
export declare class IntersectionType extends TsCode {
|
|
5
4
|
private readonly types;
|
|
6
|
-
constructor(...types: Array<
|
|
5
|
+
constructor(...types: Array<TsType>);
|
|
7
6
|
protected toTsString(): string;
|
|
8
7
|
}
|
|
@@ -20,7 +20,7 @@ export class GeneratedRepositoryGenerator {
|
|
|
20
20
|
generate() {
|
|
21
21
|
const node = this.node;
|
|
22
22
|
const entityPath = Directory.entityPath(Directory.paths.generatedDataSource.db, node.entityName);
|
|
23
|
-
return new TsFile(new Class(node.entityName.generatedDataSourceName())
|
|
23
|
+
return new TsFile(tsg.typeAlias('QueryResult', tsg.intersectionType(tsg.typeRef('Partial', [tsg.typeRef(node.entityName.entityWithRelationTypeName()).importFrom(Directory.generatedPath(Directory.paths.generatedDataSource.db, 'relationMap'))]), node.entityName.identifiableTypeReference(Directory.paths.generatedDataSource.db))), new Class(node.entityName.generatedDataSourceName())
|
|
24
24
|
.export()
|
|
25
25
|
.abstract()
|
|
26
26
|
.extends(new ExtendsClause(tsg.typeRef('BaseDBDataSource', [
|
|
@@ -32,6 +32,7 @@ export class GeneratedRepositoryGenerator {
|
|
|
32
32
|
.typeRef(node.entityName.identifiableInterfaceName())
|
|
33
33
|
.importFrom(entityPath),
|
|
34
34
|
node.entityName.fieldTypeRef(Directory.paths.generatedDataSource.db),
|
|
35
|
+
tsg.typeRef('QueryResult')
|
|
35
36
|
])).addImport(['BaseDBDataSource'], Directory.basePath(Directory.paths.generatedDataSource.db, 'baseDBDataSource')))
|
|
36
37
|
.addProperty(...this.properties(node))
|
|
37
38
|
.addMethod(this.getDefaultValueMethod(node), ...this.findMethods(node))).disableEsLint();
|
|
@@ -99,24 +100,22 @@ export class GeneratedRepositoryGenerator {
|
|
|
99
100
|
tsg.variable('const', 'tableName', tsg.identifier('fields?.tableAlias || "t0"')),
|
|
100
101
|
tsg.return(tsg
|
|
101
102
|
.identifier(it.returnType.isArray ? 'this.find' : 'this.first')
|
|
102
|
-
.call(tsg.identifier('fields'), tsg.object().addProperties(tsg.propertyAssign('where',
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.property('and')
|
|
107
|
-
.call(...exps))), tsg.identifier('context'))),
|
|
103
|
+
.call(tsg.identifier('fields'), tsg.object().addProperties(tsg.spreadAssign(tsg.identifier('options')), tsg.propertyAssign('where', qExpr
|
|
104
|
+
.property('conditions')
|
|
105
|
+
.property('and')
|
|
106
|
+
.call(...exps, tsg.identifier('options?').property('where')))), tsg.identifier('context'))),
|
|
108
107
|
];
|
|
109
|
-
const returnType = tsg
|
|
110
|
-
.typeRef('EntityResult', [
|
|
111
|
-
tsg.typeRef(node.entityName.name),
|
|
112
|
-
tsg.typeRef(node.entityName.identifiableInterfaceName()),
|
|
113
|
-
])
|
|
114
|
-
.importFrom('sasat');
|
|
108
|
+
const returnType = tsg.typeRef('QueryResult');
|
|
115
109
|
return new MethodDeclaration(it.name, [
|
|
116
110
|
...it.params.map(it => new Parameter(it.name, it.type.toTsType())),
|
|
117
111
|
new Parameter(`fields?`, tsg
|
|
118
112
|
.typeRef(`${node.entityName}Fields`)
|
|
119
113
|
.importFrom(Directory.generatedPath(Directory.paths.generatedDataSource.db, 'fields'))),
|
|
114
|
+
tsg.parameter('options?', it.returnType.isArray ? tsg.typeRef('QueryOptions').importFrom('sasat')
|
|
115
|
+
: tsg.typeRef('Omit', [
|
|
116
|
+
tsg.typeRef('QueryOptions').importFrom('sasat'),
|
|
117
|
+
tsg.typeRef('"offset" | "limit" | "sort"'),
|
|
118
|
+
])),
|
|
120
119
|
tsg.parameter('context?', tsg
|
|
121
120
|
.typeRef('GQLContext')
|
|
122
121
|
.importFrom(Directory.basePath(Directory.paths.generatedDataSource.db, 'context'))),
|
|
@@ -15,7 +15,7 @@ export class FieldGenerator {
|
|
|
15
15
|
.typeRef(`keyof ${entity.entityName}`)
|
|
16
16
|
.addImport([entity.entityName.name], Directory.entityPath(Directory.paths.generated, entity.entityName)))),
|
|
17
17
|
tsg.propertySignature('relations?', tsg.typeLiteral([
|
|
18
|
-
...entity.relations.map(it => tsg.propertySignature(`${it.refPropertyName()}?`, tsg.typeRef(`${it.
|
|
18
|
+
...entity.relations.map(it => tsg.propertySignature(`${it.refPropertyName()}?`, tsg.typeRef(`${it.to.entityName}Fields`))),
|
|
19
19
|
...entity
|
|
20
20
|
.findReferencedRelations()
|
|
21
21
|
.map(it => tsg.propertySignature(`${it.referencedByPropertyName()}?`, tsg.typeRef(`${it.parent.entityName}Fields`))),
|
|
@@ -12,7 +12,7 @@ export class QueryGenerator {
|
|
|
12
12
|
static createParams(node, query) {
|
|
13
13
|
const context = tsg.parameter('context', tsg.typeRef('GQLContext').importFrom('../context'));
|
|
14
14
|
const resolveInfo = tsg.parameter('info', tsg.typeRef('GraphQLResolveInfo'));
|
|
15
|
-
if (query.queryParams.length === 0)
|
|
15
|
+
if (query.queryParams.length === 0 || query.listType === 'all')
|
|
16
16
|
return [
|
|
17
17
|
tsg.parameter('_1', tsg.typeRef('unknown')),
|
|
18
18
|
tsg.parameter('_2', tsg.typeRef('unknown')),
|
|
@@ -23,7 +23,7 @@ export class QueryGenerator {
|
|
|
23
23
|
return [
|
|
24
24
|
tsg.parameter('_1', tsg.typeRef('unknown')),
|
|
25
25
|
tsg.parameter('params', tsg.typeLiteral([
|
|
26
|
-
tsg.propertySignature('option', query.queryParams[0].type.toTsType(),
|
|
26
|
+
tsg.propertySignature('option', query.queryParams[0].type.toTsType(), false, false),
|
|
27
27
|
])),
|
|
28
28
|
context,
|
|
29
29
|
resolveInfo,
|
|
@@ -49,28 +49,37 @@ export class QueryGenerator {
|
|
|
49
49
|
.identifier('gqlResolveInfoToField')
|
|
50
50
|
.importFrom('sasat')
|
|
51
51
|
.call(tsg.identifier('info'))
|
|
52
|
-
.as(node.entityName.fieldTypeRef(Directory.paths.generated)), tsg.identifier('context'))));
|
|
52
|
+
.as(node.entityName.fieldTypeRef(Directory.paths.generated)), tsg.identifier('undefined'), tsg.identifier('context'))));
|
|
53
53
|
}
|
|
54
54
|
listQuery(node, query) {
|
|
55
55
|
const fields = tsg.identifier('fields');
|
|
56
|
+
const option = tsg.identifier('option');
|
|
56
57
|
const ds = tsg.new(tsg
|
|
57
58
|
.identifier(node.entityName.dataSourceName())
|
|
58
59
|
.importFrom(Directory.dbDataSourcePath(Directory.paths.generated, node.entityName)));
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
const constInfo = tsg.variable('const', fields, tsg
|
|
61
|
+
.identifier('gqlResolveInfoToField')
|
|
62
|
+
.importFrom('sasat')
|
|
63
|
+
.call(tsg.identifier('info'))
|
|
64
|
+
.as(node.entityName.fieldTypeRef(Directory.paths.generated)));
|
|
65
|
+
const all = () => {
|
|
66
|
+
return [
|
|
67
|
+
constInfo,
|
|
68
|
+
tsg.return(ds
|
|
69
|
+
.property(query.repoMethodName)
|
|
70
|
+
.call(fields, tsg.identifier('undefined'), tsg.identifier('context'))),
|
|
71
|
+
];
|
|
72
|
+
};
|
|
73
|
+
const pageable = () => {
|
|
74
|
+
return [
|
|
75
|
+
constInfo,
|
|
76
|
+
tsg.variable('const', tsg.identifier('{ option }'), tsg.identifier('params')),
|
|
77
|
+
tsg.return(ds
|
|
78
|
+
.property('findPageable')
|
|
79
|
+
.call(tsg.object(tsg.propertyAssign('numberOfItem', option.property('numberOfItem')), tsg.propertyAssign('offset', option.property('offset'))), fields, tsg.identifier('undefined'), tsg.identifier('context'))),
|
|
80
|
+
];
|
|
81
|
+
};
|
|
82
|
+
return tsg.propertyAssign(query.queryName, tsg.arrowFunc(QueryGenerator.createParams(node, query), undefined, tsg.block(...(query.listType === 'paging' ? pageable() : all()))));
|
|
74
83
|
}
|
|
75
84
|
entity(node) {
|
|
76
85
|
return node.queries.map(it => (it.isList ? this.listQuery : this.query)(node, it));
|
|
@@ -9,8 +9,9 @@ import { FindMethodNode } from '../../../parser/node/findMethod.js';
|
|
|
9
9
|
export class ResolverGenerator {
|
|
10
10
|
constructor() {
|
|
11
11
|
this.entityResolver = (node) => {
|
|
12
|
-
return tsg.propertyAssign(node.entityName.name, tsg.object(...node.relations.map(relation => this.relationProperty(relation)), ...node
|
|
12
|
+
return tsg.propertyAssign(node.entityName.name, tsg.object(...node.relations.filter(it => it.to.gqlOption.enabled).map(relation => this.relationProperty(relation)), ...node
|
|
13
13
|
.findReferencedRelations()
|
|
14
|
+
.filter(it => it.from.gqlOption.enabled)
|
|
14
15
|
.map(relation => this.referencedByProperty(relation))));
|
|
15
16
|
};
|
|
16
17
|
}
|
|
@@ -23,27 +24,27 @@ export class ResolverGenerator {
|
|
|
23
24
|
.importFrom('./relationMap')),
|
|
24
25
|
], undefined, tsg.block(tsg.if(tsg.binary(tsg.identifier(paramName).property(propertyName), '!==', tsg.identifier('undefined')), tsg.return(tsg.identifier(paramName).property(propertyName))), tsg.return(tsg
|
|
25
26
|
.new(tsg
|
|
26
|
-
.identifier(relation.
|
|
27
|
-
.importFrom(Directory.dbDataSourcePath(Directory.paths.generated, relation.
|
|
28
|
-
.property(FindMethodNode.paramsToName(relation.
|
|
27
|
+
.identifier(relation.to.entityName.dataSourceName())
|
|
28
|
+
.importFrom(Directory.dbDataSourcePath(Directory.paths.generated, relation.to.entityName)))
|
|
29
|
+
.property(FindMethodNode.paramsToName(relation.to.field))
|
|
29
30
|
.call(tsg
|
|
30
31
|
.identifier(paramName)
|
|
31
|
-
.property(relation.
|
|
32
|
+
.property(relation.from.field)
|
|
32
33
|
.nonNull())))));
|
|
33
34
|
}
|
|
34
35
|
referencedByProperty(relation) {
|
|
35
|
-
const paramName = relation.
|
|
36
|
+
const paramName = relation.to.entityName.lowerCase();
|
|
36
37
|
const propertyName = relation.referencedByPropertyName();
|
|
37
38
|
return tsg.propertyAssign(propertyName, tsg.arrowFunc([
|
|
38
39
|
tsg.parameter(paramName, tsg
|
|
39
|
-
.typeRef(relation.
|
|
40
|
+
.typeRef(relation.to.entityName.resultType())
|
|
40
41
|
.importFrom('./relationMap')),
|
|
41
42
|
], undefined, tsg.block(tsg.if(tsg.binary(tsg.identifier(paramName).property(propertyName), '!==', tsg.identifier('undefined')), tsg.return(tsg.identifier(paramName).property(propertyName))), tsg.return(tsg
|
|
42
43
|
.new(tsg
|
|
43
44
|
.identifier(relation.parent.entityName.dataSourceName())
|
|
44
45
|
.importFrom(Directory.dbDataSourcePath(Directory.paths.generated, relation.parent.entityName)))
|
|
45
|
-
.property(FindMethodNode.paramsToName(relation.
|
|
46
|
-
.call(tsg.identifier(paramName).property(relation.
|
|
46
|
+
.property(FindMethodNode.paramsToName(relation.from.field))
|
|
47
|
+
.call(tsg.identifier(paramName).property(relation.to.field).nonNull())))));
|
|
47
48
|
}
|
|
48
49
|
generate(root) {
|
|
49
50
|
const hasSubscription = root.mutations().some(it => it.subscribed);
|
|
@@ -53,6 +54,6 @@ export class ResolverGenerator {
|
|
|
53
54
|
];
|
|
54
55
|
if (hasSubscription)
|
|
55
56
|
properties.push(new PropertyAssignment('Subscription', new Identifier('subscription').importFrom('./subscription')));
|
|
56
|
-
return new TsFile(new VariableDeclaration('const', new Identifier('resolvers'), new ObjectLiteral(...properties, new SpreadAssignment(new ObjectLiteral(...root.entities().map(this.entityResolver))))).export()).disableEsLint();
|
|
57
|
+
return new TsFile(new VariableDeclaration('const', new Identifier('resolvers'), new ObjectLiteral(...properties, new SpreadAssignment(new ObjectLiteral(...root.entities().filter(it => it.gqlEnabled()).map(this.entityResolver))))).export()).disableEsLint();
|
|
57
58
|
}
|
|
58
59
|
}
|
|
@@ -4,7 +4,7 @@ import { tsg } from '../code/factory.js';
|
|
|
4
4
|
import { MutationNode } from '../../../parser/node/gql/mutationNode.js';
|
|
5
5
|
export class TypeDefGenerator {
|
|
6
6
|
generate(root) {
|
|
7
|
-
const typeDefs = root.entities().flatMap(it => it.allTypeDefs());
|
|
7
|
+
const typeDefs = root.entities().filter(it => it.gqlEnabled()).flatMap(it => it.allTypeDefs());
|
|
8
8
|
const types = [
|
|
9
9
|
...this.createTypes(typeDefs),
|
|
10
10
|
this.createQuery(root.queries()),
|
|
@@ -3,6 +3,7 @@ import { RootNode } from '../../parser/node/rootNode.js';
|
|
|
3
3
|
export declare class RelationMapGenerator {
|
|
4
4
|
generate(root: RootNode): TsFile;
|
|
5
5
|
private relationMap;
|
|
6
|
+
private referencedRelationType;
|
|
6
7
|
private entityRelationType;
|
|
7
8
|
private entityRelationMap;
|
|
8
9
|
private tableInfo;
|
|
@@ -4,26 +4,29 @@ import { Directory } from '../../constants/directory.js';
|
|
|
4
4
|
import { KeywordTypeNode } from './code/node/type/typeKeyword.js';
|
|
5
5
|
export class RelationMapGenerator {
|
|
6
6
|
generate(root) {
|
|
7
|
-
return new TsFile(this.relationMap(root), this.tableInfo(root), ...root.entities().flatMap(this.entityRelationType)).disableEsLint();
|
|
7
|
+
return new TsFile(this.relationMap(root), this.tableInfo(root), ...root.entities().flatMap(it => this.entityRelationType(it))).disableEsLint();
|
|
8
8
|
}
|
|
9
9
|
relationMap(root) {
|
|
10
10
|
return tsg
|
|
11
11
|
.variable('const', tsg.identifier('relationMap'), tsg.object(...root.entities().map(it => this.entityRelationMap(it))), tsg.typeRef('RelationMap').importFrom('sasat'))
|
|
12
12
|
.export();
|
|
13
13
|
}
|
|
14
|
+
referencedRelationType(node) {
|
|
15
|
+
const type = tsg.intersectionType(tsg.typeRef('Partial', [node.parent.entityName.getTypeReference(Directory.paths.generated)]), node.parent.entityName.identifiableTypeReference(Directory.paths.generated));
|
|
16
|
+
return tsg.propertySignature(node.referencedByPropertyName(), node.relation === 'Many' ? tsg.arrayType(type) : type);
|
|
17
|
+
}
|
|
14
18
|
entityRelationType(node) {
|
|
15
19
|
const importEntity = (entity) => Directory.entityPath(Directory.paths.generated, entity);
|
|
16
20
|
const typeProperties = [
|
|
17
|
-
...node.relations.map(it => tsg.propertySignature(it.refPropertyName(),
|
|
18
|
-
.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
...node.relations.map(it => tsg.propertySignature(it.refPropertyName(), tsg.intersectionType(tsg.typeRef('Partial', [
|
|
22
|
+
tsg.intersectionType(it
|
|
23
|
+
.refType()
|
|
24
|
+
.toTsType()
|
|
25
|
+
.addImport([it.to.entityName.name], importEntity(it.to.entityName)), tsg.typeRef(it.to.entityName.relationTypeName())),
|
|
26
|
+
]), it.to.entityName.identifiableTypeReference(Directory.paths.generated)))),
|
|
21
27
|
...node
|
|
22
28
|
.findReferencedRelations()
|
|
23
|
-
.map(it =>
|
|
24
|
-
.referenceByType()
|
|
25
|
-
.toTsType()
|
|
26
|
-
.addImport([it.parent.entityName.name], importEntity(it.parent.entityName)))),
|
|
29
|
+
.map(it => this.referencedRelationType(it)),
|
|
27
30
|
];
|
|
28
31
|
return [
|
|
29
32
|
tsg
|
|
@@ -57,9 +60,9 @@ export class RelationMapGenerator {
|
|
|
57
60
|
.call(tsg.identifier('parentTableAlias'), tsg.string(parentColumn)), qExpr
|
|
58
61
|
.property('field')
|
|
59
62
|
.call(tsg.identifier('childTableAlias'), tsg.string(childColumn)))));
|
|
60
|
-
return tsg.propertyAssign(node.repository.tableName, tsg.object(...node.relations.map(rel => tsg.propertyAssign(rel.refPropertyName(), tsg.object(tsg.propertyAssign('table', tsg.string(rel.
|
|
63
|
+
return tsg.propertyAssign(node.repository.tableName, tsg.object(...node.relations.map(rel => tsg.propertyAssign(rel.refPropertyName(), tsg.object(tsg.propertyAssign('table', tsg.string(rel.to.tableName)), on(rel.from.columnName, rel.to.columnName), tsg.propertyAssign('relation', tsg.string('One'))))), ...node
|
|
61
64
|
.findReferencedRelations()
|
|
62
|
-
.map(rel => tsg.propertyAssign(rel.referencedByPropertyName(), tsg.object(tsg.propertyAssign('table', tsg.string(rel.parent.repository.tableName)), on(rel.
|
|
65
|
+
.map(rel => tsg.propertyAssign(rel.referencedByPropertyName(), tsg.object(tsg.propertyAssign('table', tsg.string(rel.parent.repository.tableName)), on(rel.to.columnName, rel.from.columnName), tsg.propertyAssign('relation', tsg.string(rel.relation)))))));
|
|
63
66
|
}
|
|
64
67
|
tableInfo(root) {
|
|
65
68
|
const columnMap = (entity) => tsg.propertyAssign('columnMap', tsg.object(...entity.fields.map(field => tsg.propertyAssign(field.fieldName, tsg.string(field.columnName)))));
|
|
@@ -25,13 +25,14 @@ const baseDBDataSourceFile = `\
|
|
|
25
25
|
${new ImportDeclaration(['Fields', 'SasatDBDatasource', 'EntityType'], 'sasat').toString()}
|
|
26
26
|
${new ImportDeclaration(['relationMap', 'tableInfo'], './__generated__/relationMap').toString()}
|
|
27
27
|
|
|
28
|
-
export abstract class BaseDBDataSource<
|
|
29
|
-
Entity,
|
|
28
|
+
export abstract class BaseDBDataSource<
|
|
29
|
+
Entity extends EntityType,
|
|
30
30
|
Creatable,
|
|
31
31
|
Identifiable,
|
|
32
|
-
EntityFields
|
|
33
|
-
>
|
|
34
|
-
|
|
32
|
+
EntityFields extends Fields,
|
|
33
|
+
QueryResult extends Partial<Entity> & Identifiable,
|
|
34
|
+
> extends SasatDBDatasource<Entity, Creatable, Identifiable, EntityFields, QueryResult> {
|
|
35
|
+
protected relationMap = relationMap;
|
|
35
36
|
protected tableInfo = tableInfo;
|
|
36
37
|
}
|
|
37
38
|
`;
|
|
@@ -9,7 +9,7 @@ export const tsValueString = (value) => {
|
|
|
9
9
|
if (typeof value === 'boolean')
|
|
10
10
|
return '' + value;
|
|
11
11
|
if (typeof value === 'string')
|
|
12
|
-
return `'${value.
|
|
12
|
+
return `'${value.replaceAll("'", "\\'")}'`;
|
|
13
13
|
if (typeof value === 'bigint')
|
|
14
14
|
return '' + value;
|
|
15
15
|
if (typeof value === 'function')
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { BooleanValueExpression } from './runtime/dsl/query/query.js';
|
|
1
|
+
export { BooleanValueExpression, Query, LockMode, } from './runtime/dsl/query/query.js';
|
|
2
2
|
export { Relation } from './migration/data/relation.js';
|
|
3
3
|
export { QExpr } from './runtime/dsl/factory.js';
|
|
4
4
|
export { RelationMap } from './runtime/dsl/query/createQueryResolveInfo.js';
|
|
@@ -7,7 +7,7 @@ export { gqlResolveInfoToField } from './runtime/gqlResolveInfoToField.js';
|
|
|
7
7
|
export { ComparisonOperators } from './db/sql/expression/comparison.js';
|
|
8
8
|
export { MigrationStore } from './migration/front/storeMigrator.js';
|
|
9
9
|
export { SasatMigration } from './migration/front/migration.js';
|
|
10
|
-
export { SasatDBDatasource, EntityResult, EntityType, ListQueryOption, } from './runtime/sasatDBDatasource.js';
|
|
10
|
+
export { SasatDBDatasource, EntityResult, EntityType, ListQueryOption, QueryOptions, } from './runtime/sasatDBDatasource.js';
|
|
11
11
|
export { getCurrentDateTimeString } from './util/dateUtil.js';
|
|
12
12
|
export { getDbClient } from './db/getDbClient.js';
|
|
13
13
|
export { assignDeep } from './util/assignDeep.js';
|
|
@@ -2,7 +2,7 @@ import { ColumnCreator } from './columnCreator.js';
|
|
|
2
2
|
import { ColumnBuilder } from './columnBuilder.js';
|
|
3
3
|
import { Reference } from '../serialized/serializedColumn.js';
|
|
4
4
|
import { TableHandler } from '../serializable/table.js';
|
|
5
|
-
import { GqlFromContextParam, MutationOption } from '../data/
|
|
5
|
+
import { GqlFromContextParam, GQLOption, MutationOption } from '../data/GQLOption.js';
|
|
6
6
|
import { DataStore } from '../dataStore.js';
|
|
7
7
|
export interface TableBuilder {
|
|
8
8
|
column(columnName: string): ColumnCreator;
|
|
@@ -16,6 +16,8 @@ export interface TableBuilder {
|
|
|
16
16
|
setGQLUpdate(enabled: boolean, options?: Partial<MutationOption>): TableBuilder;
|
|
17
17
|
setGQLDelete(enabled: boolean, options?: Partial<Omit<MutationOption, 'noReFetch'>>): TableBuilder;
|
|
18
18
|
setGQLContextColumn(columns: GqlFromContextParam[]): TableBuilder;
|
|
19
|
+
enableGQL(): TableBuilder;
|
|
20
|
+
setGQLOption(option: Partial<GQLOption>): TableBuilder;
|
|
19
21
|
}
|
|
20
22
|
export declare class TableCreator implements TableBuilder {
|
|
21
23
|
tableName: string;
|
|
@@ -31,6 +33,8 @@ export declare class TableCreator implements TableBuilder {
|
|
|
31
33
|
createdAt(): TableBuilder;
|
|
32
34
|
updatedAt(): TableBuilder;
|
|
33
35
|
addIndex(...columns: string[]): TableBuilder;
|
|
36
|
+
enableGQL(): TableBuilder;
|
|
37
|
+
setGQLOption(option: Partial<GQLOption>): TableBuilder;
|
|
34
38
|
setGQLCreate(enabled: boolean, options?: Partial<MutationOption>): TableBuilder;
|
|
35
39
|
setGQLUpdate(enabled: boolean, options?: Partial<MutationOption>): TableBuilder;
|
|
36
40
|
setGQLDelete(enabled: boolean, options?: Partial<Omit<MutationOption, 'noReFetch'>>): TableBuilder;
|
|
@@ -50,6 +50,17 @@ export class TableCreator {
|
|
|
50
50
|
this.table.addIndex(`index_${this.tableName}__${columns.join('_')}`, ...columns);
|
|
51
51
|
return this;
|
|
52
52
|
}
|
|
53
|
+
enableGQL() {
|
|
54
|
+
this.table.setGQLOption({
|
|
55
|
+
...this.table.gqlOption,
|
|
56
|
+
enabled: true,
|
|
57
|
+
});
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
setGQLOption(option) {
|
|
61
|
+
this.table.setGQLOption(option);
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
53
64
|
setGQLCreate(enabled, options) {
|
|
54
65
|
this.table.setGQLCreate(enabled, options);
|
|
55
66
|
return this;
|
|
@@ -10,7 +10,12 @@ export declare type MutationOption = {
|
|
|
10
10
|
subscription: boolean;
|
|
11
11
|
subscriptionFilter: string[];
|
|
12
12
|
};
|
|
13
|
-
export interface
|
|
13
|
+
export interface GQLOption {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
query: {
|
|
16
|
+
find: boolean;
|
|
17
|
+
list: false | 'all' | 'paging';
|
|
18
|
+
};
|
|
14
19
|
mutation: {
|
|
15
20
|
create: MutationOption & Enabled;
|
|
16
21
|
update: MutationOption & Enabled;
|
|
@@ -24,6 +29,6 @@ export declare const defaultMutationOption: {
|
|
|
24
29
|
subscription: boolean;
|
|
25
30
|
subscriptionFilter: never[];
|
|
26
31
|
};
|
|
27
|
-
export declare const getDefaultGqlOption: () =>
|
|
28
|
-
export declare const updateMutationOption: (option:
|
|
32
|
+
export declare const getDefaultGqlOption: () => GQLOption;
|
|
33
|
+
export declare const updateMutationOption: (option: GQLOption, mutation: Partial<GQLOption['mutation']>) => GQLOption;
|
|
29
34
|
export {};
|
|
@@ -5,6 +5,11 @@ export const defaultMutationOption = {
|
|
|
5
5
|
subscriptionFilter: [],
|
|
6
6
|
};
|
|
7
7
|
export const getDefaultGqlOption = () => ({
|
|
8
|
+
enabled: false,
|
|
9
|
+
query: {
|
|
10
|
+
find: true,
|
|
11
|
+
list: 'all',
|
|
12
|
+
},
|
|
8
13
|
mutation: {
|
|
9
14
|
create: defaultMutationOption,
|
|
10
15
|
update: defaultMutationOption,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StoreMigrator } from './storeMigrator.js';
|
|
2
2
|
import { Table, TableHandler } from '../serializable/table.js';
|
|
3
3
|
import { Reference, SerializedColumn, SerializedNormalColumn } from '../serialized/serializedColumn.js';
|
|
4
|
-
import { GqlFromContextParam, MutationOption } from '../data/
|
|
4
|
+
import { GqlFromContextParam, GQLOption, MutationOption } from '../data/GQLOption.js';
|
|
5
5
|
import { Column } from '../serializable/column.js';
|
|
6
6
|
import { SerializedTable } from '../serialized/serializedStore.js';
|
|
7
7
|
import { DBType } from '../column/columnTypes.js';
|
|
@@ -18,6 +18,8 @@ export interface MigrationTable extends Table {
|
|
|
18
18
|
setGQLUpdate(enabled: boolean, options?: Partial<MutationOption>): MigrationTable;
|
|
19
19
|
setGQLDelete(enabled: boolean, options?: Partial<Omit<MutationOption, 'noReFetch'>>): MigrationTable;
|
|
20
20
|
setGQLContextColumn(columns: GqlFromContextParam[]): MigrationTable;
|
|
21
|
+
enableGQL(): MigrationTable;
|
|
22
|
+
setGQLOption(option: GQLOption): MigrationTable;
|
|
21
23
|
}
|
|
22
24
|
export declare class TableMigrator implements MigrationTable {
|
|
23
25
|
private table;
|
|
@@ -35,10 +37,13 @@ export declare class TableMigrator implements MigrationTable {
|
|
|
35
37
|
dropColumn(columnName: string): MigrationTable;
|
|
36
38
|
setGQLCreate(enabled: boolean, options?: Partial<MutationOption>): MigrationTable;
|
|
37
39
|
setGQLUpdate(enabled: boolean, options?: Partial<MutationOption>): MigrationTable;
|
|
40
|
+
enableGQL(): MigrationTable;
|
|
41
|
+
setGQLOption(option: GQLOption): MigrationTable;
|
|
38
42
|
setGQLDelete(enabled: boolean, options?: Partial<Omit<MutationOption, 'noReFetch'>>): MigrationTable;
|
|
39
43
|
setGQLContextColumn(columns: GqlFromContextParam[]): MigrationTable;
|
|
40
44
|
addForeignKey(reference: Reference): MigrationTable;
|
|
41
45
|
changeColumnType(columnName: string, type: DBType): MigrationTable;
|
|
42
46
|
protected tableExists(tableName: string): true;
|
|
43
47
|
setDefault(columnName: string, value: string | number | null): MigrationTable;
|
|
48
|
+
get gqlOption(): GQLOption;
|
|
44
49
|
}
|
|
@@ -56,6 +56,17 @@ export class TableMigrator {
|
|
|
56
56
|
this.table.setGQLUpdate(enabled, options);
|
|
57
57
|
return this;
|
|
58
58
|
}
|
|
59
|
+
enableGQL() {
|
|
60
|
+
this.table.setGQLOption({
|
|
61
|
+
...this.table.gqlOption,
|
|
62
|
+
enabled: true,
|
|
63
|
+
});
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
setGQLOption(option) {
|
|
67
|
+
this.table.setGQLOption(option);
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
59
70
|
setGQLDelete(enabled, options) {
|
|
60
71
|
this.table.setGQLDelete(enabled, options);
|
|
61
72
|
return this;
|
|
@@ -99,4 +110,7 @@ export class TableMigrator {
|
|
|
99
110
|
this.store.addQuery(`ALTER TABLE ${this.tableName} ALTER ${columnName} SET DEFAULT ${SqlString.escape(value)}`);
|
|
100
111
|
return this;
|
|
101
112
|
}
|
|
113
|
+
get gqlOption() {
|
|
114
|
+
return this.table.gqlOption;
|
|
115
|
+
}
|
|
102
116
|
}
|
|
@@ -3,13 +3,14 @@ import { SerializedTable } from '../serialized/serializedStore.js';
|
|
|
3
3
|
import { BaseColumn, Column, ReferenceColumn } from './column.js';
|
|
4
4
|
import { Reference, SerializedColumn } from '../serialized/serializedColumn.js';
|
|
5
5
|
import { DBIndex } from '../data/index.js';
|
|
6
|
-
import { GqlFromContextParam,
|
|
6
|
+
import { GqlFromContextParam, GQLOption, MutationOption } from '../data/GQLOption.js';
|
|
7
7
|
import { EntityName } from '../../parser/node/entityName.js';
|
|
8
8
|
import { DataStore } from '../dataStore.js';
|
|
9
9
|
import { DBColumnTypes } from '../column/columnTypes.js';
|
|
10
10
|
export interface Table extends Serializable<SerializedTable> {
|
|
11
11
|
column(columnName: string): Column;
|
|
12
12
|
tableName: string;
|
|
13
|
+
gqlOption: GQLOption;
|
|
13
14
|
}
|
|
14
15
|
export declare class TableHandler implements Table {
|
|
15
16
|
store: DataStore;
|
|
@@ -22,7 +23,7 @@ export declare class TableHandler implements Table {
|
|
|
22
23
|
readonly uniqueKeys: string[][];
|
|
23
24
|
readonly tableName: string;
|
|
24
25
|
private _gqlOption;
|
|
25
|
-
get gqlOption():
|
|
26
|
+
get gqlOption(): GQLOption;
|
|
26
27
|
constructor(table: Partial<SerializedTable> & Pick<SerializedTable, 'tableName'>, store: DataStore);
|
|
27
28
|
column(columnName: string): Column;
|
|
28
29
|
addColumn(column: BaseColumn, isPrimary?: boolean, isUnique?: boolean): void;
|
|
@@ -40,6 +41,7 @@ export declare class TableHandler implements Table {
|
|
|
40
41
|
getEntityName(): EntityName;
|
|
41
42
|
setGQLCreate(enabled: boolean, options?: Partial<MutationOption>): void;
|
|
42
43
|
setGQLUpdate(enabled: boolean, options?: Partial<MutationOption>): void;
|
|
44
|
+
setGQLOption(option: Partial<GQLOption>): void;
|
|
43
45
|
setGQLDelete(enabled: boolean, options?: Partial<Omit<MutationOption, 'noReFetch'>>): void;
|
|
44
46
|
setGQLContextColumn(columns: GqlFromContextParam[]): void;
|
|
45
47
|
getReferenceColumns(): ReferenceColumn[];
|
|
@@ -4,7 +4,7 @@ import { SqlString } from '../../runtime/sql/sqlString.js';
|
|
|
4
4
|
import { SasatError } from '../../error.js';
|
|
5
5
|
import { referenceToSql, } from '../serialized/serializedColumn.js';
|
|
6
6
|
import { DBIndex } from '../data/index.js';
|
|
7
|
-
import { defaultMutationOption, getDefaultGqlOption, updateMutationOption, } from '../data/
|
|
7
|
+
import { defaultMutationOption, getDefaultGqlOption, updateMutationOption, } from '../data/GQLOption.js';
|
|
8
8
|
import { assembleColumn } from '../functions/assembleColumn.js';
|
|
9
9
|
import { EntityName } from '../../parser/node/entityName.js';
|
|
10
10
|
export class TableHandler {
|
|
@@ -147,6 +147,9 @@ export class TableHandler {
|
|
|
147
147
|
},
|
|
148
148
|
});
|
|
149
149
|
}
|
|
150
|
+
setGQLOption(option) {
|
|
151
|
+
this._gqlOption = { ...this.gqlOption, ...option };
|
|
152
|
+
}
|
|
150
153
|
setGQLDelete(enabled, options) {
|
|
151
154
|
this._gqlOption = updateMutationOption(this._gqlOption, {
|
|
152
155
|
delete: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SerializedColumn } from './serializedColumn.js';
|
|
2
2
|
import { Index } from '../data/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { GQLOption } from '../data/GQLOption.js';
|
|
4
4
|
export interface SerializedStore {
|
|
5
5
|
tables: SerializedTable[];
|
|
6
6
|
}
|
|
@@ -10,5 +10,5 @@ export interface SerializedTable {
|
|
|
10
10
|
uniqueKeys: string[][];
|
|
11
11
|
indexes: Index[];
|
|
12
12
|
tableName: string;
|
|
13
|
-
gqlOption:
|
|
13
|
+
gqlOption: GQLOption;
|
|
14
14
|
}
|
|
@@ -8,10 +8,13 @@ export class EntityNode {
|
|
|
8
8
|
this.fields = table.columns.map(column => FieldNode.fromColumn(column, table));
|
|
9
9
|
this.relations = table
|
|
10
10
|
.getReferenceColumns()
|
|
11
|
-
.map(it =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
11
|
+
.map(it => {
|
|
12
|
+
const targetTable = table.store
|
|
13
|
+
.table(it.data.reference.targetTable);
|
|
14
|
+
return RelationNode.fromReference(this, it, targetTable
|
|
15
|
+
.column(it.data.reference.targetColumn)
|
|
16
|
+
.fieldName(), targetTable.gqlOption);
|
|
17
|
+
});
|
|
15
18
|
}
|
|
16
19
|
field(fieldName) {
|
|
17
20
|
return this.fields.find(it => it.fieldName === fieldName);
|
|
@@ -43,4 +46,7 @@ export class EntityNode {
|
|
|
43
46
|
findReferencedRelations() {
|
|
44
47
|
return this.repository.root.findReferencedRelations(this.entityName);
|
|
45
48
|
}
|
|
49
|
+
gqlEnabled() {
|
|
50
|
+
return this.repository.gqlOption.enabled;
|
|
51
|
+
}
|
|
46
52
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { ParameterNode } from '../parameterNode.js';
|
|
2
2
|
import { TypeNode } from '../typeNode.js';
|
|
3
|
+
export declare type ListQueryType = 'all' | 'paging';
|
|
3
4
|
export declare class QueryNode {
|
|
4
5
|
readonly queryName: string;
|
|
5
6
|
readonly repoMethodName: string;
|
|
6
7
|
readonly queryParams: ParameterNode[];
|
|
7
8
|
readonly returnType: TypeNode;
|
|
8
9
|
readonly isList: boolean;
|
|
9
|
-
|
|
10
|
+
readonly listType?: ListQueryType | undefined;
|
|
11
|
+
constructor(queryName: string, repoMethodName: string, queryParams: ParameterNode[], returnType: TypeNode, isList: boolean, listType?: ListQueryType | undefined);
|
|
10
12
|
toGqlString(): string;
|
|
11
13
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ParameterNode } from '../parameterNode.js';
|
|
2
2
|
export class QueryNode {
|
|
3
|
-
constructor(queryName, repoMethodName, queryParams, returnType, isList) {
|
|
3
|
+
constructor(queryName, repoMethodName, queryParams, returnType, isList, listType) {
|
|
4
4
|
this.queryName = queryName;
|
|
5
5
|
this.repoMethodName = repoMethodName;
|
|
6
6
|
this.queryParams = queryParams;
|
|
7
7
|
this.returnType = returnType;
|
|
8
8
|
this.isList = isList;
|
|
9
|
+
this.listType = listType;
|
|
9
10
|
}
|
|
10
11
|
toGqlString() {
|
|
11
12
|
return `${this.queryName}${ParameterNode.parametersToGqlString(...this.queryParams)}: ${this.returnType.toGqlString()}`;
|
|
@@ -5,9 +5,10 @@ export class TypeDefNode {
|
|
|
5
5
|
this.params = params;
|
|
6
6
|
}
|
|
7
7
|
static new(entity) {
|
|
8
|
-
const reference = entity.relations.map(rel => new ParameterNode(rel.refPropertyName(), rel.refType()));
|
|
8
|
+
const reference = entity.relations.filter(it => it.to.gqlOption.enabled).map(rel => new ParameterNode(rel.refPropertyName(), rel.refType()));
|
|
9
9
|
const referencedBy = entity
|
|
10
10
|
.findReferencedRelations()
|
|
11
|
+
.filter(it => it.from.gqlOption.enabled)
|
|
11
12
|
.map(rel => new ParameterNode(rel.referencedByPropertyName(), rel.referenceByType()));
|
|
12
13
|
return new TypeDefNode(entity.entityName.name, [
|
|
13
14
|
...entity.fields.map(it => it.toParam()),
|
|
@@ -3,20 +3,30 @@ import { EntityNode } from './entityNode.js';
|
|
|
3
3
|
import { ReferenceColumn } from '../../migration/serializable/column.js';
|
|
4
4
|
import { EntityName } from './entityName.js';
|
|
5
5
|
import { Relation } from '../../migration/data/relation.js';
|
|
6
|
+
import { GQLOption } from "../../migration/data/GQLOption.js";
|
|
7
|
+
declare type From = {
|
|
8
|
+
field: string;
|
|
9
|
+
columnName: string;
|
|
10
|
+
gqlOption: GQLOption;
|
|
11
|
+
};
|
|
12
|
+
declare type To = {
|
|
13
|
+
field: string;
|
|
14
|
+
columnName: string;
|
|
15
|
+
tableName: string;
|
|
16
|
+
entityName: EntityName;
|
|
17
|
+
gqlOption: GQLOption;
|
|
18
|
+
};
|
|
6
19
|
export declare class RelationNode {
|
|
7
20
|
readonly parent: EntityNode;
|
|
8
21
|
readonly relationName: string | undefined;
|
|
9
|
-
readonly fromField: string;
|
|
10
|
-
readonly toField: string;
|
|
11
|
-
readonly toTableName: string;
|
|
12
|
-
readonly toEntityName: EntityName;
|
|
13
22
|
readonly relation: Relation;
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
16
|
-
static fromReference(entity: EntityNode, ref: ReferenceColumn, targetFieldName: string): RelationNode;
|
|
23
|
+
readonly from: From;
|
|
24
|
+
readonly to: To;
|
|
25
|
+
static fromReference(entity: EntityNode, ref: ReferenceColumn, targetFieldName: string, targetTableGqlOption: GQLOption): RelationNode;
|
|
17
26
|
private constructor();
|
|
18
27
|
refPropertyName(): string;
|
|
19
28
|
referencedByPropertyName(): string;
|
|
20
29
|
refType(): TypeNode;
|
|
21
30
|
referenceByType(): TypeNode;
|
|
22
31
|
}
|
|
32
|
+
export {};
|
|
@@ -2,28 +2,34 @@ import { EntityTypeNode } from './typeNode.js';
|
|
|
2
2
|
import { TableHandler } from '../../migration/serializable/table.js';
|
|
3
3
|
import { EntityName } from './entityName.js';
|
|
4
4
|
export class RelationNode {
|
|
5
|
-
constructor(parent, relationName,
|
|
5
|
+
constructor(parent, relationName, relation, from, to) {
|
|
6
6
|
this.parent = parent;
|
|
7
7
|
this.relationName = relationName;
|
|
8
|
-
this.fromField = fromField;
|
|
9
|
-
this.toField = toField;
|
|
10
|
-
this.toTableName = toTableName;
|
|
11
|
-
this.toEntityName = toEntityName;
|
|
12
8
|
this.relation = relation;
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
9
|
+
this.from = from;
|
|
10
|
+
this.to = to;
|
|
15
11
|
}
|
|
16
|
-
static fromReference(entity, ref, targetFieldName) {
|
|
17
|
-
return new RelationNode(entity, ref.data.reference.relationName, ref.data.
|
|
12
|
+
static fromReference(entity, ref, targetFieldName, targetTableGqlOption) {
|
|
13
|
+
return new RelationNode(entity, ref.data.reference.relationName, ref.data.reference.relation, {
|
|
14
|
+
field: ref.data.fieldName,
|
|
15
|
+
columnName: ref.data.columnName,
|
|
16
|
+
gqlOption: ref.table.gqlOption,
|
|
17
|
+
}, {
|
|
18
|
+
field: targetFieldName,
|
|
19
|
+
tableName: ref.data.reference.targetTable,
|
|
20
|
+
entityName: new EntityName(TableHandler.tableNameToEntityName(ref.data.reference.targetTable)),
|
|
21
|
+
columnName: ref.data.reference.targetColumn,
|
|
22
|
+
gqlOption: targetTableGqlOption,
|
|
23
|
+
});
|
|
18
24
|
}
|
|
19
25
|
refPropertyName() {
|
|
20
|
-
return this.relationName || this.
|
|
26
|
+
return this.relationName || this.from.field + this.to.entityName.name;
|
|
21
27
|
}
|
|
22
28
|
referencedByPropertyName() {
|
|
23
29
|
return (this.relationName || '') + this.parent.entityName.name;
|
|
24
30
|
}
|
|
25
31
|
refType() {
|
|
26
|
-
return new EntityTypeNode(this.
|
|
32
|
+
return new EntityTypeNode(this.to.entityName, false, false);
|
|
27
33
|
}
|
|
28
34
|
referenceByType() {
|
|
29
35
|
if (this.relation === 'Many')
|
|
@@ -5,6 +5,7 @@ import { QueryNode } from './gql/queryNode.js';
|
|
|
5
5
|
import { MutationNode } from './gql/mutationNode.js';
|
|
6
6
|
import { TableHandler } from '../../migration/serializable/table.js';
|
|
7
7
|
import { EntityName } from './entityName.js';
|
|
8
|
+
import { GQLOption } from "../../migration/data/GQLOption.js";
|
|
8
9
|
export declare class RepositoryNode {
|
|
9
10
|
readonly root: RootNode;
|
|
10
11
|
readonly tableName: string;
|
|
@@ -14,6 +15,7 @@ export declare class RepositoryNode {
|
|
|
14
15
|
readonly autoIncrementColumn?: string;
|
|
15
16
|
readonly queries: QueryNode[];
|
|
16
17
|
readonly mutations: MutationNode[];
|
|
18
|
+
readonly gqlOption: GQLOption;
|
|
17
19
|
constructor(root: RootNode, table: TableHandler);
|
|
18
20
|
private createEntity;
|
|
19
21
|
getDefaultValueColumnNames(): string[];
|
|
@@ -15,8 +15,9 @@ export class RepositoryNode {
|
|
|
15
15
|
this.autoIncrementColumn = table.columns
|
|
16
16
|
.find(it => it.serialize().autoIncrement)
|
|
17
17
|
?.fieldName();
|
|
18
|
-
this.queries = new QueryNodeFactory().create(table);
|
|
18
|
+
this.queries = new QueryNodeFactory().create(table, table.gqlOption);
|
|
19
19
|
this.mutations = new MutationNodeFactory().create(table, this.entity);
|
|
20
|
+
this.gqlOption = table.gqlOption;
|
|
20
21
|
}
|
|
21
22
|
createEntity(table) {
|
|
22
23
|
return new EntityNode(this, table);
|
|
@@ -37,14 +38,14 @@ export class RepositoryNode {
|
|
|
37
38
|
};
|
|
38
39
|
const refMethods = (relation) => {
|
|
39
40
|
return new FindMethodNode([
|
|
40
|
-
new ParameterNode(relation.
|
|
41
|
+
new ParameterNode(relation.from.field, new EntityTypeNode(relation.parent.field(relation.from.field).dbType, false, false)),
|
|
41
42
|
], new EntityTypeNode(EntityName.fromTableName(relation.parent.repository.tableName), relation.relation === 'Many', false), false);
|
|
42
43
|
};
|
|
43
44
|
const referencedByMethod = (relation) => {
|
|
44
|
-
const to = relation.parent.repository.root.findRepository(relation.
|
|
45
|
+
const to = relation.parent.repository.root.findRepository(relation.to.entityName);
|
|
45
46
|
return new FindMethodNode([
|
|
46
|
-
new ParameterNode(relation.
|
|
47
|
-
], new EntityTypeNode(relation.
|
|
47
|
+
new ParameterNode(relation.to.field, new EntityTypeNode(to.entity.field(relation.to.field).dbType, false, false)),
|
|
48
|
+
], new EntityTypeNode(relation.to.entityName, false, false), false);
|
|
48
49
|
};
|
|
49
50
|
const methods = [
|
|
50
51
|
new FindMethodNode(node.primaryKeys.map(it => {
|
|
@@ -10,7 +10,7 @@ export class RootNode {
|
|
|
10
10
|
}
|
|
11
11
|
findReferencedRelations(entity) {
|
|
12
12
|
return this.entities()
|
|
13
|
-
.map(it => it.relations.find(it => it.
|
|
13
|
+
.map(it => it.relations.find(it => it.to.entityName.name === entity.name))
|
|
14
14
|
.filter(it => it !== undefined);
|
|
15
15
|
}
|
|
16
16
|
entities() {
|
|
@@ -6,7 +6,7 @@ export declare abstract class TypeNode {
|
|
|
6
6
|
readonly isArray: boolean;
|
|
7
7
|
readonly isNullable: boolean;
|
|
8
8
|
readonly isArrayNullable: boolean;
|
|
9
|
-
constructor(typeName: DBColumnTypes | EntityName, isArray: boolean, isNullable: boolean, isArrayNullable?: boolean);
|
|
9
|
+
protected constructor(typeName: DBColumnTypes | EntityName, isArray: boolean, isNullable: boolean, isArrayNullable?: boolean);
|
|
10
10
|
abstract toTsType(): TsType;
|
|
11
11
|
toGqlString(): string;
|
|
12
12
|
}
|
|
@@ -23,7 +23,7 @@ export class TypeNode {
|
|
|
23
23
|
}
|
|
24
24
|
export class ListQueryOptionTypeNode extends TypeNode {
|
|
25
25
|
constructor() {
|
|
26
|
-
super(new EntityName(TypeDefGenerator.ListQueryOptionType), false,
|
|
26
|
+
super(new EntityName(TypeDefGenerator.ListQueryOptionType), false, false);
|
|
27
27
|
}
|
|
28
28
|
toTsType() {
|
|
29
29
|
return tsg
|
|
@@ -5,6 +5,8 @@ import { FindMethodNode } from '../node/findMethod.js';
|
|
|
5
5
|
export class MutationNodeFactory {
|
|
6
6
|
constructor() {
|
|
7
7
|
this.create = (table, entity) => {
|
|
8
|
+
if (!table.gqlOption.enabled)
|
|
9
|
+
return [];
|
|
8
10
|
const result = [];
|
|
9
11
|
const options = table.gqlOption.mutation;
|
|
10
12
|
if (options.create.enabled) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { QueryNode } from '../node/gql/queryNode.js';
|
|
2
2
|
import { TableHandler } from '../../migration/serializable/table.js';
|
|
3
|
+
import { GQLOption } from "../../migration/data/GQLOption.js";
|
|
3
4
|
export declare class QueryNodeFactory {
|
|
4
|
-
create(table: TableHandler): QueryNode[];
|
|
5
|
+
create(table: TableHandler, gqlOption: GQLOption): QueryNode[];
|
|
5
6
|
private listQuery;
|
|
6
7
|
private primaryQuery;
|
|
7
8
|
}
|
|
@@ -4,11 +4,20 @@ import { EntityTypeNode, ListQueryOptionTypeNode, } from '../node/typeNode.js';
|
|
|
4
4
|
import { ParameterNode } from '../node/parameterNode.js';
|
|
5
5
|
import { FindMethodNode } from '../node/findMethod.js';
|
|
6
6
|
export class QueryNodeFactory {
|
|
7
|
-
create(table) {
|
|
8
|
-
|
|
7
|
+
create(table, gqlOption) {
|
|
8
|
+
if (!gqlOption.enabled)
|
|
9
|
+
return [];
|
|
10
|
+
const result = [];
|
|
11
|
+
if (gqlOption.query.find) {
|
|
12
|
+
result.push(this.primaryQuery(table));
|
|
13
|
+
}
|
|
14
|
+
if (gqlOption.query.list !== false) {
|
|
15
|
+
result.push(this.listQuery(table, gqlOption.query.list));
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
9
18
|
}
|
|
10
|
-
listQuery(table) {
|
|
11
|
-
return new QueryNode(lowercaseFirstLetter(plural(table.getEntityName().name)), 'find', [new ParameterNode('option', new ListQueryOptionTypeNode())], new EntityTypeNode(table.getEntityName(), true, false), true);
|
|
19
|
+
listQuery(table, listQueryType) {
|
|
20
|
+
return new QueryNode(lowercaseFirstLetter(plural(table.getEntityName().name)), 'find', listQueryType === 'paging' ? [new ParameterNode('option', new ListQueryOptionTypeNode())] : [], new EntityTypeNode(table.getEntityName(), true, false), true, listQueryType);
|
|
12
21
|
}
|
|
13
22
|
primaryQuery(table) {
|
|
14
23
|
const primaryKeys = table.primaryKey.map(it => table.column(it).fieldName());
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BetweenExpression, BooleanValueExpression, ComparisonExpression, Field, Fn, InExpression, IsNullExpression, Join, JoinType, Literal, ParenthesisExpression, Query, QueryTable, Sort, SortDirection, Value } from './query/query.js';
|
|
2
2
|
export declare const QExpr: {
|
|
3
3
|
readonly conditions: {
|
|
4
|
-
and: (...expr: BooleanValueExpression
|
|
5
|
-
or: (...expr: BooleanValueExpression
|
|
4
|
+
and: (...expr: Array<BooleanValueExpression | undefined | null>) => BooleanValueExpression;
|
|
5
|
+
or: (...expr: Array<BooleanValueExpression | undefined | null>) => BooleanValueExpression;
|
|
6
6
|
eq: (left: Value, right: Value) => ComparisonExpression;
|
|
7
7
|
neq: (left: Value, right: Value) => ComparisonExpression;
|
|
8
8
|
gt: (left: Value, right: Value) => ComparisonExpression;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { QueryNodeKind, } from './query/query.js';
|
|
2
|
+
import { nonNullable } from "../util.js";
|
|
2
3
|
const compound = (expr, operator) => {
|
|
3
|
-
return expr.reduce((acc, current) => ({
|
|
4
|
+
return expr.filter(nonNullable).reduce((acc, current) => ({
|
|
4
5
|
kind: QueryNodeKind.CompoundExpr,
|
|
5
6
|
left: acc,
|
|
6
7
|
operator: operator,
|
|
@@ -14,6 +14,7 @@ export declare enum QueryNodeKind {
|
|
|
14
14
|
Literal = 11,
|
|
15
15
|
Sort = 12
|
|
16
16
|
}
|
|
17
|
+
export declare type LockMode = 'FOR UPDATE' | 'FOR SHARE';
|
|
17
18
|
export declare type Query = {
|
|
18
19
|
select: Select;
|
|
19
20
|
from: QueryTable;
|
|
@@ -21,6 +22,7 @@ export declare type Query = {
|
|
|
21
22
|
sort?: Sort[];
|
|
22
23
|
limit?: number;
|
|
23
24
|
offset?: number;
|
|
25
|
+
lock?: LockMode;
|
|
24
26
|
};
|
|
25
27
|
declare type Select = SelectExpr[];
|
|
26
28
|
export declare const NO_ALIAS: "__SASAT_NO_ALIAS";
|
|
@@ -2,6 +2,13 @@ import { Sql } from './nodeToSql.js';
|
|
|
2
2
|
const getJoin = (from) => {
|
|
3
3
|
return from.joins.flatMap(join => [join, ...getJoin(join.table)]);
|
|
4
4
|
};
|
|
5
|
+
const getLock = (lock) => {
|
|
6
|
+
if (!lock)
|
|
7
|
+
return '';
|
|
8
|
+
if (lock === 'FOR UPDATE')
|
|
9
|
+
return ' FOR UPDATE';
|
|
10
|
+
return ' FOR SHARE';
|
|
11
|
+
};
|
|
5
12
|
export const queryToSql = (query) => {
|
|
6
13
|
const select = query.select.map(Sql.select).join(', ');
|
|
7
14
|
const join = getJoin(query.from).map(Sql.join).join(' ');
|
|
@@ -18,5 +25,6 @@ export const queryToSql = (query) => {
|
|
|
18
25
|
where +
|
|
19
26
|
sort +
|
|
20
27
|
limit +
|
|
21
|
-
offset
|
|
28
|
+
offset +
|
|
29
|
+
getLock(query.lock));
|
|
22
30
|
};
|
|
@@ -2,7 +2,7 @@ import { CommandResponse, RelationMap } from '../index.js';
|
|
|
2
2
|
import { Fields } from './field.js';
|
|
3
3
|
import { SQLExecutor, SqlValueType } from '../db/connectors/dbClient.js';
|
|
4
4
|
import { TableInfo } from './dsl/query/createQueryResolveInfo.js';
|
|
5
|
-
import { BooleanValueExpression, Sort } from './dsl/query/query.js';
|
|
5
|
+
import { BooleanValueExpression, LockMode, Sort } from './dsl/query/query.js';
|
|
6
6
|
export declare type EntityType = Record<string, SqlValueType>;
|
|
7
7
|
export declare type EntityResult<Entity, Identifiable> = Identifiable & Partial<Entity>;
|
|
8
8
|
interface Repository<Entity, Creatable, Identifiable> {
|
|
@@ -16,7 +16,14 @@ export declare type ListQueryOption = {
|
|
|
16
16
|
order?: string;
|
|
17
17
|
asc?: boolean;
|
|
18
18
|
};
|
|
19
|
-
export declare
|
|
19
|
+
export declare type QueryOptions = {
|
|
20
|
+
where?: BooleanValueExpression;
|
|
21
|
+
sort?: Sort[];
|
|
22
|
+
limit?: number;
|
|
23
|
+
offset?: number;
|
|
24
|
+
lock?: LockMode;
|
|
25
|
+
};
|
|
26
|
+
export declare abstract class SasatDBDatasource<Entity extends EntityType, Creatable, Identifiable, EntityFields extends Fields, QueryResult extends Partial<Entity> & Identifiable> implements Repository<Entity, Creatable, Identifiable> {
|
|
20
27
|
protected client: SQLExecutor;
|
|
21
28
|
protected abstract relationMap: RelationMap;
|
|
22
29
|
protected abstract tableInfo: TableInfo;
|
|
@@ -32,27 +39,14 @@ export declare abstract class SasatDBDatasource<Entity extends EntityType, Creat
|
|
|
32
39
|
create(entity: Creatable): Promise<Entity>;
|
|
33
40
|
update(entity: Identifiable & Partial<Entity>): Promise<CommandResponse>;
|
|
34
41
|
delete(entity: Identifiable): Promise<CommandResponse>;
|
|
35
|
-
first(fields?: EntityFields, option?:
|
|
36
|
-
|
|
37
|
-
sort?: Sort[];
|
|
38
|
-
}, context?: any): Promise<EntityResult<Entity, Identifiable> | null>;
|
|
39
|
-
find(fields?: EntityFields, options?: {
|
|
40
|
-
where?: BooleanValueExpression;
|
|
41
|
-
sort?: Sort[];
|
|
42
|
-
limit?: number;
|
|
43
|
-
offset?: number;
|
|
44
|
-
}, context?: unknown): Promise<EntityResult<Entity, Identifiable>[]>;
|
|
42
|
+
first(fields?: EntityFields, option?: Omit<QueryOptions, 'limit' | 'offset'>, context?: any): Promise<QueryResult | null>;
|
|
43
|
+
find(fields?: EntityFields, options?: QueryOptions, context?: unknown): Promise<QueryResult[]>;
|
|
45
44
|
findPageable(paging: {
|
|
46
45
|
numberOfItem: number;
|
|
47
46
|
where?: BooleanValueExpression;
|
|
48
47
|
offset?: number;
|
|
49
48
|
sort?: Sort[];
|
|
50
|
-
}, fields?: EntityFields, options?:
|
|
51
|
-
where?: BooleanValueExpression;
|
|
52
|
-
sort?: Sort[];
|
|
53
|
-
limit?: number;
|
|
54
|
-
offset?: number;
|
|
55
|
-
}, context?: unknown): Promise<EntityResult<Entity, Identifiable>[]>;
|
|
49
|
+
}, fields?: EntityFields, options?: QueryOptions, context?: unknown): Promise<QueryResult[]>;
|
|
56
50
|
private executeQuery;
|
|
57
51
|
private createIdentifiableExpression;
|
|
58
52
|
}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import { BooleanValueExpression, Query
|
|
1
|
+
import { BooleanValueExpression, Query } from '../dsl/query/query.js';
|
|
2
2
|
import { SQLExecutor } from '../../db/connectors/dbClient.js';
|
|
3
3
|
import { RelationMap, TableInfo } from '../dsl/query/createQueryResolveInfo.js';
|
|
4
4
|
import { Fields } from '../field.js';
|
|
5
5
|
import { QueryResolveInfo } from '../dsl/query/sql/hydrate.js';
|
|
6
|
-
import { ListQueryOption } from '../sasatDBDatasource.js';
|
|
7
|
-
declare type QueryOptions = {
|
|
8
|
-
where?: BooleanValueExpression;
|
|
9
|
-
sort?: Sort[];
|
|
10
|
-
limit?: number;
|
|
11
|
-
offset?: number;
|
|
12
|
-
};
|
|
6
|
+
import { ListQueryOption, QueryOptions } from '../sasatDBDatasource.js';
|
|
13
7
|
export declare const createQuery: (baseTableName: string, fields: Fields, options: QueryOptions | undefined, tableInfo: TableInfo, relationMap: RelationMap, context?: any) => Query;
|
|
14
8
|
declare type PagingOption = ListQueryOption & {
|
|
15
9
|
where?: BooleanValueExpression;
|
|
@@ -12,8 +12,10 @@ export const createQuery = (baseTableName, fields, options, tableInfo, relationM
|
|
|
12
12
|
table.tableAlias = tableAlias;
|
|
13
13
|
tableCount++;
|
|
14
14
|
const info = tableInfo[tableName];
|
|
15
|
-
select.push(...unique([
|
|
16
|
-
.
|
|
15
|
+
select.push(...unique([
|
|
16
|
+
...table.fields.filter(notTypeName),
|
|
17
|
+
...info.identifiableKeys,
|
|
18
|
+
]).map(it => {
|
|
17
19
|
const realName = info.columnMap[it] || it;
|
|
18
20
|
return QExpr.field(tableAlias, realName, tableAlias + SELECT_ALIAS_SEPARATOR + it);
|
|
19
21
|
}));
|
|
@@ -33,7 +35,9 @@ export const createQuery = (baseTableName, fields, options, tableInfo, relationM
|
|
|
33
35
|
export const createPagingInnerQuery = (tableName, tableAlias, fields, option, tableInfo) => {
|
|
34
36
|
const map = tableInfo[tableName].columnMap;
|
|
35
37
|
return {
|
|
36
|
-
select: fields.fields
|
|
38
|
+
select: fields.fields
|
|
39
|
+
.filter(notTypeName)
|
|
40
|
+
.map(it => QExpr.field(tableAlias, map[it])),
|
|
37
41
|
from: QExpr.table(tableName, [], tableAlias),
|
|
38
42
|
limit: option.numberOfItem,
|
|
39
43
|
offset: option.offset,
|
package/lib/runtime/util.d.ts
CHANGED
package/lib/runtime/util.js
CHANGED