@memberjunction/codegen-lib 1.0.6 → 1.0.7-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced_generation.d.ts +3 -0
- package/dist/advanced_generation.d.ts.map +1 -1
- package/dist/advanced_generation.js +39 -26
- package/dist/advanced_generation.js.map +1 -1
- package/dist/angular_client_codegen.d.ts +45 -2
- package/dist/angular_client_codegen.d.ts.map +1 -1
- package/dist/angular_client_codegen.js +423 -399
- package/dist/angular_client_codegen.js.map +1 -1
- package/dist/createNewUser.d.ts +6 -1
- package/dist/createNewUser.d.ts.map +1 -1
- package/dist/createNewUser.js +68 -53
- package/dist/createNewUser.js.map +1 -1
- package/dist/dbSchema.d.ts +10 -3
- package/dist/dbSchema.d.ts.map +1 -1
- package/dist/dbSchema.js +144 -130
- package/dist/dbSchema.js.map +1 -1
- package/dist/entity_subclasses_codegen.d.ts +11 -6
- package/dist/entity_subclasses_codegen.d.ts.map +1 -1
- package/dist/entity_subclasses_codegen.js +144 -131
- package/dist/entity_subclasses_codegen.js.map +1 -1
- package/dist/graphql_server_codegen.d.ts +28 -5
- package/dist/graphql_server_codegen.d.ts.map +1 -1
- package/dist/graphql_server_codegen.js +552 -531
- package/dist/graphql_server_codegen.js.map +1 -1
- package/dist/logging.d.ts +20 -0
- package/dist/logging.d.ts.map +1 -1
- package/dist/logging.js +61 -26
- package/dist/logging.js.map +1 -1
- package/dist/manageMetadata.d.ts +128 -7
- package/dist/manageMetadata.d.ts.map +1 -1
- package/dist/manageMetadata.js +992 -898
- package/dist/manageMetadata.js.map +1 -1
- package/dist/runCodeGen.d.ts +16 -0
- package/dist/runCodeGen.d.ts.map +1 -1
- package/dist/runCodeGen.js +185 -140
- package/dist/runCodeGen.js.map +1 -1
- package/dist/runCommand.d.ts +7 -2
- package/dist/runCommand.d.ts.map +1 -1
- package/dist/runCommand.js +104 -90
- package/dist/runCommand.js.map +1 -1
- package/dist/sql.d.ts +21 -16
- package/dist/sql.d.ts.map +1 -1
- package/dist/sql.js +98 -87
- package/dist/sql.js.map +1 -1
- package/dist/sql_codegen.d.ts +56 -13
- package/dist/sql_codegen.d.ts.map +1 -1
- package/dist/sql_codegen.js +836 -795
- package/dist/sql_codegen.js.map +1 -1
- package/dist/util.js +0 -2
- package/dist/util.js.map +1 -1
- package/package.json +32 -32
- package/readme.md +2 -2
- package/dist/graphql_client_codegen.d.ts +0 -4
- package/dist/graphql_client_codegen.js +0 -161
- package/dist/graphql_client_codegen.js.map +0 -1
- package/dist/react_client_codegen.d.ts +0 -4
- package/dist/react_client_codegen.js +0 -147
- package/dist/react_client_codegen.js.map +0 -1
|
@@ -1,575 +1,596 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
2
8
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
9
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
10
|
};
|
|
5
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
12
|
+
exports.GraphQLServerGeneratorBase = void 0;
|
|
7
13
|
const core_1 = require("@memberjunction/core");
|
|
8
14
|
const fs_1 = __importDefault(require("fs"));
|
|
9
15
|
const path_1 = __importDefault(require("path"));
|
|
10
16
|
const logging_1 = require("./logging");
|
|
11
17
|
const config_1 = require("./config");
|
|
12
18
|
const util_1 = require("./util");
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
const global_1 = require("@memberjunction/global");
|
|
20
|
+
/**
|
|
21
|
+
* This class is responsible for generating the GraphQL Server resolvers and types for the entities, you can sub-class this class to extend/modify the logic, make sure to use @memberjunction/global RegisterClass decorator
|
|
22
|
+
* so that your class is used.
|
|
23
|
+
*/
|
|
24
|
+
let GraphQLServerGeneratorBase = class GraphQLServerGeneratorBase {
|
|
25
|
+
constructor() {
|
|
26
|
+
this._graphQLTypeSuffix = '_';
|
|
27
|
+
}
|
|
28
|
+
generateGraphQLServerCode(entities, outputDirectory, generatedEntitiesImportLibrary, excludeRelatedEntitiesExternalToSchema) {
|
|
29
|
+
let sRet = '';
|
|
30
|
+
try {
|
|
31
|
+
sRet = this.generateAllEntitiesServerFileHeader(entities, generatedEntitiesImportLibrary);
|
|
32
|
+
for (let i = 0; i < entities.length; ++i) {
|
|
33
|
+
sRet += this.generateServerEntityString(entities[i], false, generatedEntitiesImportLibrary, excludeRelatedEntitiesExternalToSchema);
|
|
34
|
+
}
|
|
35
|
+
(0, util_1.makeDir)(outputDirectory);
|
|
36
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDirectory, 'generated.ts'), sRet);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
(0, logging_1.logError)(err);
|
|
41
|
+
return false;
|
|
19
42
|
}
|
|
20
|
-
(0, util_1.makeDir)(outputDirectory);
|
|
21
|
-
fs_1.default.writeFileSync(path_1.default.join(outputDirectory, 'generated.ts'), sRet);
|
|
22
|
-
return true;
|
|
23
43
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
44
|
+
/**
|
|
45
|
+
* The suffix to append to the GraphQL Type name, default is an underscore, override this property in your sub-class to change the suffix
|
|
46
|
+
*/
|
|
47
|
+
get GraphQLTypeSuffix() {
|
|
48
|
+
return this._graphQLTypeSuffix;
|
|
27
49
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
generateServerEntityString(entity, includeFileHeader, generatedEntitiesImportLibrary, excludeRelatedEntitiesExternalToSchema) {
|
|
51
|
+
let sEntityOutput = '';
|
|
52
|
+
try {
|
|
53
|
+
const md = new core_1.Metadata();
|
|
54
|
+
const fields = entity.Fields;
|
|
55
|
+
const serverGraphQLTypeName = entity.ClassName + this.GraphQLTypeSuffix;
|
|
56
|
+
if (includeFileHeader)
|
|
57
|
+
sEntityOutput = this.generateEntitySpecificServerFileHeader(entity, generatedEntitiesImportLibrary, excludeRelatedEntitiesExternalToSchema);
|
|
58
|
+
sEntityOutput += this.generateServerEntityHeader(entity, serverGraphQLTypeName);
|
|
59
|
+
// now generate the fields by looping through the fields collection from the database
|
|
60
|
+
for (let j = 0; j < fields.length; ++j) {
|
|
61
|
+
sEntityOutput += this.generateServerField(fields[j]);
|
|
62
|
+
}
|
|
63
|
+
for (let j = 0; j < entity.RelatedEntities.length; ++j) {
|
|
64
|
+
const r = entity.RelatedEntities[j];
|
|
65
|
+
const re = md.Entities.find(e => e.Name.toLowerCase() === r.RelatedEntity.toLowerCase());
|
|
66
|
+
// only include the relationship if we are IncludeInAPI for the related entity
|
|
67
|
+
if (re.IncludeInAPI) {
|
|
68
|
+
if (!excludeRelatedEntitiesExternalToSchema || re.SchemaName === entity.SchemaName) {
|
|
69
|
+
// only include the relationship if either we are NOT excluding related entities external to the schema
|
|
70
|
+
// or if the related entity is in the same schema as the current entity
|
|
71
|
+
sEntityOutput += this.generateServerRelationship(md, entity.RelatedEntities[j]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
sEntityOutput += `// Relationship to ${r.RelatedEntity} is not included in the API because it is not marked as IncludeInAPI\n`;
|
|
53
76
|
}
|
|
54
77
|
}
|
|
55
|
-
|
|
56
|
-
|
|
78
|
+
// finally, close it up with the footer
|
|
79
|
+
sEntityOutput += this.generateServerEntityFooter(entity);
|
|
80
|
+
sEntityOutput += this.generateServerGraphQLResolver(entity, serverGraphQLTypeName, excludeRelatedEntitiesExternalToSchema);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
(0, logging_1.logError)(err);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
return sEntityOutput;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
generateAllEntitiesServerFileHeader(entities, importLibrary) {
|
|
90
|
+
let sRet = `/********************************************************************************
|
|
91
|
+
* ALL ENTITIES - TypeGraphQL Type Class Definition - AUTO GENERATED FILE
|
|
92
|
+
* Generated Entities and Resolvers for Server
|
|
93
|
+
*
|
|
94
|
+
* GENERATED: ${new Date().toLocaleString()}
|
|
95
|
+
*
|
|
96
|
+
* >>> DO NOT MODIFY THIS FILE!!!!!!!!!!!!
|
|
97
|
+
* >>> YOUR CHANGES WILL BE OVERWRITTEN
|
|
98
|
+
* >>> THE NEXT TIME THIS FILE IS GENERATED
|
|
99
|
+
*
|
|
100
|
+
**********************************************************************************/
|
|
101
|
+
import { Arg, Ctx, Int, Query, Resolver, Field, Float, ObjectType, FieldResolver, Root, InputType, Mutation,
|
|
102
|
+
PubSub, PubSubEngine, ResolverBase, RunViewByIDInput, RunViewByNameInput, RunDynamicViewInput } from '@memberjunction/server';
|
|
103
|
+
import { Metadata, EntityPermissionType } from '@memberjunction/core'
|
|
104
|
+
import { AppContext } from '@memberjunction/server';
|
|
105
|
+
|
|
106
|
+
import { MaxLength } from 'class-validator';
|
|
107
|
+
import { DataSource } from 'typeorm';
|
|
108
|
+
${importLibrary.trim().toLowerCase() === '@memberjunction/core-entities' ? `import { mj_core_schema } from '../config';\n` : ''}
|
|
109
|
+
import * as mj_core_schema_server_object_types from '@memberjunction/server'
|
|
110
|
+
|
|
111
|
+
import { ${entities.map(e => `${e.ClassName}Entity`).join(', ')} } from '${importLibrary}';
|
|
112
|
+
`;
|
|
113
|
+
return sRet;
|
|
114
|
+
}
|
|
115
|
+
generateEntitySpecificServerFileHeader(entity, importLibrary, excludeRelatedEntitiesExternalToSchema) {
|
|
116
|
+
const md = new core_1.Metadata();
|
|
117
|
+
let sRet = `/********************************************************************************
|
|
118
|
+
* ${entity.Name} TypeORM/TypeGraphQL Type Class Definition - AUTO GENERATED FILE
|
|
119
|
+
*
|
|
120
|
+
* GENERATED: ${new Date().toLocaleString()}
|
|
121
|
+
*
|
|
122
|
+
* >>> DO NOT MODIFY THIS FILE!!!!!!!!!!!!
|
|
123
|
+
* >>> YOUR CHANGES WILL BE OVERWRITTEN
|
|
124
|
+
* >>> THE NEXT TIME THIS FILE IS GENERATED
|
|
125
|
+
*
|
|
126
|
+
**********************************************************************************/
|
|
127
|
+
import { MaxLength } from 'class-validator';
|
|
128
|
+
import { Field, ${entity._floatCount > 0 ? 'Float, ' : ''}Int, ObjectType } from '@memberjunction/server';
|
|
129
|
+
import { ${`${entity.ClassName}Entity`} } from '${importLibrary}';
|
|
130
|
+
`;
|
|
131
|
+
for (let i = 0; i < entity.RelatedEntities.length; ++i) {
|
|
132
|
+
const r = entity.RelatedEntities[i];
|
|
133
|
+
const re = md.Entities.find(e => e.Name.toLowerCase() == r.RelatedEntity.toLowerCase());
|
|
134
|
+
if (!excludeRelatedEntitiesExternalToSchema || re.SchemaName === entity.SchemaName) {
|
|
135
|
+
// we only include entities that are in the same schema as the current entity
|
|
136
|
+
// OR if we are not excluding related entities external to the schema
|
|
137
|
+
const tableName = entity.RelatedEntities[i].RelatedEntityBaseTableCodeName;
|
|
138
|
+
sRet += `\nimport ${tableName} from './${tableName}';`;
|
|
57
139
|
}
|
|
58
140
|
}
|
|
59
|
-
|
|
60
|
-
sEntityOutput += generateServerEntityFooter(entity);
|
|
61
|
-
sEntityOutput += generateServerGraphQLResolver(entity, serverGraphQLTypeName, excludeRelatedEntitiesExternalToSchema);
|
|
141
|
+
return sRet;
|
|
62
142
|
}
|
|
63
|
-
|
|
64
|
-
(0
|
|
143
|
+
generateServerEntityHeader(entity, serverGraphQLTypeName) {
|
|
144
|
+
let sDescription = entity.Description?.trim().length > 0 ? entity.Description : '';
|
|
145
|
+
if (sDescription.includes("'"))
|
|
146
|
+
sDescription = sDescription.replace(/'/g, "\\'");
|
|
147
|
+
return `
|
|
148
|
+
|
|
149
|
+
//****************************************************************************
|
|
150
|
+
// ENTITY CLASS for ${entity.Name}
|
|
151
|
+
//****************************************************************************
|
|
152
|
+
@ObjectType(${sDescription.length > 0 ? `{ description: '${sDescription}' }` : ''})
|
|
153
|
+
export class ${serverGraphQLTypeName} {`;
|
|
65
154
|
}
|
|
66
|
-
|
|
67
|
-
|
|
155
|
+
generateServerEntityFooter(entity) {
|
|
156
|
+
if (!entity)
|
|
157
|
+
(0, logging_1.logError)("entity parameter must be passed in to generateServerEntityFooter()");
|
|
158
|
+
return `\n}`;
|
|
68
159
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
*
|
|
109
|
-
**********************************************************************************/
|
|
110
|
-
import { MaxLength } from 'class-validator';
|
|
111
|
-
import { Field, ${entity._floatCount > 0 ? 'Float, ' : ''}Int, ObjectType } from '@memberjunction/server';
|
|
112
|
-
import { ${`${entity.ClassName}Entity`} } from '${importLibrary}';
|
|
113
|
-
`;
|
|
114
|
-
for (let i = 0; i < entity.RelatedEntities.length; ++i) {
|
|
115
|
-
const r = entity.RelatedEntities[i];
|
|
116
|
-
const re = md.Entities.find(e => e.Name.toLowerCase() == r.RelatedEntity.toLowerCase());
|
|
117
|
-
if (!excludeRelatedEntitiesExternalToSchema || re.SchemaName === entity.SchemaName) {
|
|
118
|
-
// we only include entities that are in the same schema as the current entity
|
|
119
|
-
// OR if we are not excluding related entities external to the schema
|
|
120
|
-
const tableName = entity.RelatedEntities[i].RelatedEntityBaseTableCodeName;
|
|
121
|
-
sRet += `\nimport ${tableName} from './${tableName}';`;
|
|
160
|
+
generateServerField(fieldInfo) {
|
|
161
|
+
const fieldString = this.getTypeGraphQLFieldString(fieldInfo);
|
|
162
|
+
let fieldOptions = '';
|
|
163
|
+
if (fieldInfo.AllowsNull)
|
|
164
|
+
fieldOptions += 'nullable: true';
|
|
165
|
+
if (fieldInfo.Description !== null && fieldInfo.Description.trim().length > 0)
|
|
166
|
+
fieldOptions += (fieldOptions.length > 0 ? ', ' : '') + `description: '${fieldInfo.Description.replace(/'/g, "\\'")}'`;
|
|
167
|
+
return `
|
|
168
|
+
@Field(${fieldString}${fieldOptions.length > 0 ? (fieldString == '' ? '' : ', ') + `{${fieldOptions}}` : ''}) ${fieldInfo.Length > 0 && fieldString == '' /*string*/ ? '\n @MaxLength(' + fieldInfo.Length + ')' : ''}
|
|
169
|
+
${fieldInfo.CodeName}${fieldInfo.AllowsNull ? '?' : ''}: ${(0, core_1.TypeScriptTypeFromSQLType)(fieldInfo.Type)};
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
getTypeGraphQLFieldString(fieldInfo) {
|
|
173
|
+
switch (fieldInfo.Type.toLowerCase()) {
|
|
174
|
+
case 'text':
|
|
175
|
+
case 'char':
|
|
176
|
+
case 'varchar':
|
|
177
|
+
case 'ntext':
|
|
178
|
+
case 'nchar':
|
|
179
|
+
case 'nvarchar':
|
|
180
|
+
case 'uniqueidentifier': //treat this as a string
|
|
181
|
+
return '';
|
|
182
|
+
case 'datetime':
|
|
183
|
+
case 'datetimeoffset':
|
|
184
|
+
case 'date':
|
|
185
|
+
case 'time':
|
|
186
|
+
return '';
|
|
187
|
+
case 'bit':
|
|
188
|
+
return "() => Boolean";
|
|
189
|
+
case 'decimal':
|
|
190
|
+
case 'numeric':
|
|
191
|
+
case 'float':
|
|
192
|
+
case 'real':
|
|
193
|
+
case 'money':
|
|
194
|
+
case 'smallmoney':
|
|
195
|
+
fieldInfo.IsFloat = true; // used by calling functions to determine if we need to import Float
|
|
196
|
+
return '() => Float';
|
|
197
|
+
default:
|
|
198
|
+
return '() => Int';
|
|
122
199
|
}
|
|
123
200
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//****************************************************************************
|
|
134
|
-
// ENTITY CLASS for ${entity.Name}
|
|
135
|
-
//****************************************************************************
|
|
136
|
-
@ObjectType(${sDescription.length > 0 ? `{ description: '${sDescription}' }` : ''})
|
|
137
|
-
export class ${serverGraphQLTypeName} {`;
|
|
138
|
-
}
|
|
139
|
-
function generateServerEntityFooter(entity) {
|
|
140
|
-
if (!entity)
|
|
141
|
-
(0, logging_1.logError)("entity parameter must be passed in to generateServerEntityFooter()");
|
|
142
|
-
return `\n}`;
|
|
143
|
-
}
|
|
144
|
-
function generateServerField(fieldInfo) {
|
|
145
|
-
const fieldString = getTypeGraphQLFieldString(fieldInfo);
|
|
146
|
-
let fieldOptions = '';
|
|
147
|
-
if (fieldInfo.AllowsNull)
|
|
148
|
-
fieldOptions += 'nullable: true';
|
|
149
|
-
if (fieldInfo.Description !== null && fieldInfo.Description.trim().length > 0)
|
|
150
|
-
fieldOptions += (fieldOptions.length > 0 ? ', ' : '') + `description: '${fieldInfo.Description.replace(/'/g, "\\'")}'`;
|
|
151
|
-
return `
|
|
152
|
-
@Field(${fieldString}${fieldOptions.length > 0 ? (fieldString == '' ? '' : ', ') + `{${fieldOptions}}` : ''}) ${fieldInfo.Length > 0 && fieldString == '' /*string*/ ? '\n @MaxLength(' + fieldInfo.Length + ')' : ''}
|
|
153
|
-
${fieldInfo.CodeName}${fieldInfo.AllowsNull ? '?' : ''}: ${(0, core_1.TypeScriptTypeFromSQLType)(fieldInfo.Type)};
|
|
201
|
+
generateServerRelationship(md, r) {
|
|
202
|
+
const re = md.Entities.find(e => e.Name.toLowerCase() === r.RelatedEntity.toLowerCase());
|
|
203
|
+
const classPackagePrefix = re.SchemaName === config_1.mjCoreSchema ? 'mj_core_schema_server_object_types.' : '';
|
|
204
|
+
const relatedClassName = classPackagePrefix + r.RelatedEntityBaseTableCodeName;
|
|
205
|
+
if (r.Type.toLowerCase().trim() == 'one to many') {
|
|
206
|
+
return `
|
|
207
|
+
@Field(() => [${relatedClassName + this.GraphQLTypeSuffix}])
|
|
208
|
+
${r.RelatedEntityCodeName}Array: ${relatedClassName + this.GraphQLTypeSuffix}[]; // Link to ${r.RelatedEntityCodeName}
|
|
154
209
|
`;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
case 'nchar':
|
|
163
|
-
case 'nvarchar':
|
|
164
|
-
case 'uniqueidentifier': //treat this as a string
|
|
165
|
-
return '';
|
|
166
|
-
case 'datetime':
|
|
167
|
-
case 'datetimeoffset':
|
|
168
|
-
case 'date':
|
|
169
|
-
case 'time':
|
|
170
|
-
return '';
|
|
171
|
-
case 'bit':
|
|
172
|
-
return "() => Boolean";
|
|
173
|
-
case 'decimal':
|
|
174
|
-
case 'numeric':
|
|
175
|
-
case 'float':
|
|
176
|
-
case 'real':
|
|
177
|
-
case 'money':
|
|
178
|
-
case 'smallmoney':
|
|
179
|
-
fieldInfo.IsFloat = true; // used by calling functions to determine if we need to import Float
|
|
180
|
-
return '() => Float';
|
|
181
|
-
default:
|
|
182
|
-
return '() => Int';
|
|
210
|
+
}
|
|
211
|
+
else { // many to many
|
|
212
|
+
return `
|
|
213
|
+
@Field(() => [${relatedClassName + this.GraphQLTypeSuffix}])
|
|
214
|
+
${r.RelatedEntityCodeName}Array: ${relatedClassName + this.GraphQLTypeSuffix}[]; // Link to ${r.RelatedEntity}
|
|
215
|
+
`;
|
|
216
|
+
}
|
|
183
217
|
}
|
|
218
|
+
generateServerGraphQLResolver(entity, serverGraphQLTypeName, excludeRelatedEntitiesExternalToSchema) {
|
|
219
|
+
const md = new core_1.Metadata();
|
|
220
|
+
let sRet = '';
|
|
221
|
+
// we only generate resolvers for entities that have a primary key field
|
|
222
|
+
if (entity.PrimaryKeys.length > 0) {
|
|
223
|
+
// first add in the base resolver query to lookup by ID for all entities
|
|
224
|
+
const auditAccessCode = entity.AuditRecordAccess ? `
|
|
225
|
+
this.createRecordAccessAuditLogRecord(userPayload, '${entity.Name}', ${entity.PrimaryKey.Name})` : '';
|
|
226
|
+
sRet = `
|
|
227
|
+
//****************************************************************************
|
|
228
|
+
// RESOLVER for ${entity.Name}
|
|
229
|
+
//****************************************************************************
|
|
230
|
+
@ObjectType()
|
|
231
|
+
export class Run${entity.BaseTableCodeName}ViewResult {
|
|
232
|
+
@Field(() => [${serverGraphQLTypeName}])
|
|
233
|
+
Results: ${serverGraphQLTypeName}[];
|
|
234
|
+
|
|
235
|
+
@Field(() => Int, {nullable: true})
|
|
236
|
+
UserViewRunID?: number;
|
|
237
|
+
|
|
238
|
+
@Field(() => Int, {nullable: true})
|
|
239
|
+
RowCount: number;
|
|
240
|
+
|
|
241
|
+
@Field(() => Int, {nullable: true})
|
|
242
|
+
TotalRowCount: number;
|
|
243
|
+
|
|
244
|
+
@Field(() => Int, {nullable: true})
|
|
245
|
+
ExecutionTime: number;
|
|
246
|
+
|
|
247
|
+
@Field({nullable: true})
|
|
248
|
+
ErrorMessage?: string;
|
|
249
|
+
|
|
250
|
+
@Field(() => Boolean, {nullable: false})
|
|
251
|
+
Success: boolean;
|
|
184
252
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return
|
|
191
|
-
@Field(() => [${relatedClassName + _graphQLTypeSuffix}])
|
|
192
|
-
${r.RelatedEntityCodeName}Array: ${relatedClassName + _graphQLTypeSuffix}[]; // Link to ${r.RelatedEntityCodeName}
|
|
193
|
-
`;
|
|
194
|
-
}
|
|
195
|
-
else { // many to many
|
|
196
|
-
return `
|
|
197
|
-
@Field(() => [${relatedClassName + _graphQLTypeSuffix}])
|
|
198
|
-
${r.RelatedEntityCodeName}Array: ${relatedClassName + _graphQLTypeSuffix}[]; // Link to ${r.RelatedEntity}
|
|
199
|
-
`;
|
|
253
|
+
|
|
254
|
+
@Resolver(${serverGraphQLTypeName})
|
|
255
|
+
export class ${entity.BaseTableCodeName}Resolver${entity.CustomResolverAPI ? 'Base' : ''} extends ResolverBase {
|
|
256
|
+
@Query(() => Run${entity.BaseTableCodeName}ViewResult)
|
|
257
|
+
async Run${entity.BaseTableCodeName}ViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
258
|
+
return super.RunViewByIDGeneric(input, dataSource, userPayload, pubSub);
|
|
200
259
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
//****************************************************************************
|
|
212
|
-
// RESOLVER for ${entity.Name}
|
|
213
|
-
//****************************************************************************
|
|
214
|
-
@ObjectType()
|
|
215
|
-
export class Run${entity.BaseTableCodeName}ViewResult {
|
|
216
|
-
@Field(() => [${serverGraphQLTypeName}])
|
|
217
|
-
Results: ${serverGraphQLTypeName}[];
|
|
218
|
-
|
|
219
|
-
@Field(() => Int, {nullable: true})
|
|
220
|
-
UserViewRunID?: number;
|
|
221
|
-
|
|
222
|
-
@Field(() => Int, {nullable: true})
|
|
223
|
-
RowCount: number;
|
|
224
|
-
|
|
225
|
-
@Field(() => Int, {nullable: true})
|
|
226
|
-
TotalRowCount: number;
|
|
227
|
-
|
|
228
|
-
@Field(() => Int, {nullable: true})
|
|
229
|
-
ExecutionTime: number;
|
|
230
|
-
|
|
231
|
-
@Field({nullable: true})
|
|
232
|
-
ErrorMessage?: string;
|
|
233
|
-
|
|
234
|
-
@Field(() => Boolean, {nullable: false})
|
|
235
|
-
Success: boolean;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
@Resolver(${serverGraphQLTypeName})
|
|
239
|
-
export class ${entity.BaseTableCodeName}Resolver${entity.CustomResolverAPI ? 'Base' : ''} extends ResolverBase {
|
|
240
|
-
@Query(() => Run${entity.BaseTableCodeName}ViewResult)
|
|
241
|
-
async Run${entity.BaseTableCodeName}ViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
242
|
-
return super.RunViewByIDGeneric(input, dataSource, userPayload, pubSub);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
@Query(() => Run${entity.BaseTableCodeName}ViewResult)
|
|
246
|
-
async Run${entity.BaseTableCodeName}ViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
247
|
-
return super.RunViewByNameGeneric(input, dataSource, userPayload, pubSub);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
@Query(() => Run${entity.BaseTableCodeName}ViewResult)
|
|
251
|
-
async Run${entity.BaseTableCodeName}DynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
252
|
-
input.EntityName = '${entity.Name}';
|
|
253
|
-
return super.RunDynamicViewGeneric(input, dataSource, userPayload, pubSub);
|
|
260
|
+
|
|
261
|
+
@Query(() => Run${entity.BaseTableCodeName}ViewResult)
|
|
262
|
+
async Run${entity.BaseTableCodeName}ViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
263
|
+
return super.RunViewByNameGeneric(input, dataSource, userPayload, pubSub);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@Query(() => Run${entity.BaseTableCodeName}ViewResult)
|
|
267
|
+
async Run${entity.BaseTableCodeName}DynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
268
|
+
input.EntityName = '${entity.Name}';
|
|
269
|
+
return super.RunDynamicViewGeneric(input, dataSource, userPayload, pubSub);
|
|
254
270
|
}`;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
@Query(() => ${serverGraphQLTypeName}, { nullable: true })
|
|
268
|
-
async ${entity.BaseTableCodeName}(${graphQLPKEYArgs}, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<${serverGraphQLTypeName} | null> {
|
|
269
|
-
this.CheckUserReadPermissions('${entity.Name}', userPayload);
|
|
270
|
-
const sSQL = \`SELECT * FROM [${schemaName(entity)}].[${entity.BaseView}] WHERE ${whereClause} \` + this.getRowLevelSecurityWhereClause('${entity.Name}', userPayload, EntityPermissionType.Read, 'AND');${auditAccessCode}
|
|
271
|
-
const result = this.MapFieldNamesToCodeNames('${entity.Name}', await dataSource.query(sSQL).then((r) => r && r.length > 0 ? r[0] : {}))
|
|
272
|
-
return result;
|
|
273
|
-
}
|
|
274
|
-
`;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
@Query(() => [${serverGraphQLTypeName}])
|
|
279
|
-
async All${entity.CodeName}(@Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
280
|
-
this.CheckUserReadPermissions('${entity.Name}', userPayload);
|
|
281
|
-
const sSQL = \`SELECT * FROM [${schemaName(entity)}].[${entity.BaseView}]\` + this.getRowLevelSecurityWhereClause('${entity.Name}', userPayload, EntityPermissionType.Read, ' WHERE');
|
|
282
|
-
const result = this.ArrayMapFieldNamesToCodeNames('${entity.Name}', await dataSource.query(sSQL));
|
|
283
|
-
return result;
|
|
284
|
-
}
|
|
285
|
-
`;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
271
|
+
let graphQLPKEYArgs = '';
|
|
272
|
+
let whereClause = '';
|
|
273
|
+
for (let i = 0; i < entity.PrimaryKeys.length; i++) {
|
|
274
|
+
const pk = entity.PrimaryKeys[i];
|
|
275
|
+
const idQuotes = pk.NeedsQuotes ? "'" : '';
|
|
276
|
+
graphQLPKEYArgs += (graphQLPKEYArgs.length > 0 ? ', ' : '');
|
|
277
|
+
graphQLPKEYArgs += `@Arg('${pk.CodeName}', () => ${pk.GraphQLType}) `;
|
|
278
|
+
graphQLPKEYArgs += `${pk.CodeName}: ${pk.TSType}`;
|
|
279
|
+
whereClause += (whereClause.length > 0 ? ' AND ' : '');
|
|
280
|
+
whereClause += `[${pk.CodeName}]=${idQuotes}\${${pk.CodeName}}${idQuotes}`;
|
|
281
|
+
}
|
|
282
|
+
sRet += `
|
|
283
|
+
@Query(() => ${serverGraphQLTypeName}, { nullable: true })
|
|
284
|
+
async ${entity.BaseTableCodeName}(${graphQLPKEYArgs}, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<${serverGraphQLTypeName} | null> {
|
|
285
|
+
this.CheckUserReadPermissions('${entity.Name}', userPayload);
|
|
286
|
+
const sSQL = \`SELECT * FROM [${this.schemaName(entity)}].[${entity.BaseView}] WHERE ${whereClause} \` + this.getRowLevelSecurityWhereClause('${entity.Name}', userPayload, EntityPermissionType.Read, 'AND');${auditAccessCode}
|
|
287
|
+
const result = this.MapFieldNamesToCodeNames('${entity.Name}', await dataSource.query(sSQL).then((r) => r && r.length > 0 ? r[0] : {}))
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
`;
|
|
291
|
+
if (entity.AllowAllRowsAPI) {
|
|
292
|
+
// this entity allows a query to return all rows, so include that type of query next
|
|
293
|
+
sRet += `
|
|
294
|
+
@Query(() => [${serverGraphQLTypeName}])
|
|
295
|
+
async All${entity.CodeName}(@Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
296
|
+
this.CheckUserReadPermissions('${entity.Name}', userPayload);
|
|
297
|
+
const sSQL = \`SELECT * FROM [${this.schemaName(entity)}].[${entity.BaseView}]\` + this.getRowLevelSecurityWhereClause('${entity.Name}', userPayload, EntityPermissionType.Read, ' WHERE');
|
|
298
|
+
const result = this.ArrayMapFieldNamesToCodeNames('${entity.Name}', await dataSource.query(sSQL));
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
`;
|
|
302
|
+
}
|
|
303
|
+
// now, generate the FieldResolvers for each of the one-to-many relationships
|
|
304
|
+
for (let i = 0; i < entity.RelatedEntities.length; i++) {
|
|
305
|
+
const r = entity.RelatedEntities[i];
|
|
306
|
+
const re = md.Entities.find(e => e.Name.toLowerCase() === r.RelatedEntity.toLowerCase());
|
|
307
|
+
// only include the relationship if we are IncludeInAPI for the related entity
|
|
308
|
+
if (re.IncludeInAPI) {
|
|
309
|
+
if (!excludeRelatedEntitiesExternalToSchema || re.SchemaName === entity.SchemaName) {
|
|
310
|
+
// only include the relationship if either we are NOT excluding related entities external to the schema
|
|
311
|
+
// or if the related entity is in the same schema as the current entity
|
|
312
|
+
if (r.Type.toLowerCase().trim() == 'many to many')
|
|
313
|
+
sRet += this.generateManyToManyFieldResolver(entity, r);
|
|
314
|
+
else
|
|
315
|
+
sRet += this.generateOneToManyFieldResolver(entity, r);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
sRet += `// Relationship to ${r.RelatedEntity} is not included in the API because it is not marked as IncludeInAPI\n`;
|
|
300
320
|
}
|
|
301
321
|
}
|
|
302
|
-
|
|
303
|
-
|
|
322
|
+
// now do the mutations
|
|
323
|
+
const sInputType = this.generateServerGraphQLInputType(entity);
|
|
324
|
+
if (sInputType !== '') {
|
|
325
|
+
// only generate mutations if we have input type, because otherwsie we don't need em
|
|
326
|
+
sRet += this.generateServerGraphQLMutations(entity, serverGraphQLTypeName);
|
|
327
|
+
}
|
|
328
|
+
sRet += `\n}`;
|
|
329
|
+
if (sInputType !== '') {
|
|
330
|
+
sRet = sInputType + sRet; // put the input type before the resolver as the decorators have to be evaluated ahead of their use in the resolver
|
|
304
331
|
}
|
|
305
332
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
sRet += `\n}`;
|
|
313
|
-
if (sInputType !== '') {
|
|
314
|
-
sRet = sInputType + sRet; // put the input type before the resolver as the decorators have to be evaluated ahead of their use in the resolver
|
|
333
|
+
return sRet;
|
|
334
|
+
}
|
|
335
|
+
schemaName(entity) {
|
|
336
|
+
if (entity.SchemaName === config_1.mjCoreSchema) {
|
|
337
|
+
return '${Metadata.Provider.ConfigData.MJCoreSchemaName}';
|
|
315
338
|
}
|
|
339
|
+
else
|
|
340
|
+
return entity.SchemaName; // put the actual schema name in
|
|
316
341
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
342
|
+
generateServerGraphQLInputType(entity) {
|
|
343
|
+
let sRet = '';
|
|
344
|
+
if (entity.AllowCreateAPI)
|
|
345
|
+
sRet += this.generateServerGraphQLInputTypeInner(entity, false, 'Create');
|
|
346
|
+
if (entity.AllowUpdateAPI)
|
|
347
|
+
sRet += this.generateServerGraphQLInputTypeInner(entity, true, 'Update');
|
|
348
|
+
return sRet;
|
|
322
349
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if (entity.AllowUpdateAPI)
|
|
331
|
-
sRet += generateServerGraphQLInputTypeInner(entity, true, 'Update');
|
|
332
|
-
return sRet;
|
|
333
|
-
}
|
|
334
|
-
function generateServerGraphQLInputTypeInner(entity, isUpdate, classPrefix) {
|
|
335
|
-
let sRet = '';
|
|
336
|
-
sRet += `\n
|
|
337
|
-
//****************************************************************************
|
|
338
|
-
// INPUT TYPE for ${entity.Name}
|
|
339
|
-
//****************************************************************************
|
|
340
|
-
@InputType()
|
|
350
|
+
generateServerGraphQLInputTypeInner(entity, isUpdate, classPrefix) {
|
|
351
|
+
let sRet = '';
|
|
352
|
+
sRet += `\n
|
|
353
|
+
//****************************************************************************
|
|
354
|
+
// INPUT TYPE for ${entity.Name}
|
|
355
|
+
//****************************************************************************
|
|
356
|
+
@InputType()
|
|
341
357
|
export class ${classPrefix}${entity.BaseTableCodeName}Input {`;
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
@Field(${sFullTypeGraphQLString})
|
|
352
|
-
${f.CodeName}: ${(0, core_1.TypeScriptTypeFromSQLType)(f.Type)};
|
|
353
|
-
`;
|
|
358
|
+
for (let i = 0; i < entity.Fields.length; i++) {
|
|
359
|
+
const f = entity.Fields[i];
|
|
360
|
+
const sTypeGraphQLString = this.getTypeGraphQLFieldString(f);
|
|
361
|
+
const sNull = f.AllowsNull ? '{ nullable: true }' : '';
|
|
362
|
+
const sFullTypeGraphQLString = sTypeGraphQLString + (sNull === '' || sTypeGraphQLString === '' ? '' : ', ') + sNull;
|
|
363
|
+
// always include ID becuase it is used for UPDATES
|
|
364
|
+
const includePrimaryKey = isUpdate || (!f.AutoIncrement && f.Type !== 'uniqueidentifier'); // include primary key for updates and also for creates if it is not an autoincrement field or a uniqueidentifier
|
|
365
|
+
if ((includePrimaryKey && f.IsPrimaryKey) || (!f.IsPrimaryKey && !f.IsVirtual && f.AllowUpdateAPI && f.Type.trim().toLowerCase() !== 'uniqueidentifier')) {
|
|
366
|
+
sRet += `
|
|
367
|
+
@Field(${sFullTypeGraphQLString})
|
|
368
|
+
${f.CodeName}: ${(0, core_1.TypeScriptTypeFromSQLType)(f.Type)};
|
|
369
|
+
`;
|
|
370
|
+
}
|
|
354
371
|
}
|
|
355
|
-
|
|
356
|
-
sRet += `}
|
|
357
|
-
`;
|
|
358
|
-
return sRet;
|
|
359
|
-
}
|
|
360
|
-
function generateServerGraphQLMutations(entity, serverGraphQLTypeName) {
|
|
361
|
-
let sRet = '';
|
|
362
|
-
// MUTATIONS
|
|
363
|
-
// First, determine if the entity has either Create/Edit allowed, if either, we need to generate a InputType
|
|
364
|
-
if (entity.AllowCreateAPI && !entity.VirtualEntity) {
|
|
365
|
-
// generate a create mutation
|
|
366
|
-
sRet += `
|
|
367
|
-
@Mutation(() => ${serverGraphQLTypeName})
|
|
368
|
-
async Create${entity.BaseTableCodeName}(
|
|
369
|
-
@Arg('input', () => Create${entity.BaseTableCodeName}Input) input: Create${entity.BaseTableCodeName}Input,
|
|
370
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
371
|
-
@PubSub() pubSub: PubSubEngine
|
|
372
|
-
) {
|
|
373
|
-
if (await this.BeforeCreate(dataSource, input)) { // fire event and proceed if it wasn't cancelled
|
|
374
|
-
const entityObject = <${`${entity.ClassName}Entity`}>await new Metadata().GetEntityObject('${entity.Name}', this.GetUserFromPayload(userPayload));
|
|
375
|
-
await entityObject.NewRecord();
|
|
376
|
-
entityObject.SetMany(input);
|
|
377
|
-
if (await entityObject.Save()) {
|
|
378
|
-
// save worked, fire the AfterCreate event and then return all the data
|
|
379
|
-
await this.AfterCreate(dataSource, input); // fire event
|
|
380
|
-
return entityObject.GetAll();
|
|
381
|
-
}
|
|
382
|
-
else
|
|
383
|
-
// save failed, return null
|
|
384
|
-
return null;
|
|
385
|
-
}
|
|
386
|
-
else
|
|
387
|
-
return null;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Before/After CREATE Event Hooks for Sub-Classes to Override
|
|
391
|
-
protected async BeforeCreate(dataSource: DataSource, input: Create${entity.BaseTableCodeName}Input): Promise<boolean> {
|
|
392
|
-
return true;
|
|
393
|
-
}
|
|
394
|
-
protected async AfterCreate(dataSource: DataSource, input: Create${entity.BaseTableCodeName}Input) {
|
|
395
|
-
}
|
|
372
|
+
sRet += `}
|
|
396
373
|
`;
|
|
374
|
+
return sRet;
|
|
375
|
+
}
|
|
376
|
+
generateServerGraphQLMutations(entity, serverGraphQLTypeName) {
|
|
377
|
+
let sRet = '';
|
|
378
|
+
// MUTATIONS
|
|
379
|
+
// First, determine if the entity has either Create/Edit allowed, if either, we need to generate a InputType
|
|
380
|
+
if (entity.AllowCreateAPI && !entity.VirtualEntity) {
|
|
381
|
+
// generate a create mutation
|
|
382
|
+
sRet += `
|
|
383
|
+
@Mutation(() => ${serverGraphQLTypeName})
|
|
384
|
+
async Create${entity.BaseTableCodeName}(
|
|
385
|
+
@Arg('input', () => Create${entity.BaseTableCodeName}Input) input: Create${entity.BaseTableCodeName}Input,
|
|
386
|
+
@Ctx() { dataSource, userPayload }: AppContext,
|
|
387
|
+
@PubSub() pubSub: PubSubEngine
|
|
388
|
+
) {
|
|
389
|
+
if (await this.BeforeCreate(dataSource, input)) { // fire event and proceed if it wasn't cancelled
|
|
390
|
+
const entityObject = <${`${entity.ClassName}Entity`}>await new Metadata().GetEntityObject('${entity.Name}', this.GetUserFromPayload(userPayload));
|
|
391
|
+
await entityObject.NewRecord();
|
|
392
|
+
entityObject.SetMany(input);
|
|
393
|
+
if (await entityObject.Save()) {
|
|
394
|
+
// save worked, fire the AfterCreate event and then return all the data
|
|
395
|
+
await this.AfterCreate(dataSource, input); // fire event
|
|
396
|
+
return entityObject.GetAll();
|
|
397
|
+
}
|
|
398
|
+
else
|
|
399
|
+
// save failed, return null
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
else
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Before/After CREATE Event Hooks for Sub-Classes to Override
|
|
407
|
+
protected async BeforeCreate(dataSource: DataSource, input: Create${entity.BaseTableCodeName}Input): Promise<boolean> {
|
|
408
|
+
return true;
|
|
397
409
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
+
protected async AfterCreate(dataSource: DataSource, input: Create${entity.BaseTableCodeName}Input) {
|
|
411
|
+
}
|
|
412
|
+
`;
|
|
413
|
+
}
|
|
414
|
+
if (entity.AllowUpdateAPI && !entity.VirtualEntity) {
|
|
415
|
+
// generate an edit mutation
|
|
416
|
+
const loadParamString = entity.PrimaryKeys.map(f => `input.${f.CodeName}`).join(', ');
|
|
417
|
+
sRet += `
|
|
418
|
+
@Mutation(() => ${serverGraphQLTypeName})
|
|
419
|
+
async Update${entity.BaseTableCodeName}(
|
|
420
|
+
@Arg('input', () => Update${entity.BaseTableCodeName}Input) input: Update${entity.BaseTableCodeName}Input,
|
|
421
|
+
@Ctx() { dataSource, userPayload }: AppContext,
|
|
422
|
+
@PubSub() pubSub: PubSubEngine
|
|
423
|
+
) {
|
|
424
|
+
if (await this.BeforeUpdate(dataSource, input)) { // fire event and proceed if it wasn't cancelled
|
|
425
|
+
const entityObject = <${`${entity.ClassName}Entity`}>await new Metadata().GetEntityObject('${entity.Name}', this.GetUserFromPayload(userPayload));
|
|
410
426
|
${entity.TrackRecordChanges ? `await entityObject.Load(${loadParamString}) // Track Changes is turned on, so we need to get the latest data from DB first before we save` :
|
|
411
|
-
|
|
412
|
-
${entity.TrackRecordChanges ? 'entityObject.SetMany(input);' : ''}
|
|
413
|
-
if (await entityObject.Save(${entity.TrackRecordChanges ? '' : '{ IgnoreDirtyState: true /*flag used because of LoadFromData() call above*/ }'})) {
|
|
414
|
-
// save worked, fire afterevent and return all the data
|
|
415
|
-
await this.AfterUpdate(dataSource, input); // fire event
|
|
416
|
-
return entityObject.GetAll();
|
|
417
|
-
}
|
|
418
|
-
else
|
|
419
|
-
return null; // save failed, return null
|
|
420
|
-
}
|
|
421
|
-
else
|
|
422
|
-
return null;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Before/After UPDATE Event Hooks for Sub-Classes to Override
|
|
426
|
-
protected async BeforeUpdate(dataSource: DataSource, input: Update${entity.BaseTableCodeName}Input): Promise<boolean> {
|
|
427
|
-
const i = input, d = dataSource; // prevent error
|
|
428
|
-
return true;
|
|
429
|
-
}
|
|
430
|
-
protected async AfterUpdate(dataSource: DataSource, input: Update${entity.BaseTableCodeName}Input) {
|
|
431
|
-
const i = input, d = dataSource; // prevent error
|
|
432
|
-
}
|
|
433
|
-
`;
|
|
434
|
-
}
|
|
435
|
-
if (entity.AllowDeleteAPI && !entity.VirtualEntity) {
|
|
436
|
-
let graphQLPKEYArgs = '';
|
|
437
|
-
let simplePKEYArgs = '';
|
|
438
|
-
let pkeys = '';
|
|
439
|
-
let whereClause = '';
|
|
440
|
-
for (let i = 0; i < entity.PrimaryKeys.length; i++) {
|
|
441
|
-
const pk = entity.PrimaryKeys[i];
|
|
442
|
-
const idQuotes = pk.NeedsQuotes ? "'" : '';
|
|
443
|
-
graphQLPKEYArgs += (graphQLPKEYArgs.length > 0 ? ', ' : '');
|
|
444
|
-
graphQLPKEYArgs += `@Arg('${pk.CodeName}', () => ${pk.GraphQLType}) `;
|
|
445
|
-
graphQLPKEYArgs += `${pk.CodeName}: ${pk.TSType}`;
|
|
446
|
-
simplePKEYArgs += (simplePKEYArgs.length > 0 ? ', ' : '');
|
|
447
|
-
simplePKEYArgs += `${pk.CodeName}: ${pk.TSType}`;
|
|
448
|
-
pkeys += (pkeys.length > 0 ? ', ' : '');
|
|
449
|
-
pkeys += `${pk.CodeName}`;
|
|
450
|
-
whereClause += (whereClause.length > 0 ? ' AND ' : '');
|
|
451
|
-
whereClause += `[${pk.CodeName}]=${idQuotes}\${${pk.CodeName}}${idQuotes}`;
|
|
427
|
+
`entityObject.LoadFromData(input) // using the input instead of loading from DB because TrackChanges is turned off for ${entity.Name}`}
|
|
428
|
+
${entity.TrackRecordChanges ? 'entityObject.SetMany(input);' : ''}
|
|
429
|
+
if (await entityObject.Save(${entity.TrackRecordChanges ? '' : '{ IgnoreDirtyState: true /*flag used because of LoadFromData() call above*/ }'})) {
|
|
430
|
+
// save worked, fire afterevent and return all the data
|
|
431
|
+
await this.AfterUpdate(dataSource, input); // fire event
|
|
432
|
+
return entityObject.GetAll();
|
|
433
|
+
}
|
|
434
|
+
else
|
|
435
|
+
return null; // save failed, return null
|
|
452
436
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
return null; // delete failed, this will cause an exception
|
|
466
|
-
}
|
|
467
|
-
else
|
|
468
|
-
return null; // BeforeDelete canceled the operation, this will cause an exception
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Before/After UPDATE Event Hooks for Sub-Classes to Override
|
|
472
|
-
protected async BeforeDelete(dataSource: DataSource, ${simplePKEYArgs}): Promise<boolean> {
|
|
473
|
-
const i = ${entity.PrimaryKey.Name}, d = dataSource; // prevent error;
|
|
474
|
-
return true;
|
|
475
|
-
}
|
|
476
|
-
protected async AfterDelete(dataSource: DataSource, ${simplePKEYArgs}) {
|
|
477
|
-
const i = ${entity.PrimaryKey.Name}, d = dataSource; // prevent error
|
|
478
|
-
}
|
|
479
|
-
`;
|
|
480
|
-
}
|
|
481
|
-
return sRet;
|
|
482
|
-
}
|
|
483
|
-
// function generateSPParams(entity: EntityInfo, isUpdate: boolean): string {
|
|
484
|
-
// let sRet: string = '',bFirst: boolean = true;
|
|
485
|
-
// for (let i = 0; i < entity.Fields.length; i++) {
|
|
486
|
-
// const f = entity.Fields[i];
|
|
487
|
-
// if (!f.IsVirtual) {
|
|
488
|
-
// switch (f.Name.toLowerCase()) {
|
|
489
|
-
// case 'id':
|
|
490
|
-
// if (isUpdate) {
|
|
491
|
-
// sRet += generateSingleSPParam(f, bFirst);
|
|
492
|
-
// bFirst = false;
|
|
493
|
-
// }
|
|
494
|
-
// break;
|
|
495
|
-
// case 'createdat':
|
|
496
|
-
// case 'updatedat':
|
|
497
|
-
// // do nothing
|
|
498
|
-
// break;
|
|
499
|
-
// default:
|
|
500
|
-
// if (f.Type.trim().toLowerCase() !== 'uniqueidentifier') {
|
|
501
|
-
// // DO NOT INCLUDE UNIQUEIDENTIFIER FIELDS
|
|
502
|
-
// // FOR CREATE/UPDATE, THEY ARE GENERATED BY THE DB
|
|
503
|
-
// sRet += generateSingleSPParam(f, bFirst);
|
|
504
|
-
// bFirst = false;
|
|
505
|
-
// }
|
|
506
|
-
// break;
|
|
507
|
-
// }
|
|
508
|
-
// }
|
|
509
|
-
// }
|
|
510
|
-
// return sRet;
|
|
511
|
-
// }
|
|
512
|
-
// function generateSingleSPParam(f: EntityFieldInfo, isFirst: boolean): string {
|
|
513
|
-
// let sRet: string = '';
|
|
514
|
-
// let quotes: string = '';
|
|
515
|
-
// switch ( TypeScriptTypeFromSQLType(f.Type).toLowerCase() ) {
|
|
516
|
-
// case 'string':
|
|
517
|
-
// case 'date':
|
|
518
|
-
// quotes = "'";
|
|
519
|
-
// break;
|
|
520
|
-
// default:
|
|
521
|
-
// break;
|
|
522
|
-
// }
|
|
523
|
-
// if (!isFirst)
|
|
524
|
-
// sRet += ',\n ';
|
|
525
|
-
// sRet += `@${f.Name}=\${this.packageSPParam(input.${f.Name},"${quotes}")}`
|
|
526
|
-
// return sRet;
|
|
527
|
-
// }
|
|
528
|
-
function generateOneToManyFieldResolver(entity, r) {
|
|
529
|
-
// let keyFieldTS: string = 'number';
|
|
530
|
-
// if (r.EntityKeyField) {
|
|
531
|
-
// const keyField = entity.Fields.find(f => f.Name.toLowerCase() == r.EntityKeyField.toLowerCase())
|
|
532
|
-
// keyFieldTS = keyField ? TypeScriptTypeFromSQLType(keyField.Type) : 'int';
|
|
533
|
-
// }
|
|
534
|
-
const md = new core_1.Metadata();
|
|
535
|
-
const re = md.Entities.find(e => e.Name.toLowerCase() == r.RelatedEntity.toLowerCase());
|
|
536
|
-
const instanceName = entity.BaseTableCodeName.toLowerCase() + _graphQLTypeSuffix;
|
|
537
|
-
const filterFieldName = !r.EntityKeyField ? entity.PrimaryKey.Name : r.EntityKeyField;
|
|
538
|
-
const filterField = entity.Fields.find(f => f.Name.toLowerCase() == filterFieldName.toLowerCase());
|
|
539
|
-
if (!filterField)
|
|
540
|
-
throw new Error(`Field ${filterFieldName} not found in entity ${entity.Name} - check the relationship ${r.ID} and the EntityKeyField property`);
|
|
541
|
-
const quotes = filterField.NeedsQuotes ? "'" : '';
|
|
542
|
-
const serverPackagePrefix = re.SchemaName === config_1.mjCoreSchema ? 'mj_core_schema_server_object_types.' : '';
|
|
543
|
-
const serverClassName = serverPackagePrefix + r.RelatedEntityBaseTableCodeName + _graphQLTypeSuffix;
|
|
544
|
-
return `
|
|
545
|
-
@FieldResolver(() => [${serverClassName}])
|
|
546
|
-
async ${r.RelatedEntityCodeName}Array(@Root() ${instanceName}: ${entity.BaseTableCodeName + _graphQLTypeSuffix}, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
547
|
-
this.CheckUserReadPermissions('${r.RelatedEntity}', userPayload);
|
|
548
|
-
const sSQL = \`SELECT * FROM [${schemaName(re)}].[${r.RelatedEntityBaseView}]\ WHERE [${r.RelatedEntityJoinField}]=${quotes}\${${instanceName}.${filterFieldName}}${quotes} \` + this.getRowLevelSecurityWhereClause('${r.RelatedEntity}', userPayload, EntityPermissionType.Read, 'AND');
|
|
549
|
-
const result = this.ArrayMapFieldNamesToCodeNames('${r.RelatedEntity}', await dataSource.query(sSQL));
|
|
550
|
-
return result;
|
|
551
|
-
}
|
|
437
|
+
else
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Before/After UPDATE Event Hooks for Sub-Classes to Override
|
|
442
|
+
protected async BeforeUpdate(dataSource: DataSource, input: Update${entity.BaseTableCodeName}Input): Promise<boolean> {
|
|
443
|
+
const i = input, d = dataSource; // prevent error
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
protected async AfterUpdate(dataSource: DataSource, input: Update${entity.BaseTableCodeName}Input) {
|
|
447
|
+
const i = input, d = dataSource; // prevent error
|
|
448
|
+
}
|
|
552
449
|
`;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
450
|
+
}
|
|
451
|
+
if (entity.AllowDeleteAPI && !entity.VirtualEntity) {
|
|
452
|
+
let graphQLPKEYArgs = '';
|
|
453
|
+
let simplePKEYArgs = '';
|
|
454
|
+
let pkeys = '';
|
|
455
|
+
let whereClause = '';
|
|
456
|
+
for (let i = 0; i < entity.PrimaryKeys.length; i++) {
|
|
457
|
+
const pk = entity.PrimaryKeys[i];
|
|
458
|
+
const idQuotes = pk.NeedsQuotes ? "'" : '';
|
|
459
|
+
graphQLPKEYArgs += (graphQLPKEYArgs.length > 0 ? ', ' : '');
|
|
460
|
+
graphQLPKEYArgs += `@Arg('${pk.CodeName}', () => ${pk.GraphQLType}) `;
|
|
461
|
+
graphQLPKEYArgs += `${pk.CodeName}: ${pk.TSType}`;
|
|
462
|
+
simplePKEYArgs += (simplePKEYArgs.length > 0 ? ', ' : '');
|
|
463
|
+
simplePKEYArgs += `${pk.CodeName}: ${pk.TSType}`;
|
|
464
|
+
pkeys += (pkeys.length > 0 ? ', ' : '');
|
|
465
|
+
pkeys += `${pk.CodeName}`;
|
|
466
|
+
whereClause += (whereClause.length > 0 ? ' AND ' : '');
|
|
467
|
+
whereClause += `[${pk.CodeName}]=${idQuotes}\${${pk.CodeName}}${idQuotes}`;
|
|
468
|
+
}
|
|
469
|
+
sRet += `
|
|
470
|
+
@Mutation(() => ${serverGraphQLTypeName})
|
|
471
|
+
async Delete${entity.BaseTableCodeName}(${graphQLPKEYArgs}, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
472
|
+
if (await this.BeforeDelete(dataSource, ${pkeys})) { // fire event and proceed if it wasn't cancelled
|
|
473
|
+
const entityObject = <${`${entity.ClassName}Entity`}>await new Metadata().GetEntityObject('${entity.Name}', this.GetUserFromPayload(userPayload));
|
|
474
|
+
await entityObject.Load(${pkeys});
|
|
475
|
+
const returnValue = entityObject.GetAll(); // grab the values before we delete so we can return last state before delete if we are successful.
|
|
476
|
+
if (await entityObject.Delete()) {
|
|
477
|
+
await this.AfterDelete(dataSource, ${pkeys}); // fire event
|
|
478
|
+
return returnValue;
|
|
479
|
+
}
|
|
480
|
+
else
|
|
481
|
+
return null; // delete failed, this will cause an exception
|
|
482
|
+
}
|
|
483
|
+
else
|
|
484
|
+
return null; // BeforeDelete canceled the operation, this will cause an exception
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Before/After UPDATE Event Hooks for Sub-Classes to Override
|
|
488
|
+
protected async BeforeDelete(dataSource: DataSource, ${simplePKEYArgs}): Promise<boolean> {
|
|
489
|
+
const i = ${entity.PrimaryKey.Name}, d = dataSource; // prevent error;
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
protected async AfterDelete(dataSource: DataSource, ${simplePKEYArgs}) {
|
|
493
|
+
const i = ${entity.PrimaryKey.Name}, d = dataSource; // prevent error
|
|
494
|
+
}
|
|
573
495
|
`;
|
|
574
|
-
}
|
|
496
|
+
}
|
|
497
|
+
return sRet;
|
|
498
|
+
}
|
|
499
|
+
// function generateSPParams(entity: EntityInfo, isUpdate: boolean): string {
|
|
500
|
+
// let sRet: string = '',bFirst: boolean = true;
|
|
501
|
+
// for (let i = 0; i < entity.Fields.length; i++) {
|
|
502
|
+
// const f = entity.Fields[i];
|
|
503
|
+
// if (!f.IsVirtual) {
|
|
504
|
+
// switch (f.Name.toLowerCase()) {
|
|
505
|
+
// case 'id':
|
|
506
|
+
// if (isUpdate) {
|
|
507
|
+
// sRet += generateSingleSPParam(f, bFirst);
|
|
508
|
+
// bFirst = false;
|
|
509
|
+
// }
|
|
510
|
+
// break;
|
|
511
|
+
// case 'createdat':
|
|
512
|
+
// case 'updatedat':
|
|
513
|
+
// // do nothing
|
|
514
|
+
// break;
|
|
515
|
+
// default:
|
|
516
|
+
// if (f.Type.trim().toLowerCase() !== 'uniqueidentifier') {
|
|
517
|
+
// // DO NOT INCLUDE UNIQUEIDENTIFIER FIELDS
|
|
518
|
+
// // FOR CREATE/UPDATE, THEY ARE GENERATED BY THE DB
|
|
519
|
+
// sRet += generateSingleSPParam(f, bFirst);
|
|
520
|
+
// bFirst = false;
|
|
521
|
+
// }
|
|
522
|
+
// break;
|
|
523
|
+
// }
|
|
524
|
+
// }
|
|
525
|
+
// }
|
|
526
|
+
// return sRet;
|
|
527
|
+
// }
|
|
528
|
+
// function generateSingleSPParam(f: EntityFieldInfo, isFirst: boolean): string {
|
|
529
|
+
// let sRet: string = '';
|
|
530
|
+
// let quotes: string = '';
|
|
531
|
+
// switch ( TypeScriptTypeFromSQLType(f.Type).toLowerCase() ) {
|
|
532
|
+
// case 'string':
|
|
533
|
+
// case 'date':
|
|
534
|
+
// quotes = "'";
|
|
535
|
+
// break;
|
|
536
|
+
// default:
|
|
537
|
+
// break;
|
|
538
|
+
// }
|
|
539
|
+
// if (!isFirst)
|
|
540
|
+
// sRet += ',\n ';
|
|
541
|
+
// sRet += `@${f.Name}=\${this.packageSPParam(input.${f.Name},"${quotes}")}`
|
|
542
|
+
// return sRet;
|
|
543
|
+
// }
|
|
544
|
+
generateOneToManyFieldResolver(entity, r) {
|
|
545
|
+
// let keyFieldTS: string = 'number';
|
|
546
|
+
// if (r.EntityKeyField) {
|
|
547
|
+
// const keyField = entity.Fields.find(f => f.Name.toLowerCase() == r.EntityKeyField.toLowerCase())
|
|
548
|
+
// keyFieldTS = keyField ? TypeScriptTypeFromSQLType(keyField.Type) : 'int';
|
|
549
|
+
// }
|
|
550
|
+
const md = new core_1.Metadata();
|
|
551
|
+
const re = md.Entities.find(e => e.Name.toLowerCase() == r.RelatedEntity.toLowerCase());
|
|
552
|
+
const instanceName = entity.BaseTableCodeName.toLowerCase() + this.GraphQLTypeSuffix;
|
|
553
|
+
const filterFieldName = !r.EntityKeyField ? entity.PrimaryKey.Name : r.EntityKeyField;
|
|
554
|
+
const filterField = entity.Fields.find(f => f.Name.toLowerCase() == filterFieldName.toLowerCase());
|
|
555
|
+
if (!filterField)
|
|
556
|
+
throw new Error(`Field ${filterFieldName} not found in entity ${entity.Name} - check the relationship ${r.ID} and the EntityKeyField property`);
|
|
557
|
+
const quotes = filterField.NeedsQuotes ? "'" : '';
|
|
558
|
+
const serverPackagePrefix = re.SchemaName === config_1.mjCoreSchema ? 'mj_core_schema_server_object_types.' : '';
|
|
559
|
+
const serverClassName = serverPackagePrefix + r.RelatedEntityBaseTableCodeName + this.GraphQLTypeSuffix;
|
|
560
|
+
return `
|
|
561
|
+
@FieldResolver(() => [${serverClassName}])
|
|
562
|
+
async ${r.RelatedEntityCodeName}Array(@Root() ${instanceName}: ${entity.BaseTableCodeName + this.GraphQLTypeSuffix}, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
563
|
+
this.CheckUserReadPermissions('${r.RelatedEntity}', userPayload);
|
|
564
|
+
const sSQL = \`SELECT * FROM [${this.schemaName(re)}].[${r.RelatedEntityBaseView}]\ WHERE [${r.RelatedEntityJoinField}]=${quotes}\${${instanceName}.${filterFieldName}}${quotes} \` + this.getRowLevelSecurityWhereClause('${r.RelatedEntity}', userPayload, EntityPermissionType.Read, 'AND');
|
|
565
|
+
const result = this.ArrayMapFieldNamesToCodeNames('${r.RelatedEntity}', await dataSource.query(sSQL));
|
|
566
|
+
return result;
|
|
567
|
+
}
|
|
568
|
+
`;
|
|
569
|
+
}
|
|
570
|
+
generateManyToManyFieldResolver(entity, r) {
|
|
571
|
+
const md = new core_1.Metadata();
|
|
572
|
+
const re = md.Entities.find(e => e.Name.toLowerCase() == r.RelatedEntity.toLowerCase());
|
|
573
|
+
const instanceName = entity.BaseTableCodeName.toLowerCase() + this.GraphQLTypeSuffix;
|
|
574
|
+
const filterFieldName = !r.EntityKeyField ? entity.PrimaryKey.Name : r.EntityKeyField;
|
|
575
|
+
const filterField = entity.Fields.find(f => f.Name.toLowerCase() == filterFieldName.toLowerCase());
|
|
576
|
+
if (!filterField)
|
|
577
|
+
throw new Error(`Field ${filterFieldName} not found in entity ${entity.Name} - check the relationship ${r.ID} and the EntityKeyField property`);
|
|
578
|
+
const quotes = filterField.NeedsQuotes ? "'" : '';
|
|
579
|
+
const serverPackagePrefix = re.SchemaName === config_1.mjCoreSchema ? 'mj_core_schema_server_object_types.' : '';
|
|
580
|
+
const serverClassName = serverPackagePrefix + r.RelatedEntityBaseTableCodeName + this.GraphQLTypeSuffix;
|
|
581
|
+
return `
|
|
582
|
+
@FieldResolver(() => [${serverClassName}])
|
|
583
|
+
async ${r.RelatedEntityCodeName}Array(@Root() ${instanceName}: ${entity.BaseTableCodeName + this.GraphQLTypeSuffix}, @Ctx() { dataSource, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
584
|
+
this.CheckUserReadPermissions('${r.RelatedEntity}', userPayload);
|
|
585
|
+
const sSQL = \`SELECT * FROM [${this.schemaName(re)}].[${r.RelatedEntityBaseView}]\ WHERE [${re.PrimaryKey.Name}] IN (SELECT [${r.JoinEntityInverseJoinField}] FROM [${this.schemaName(re)}].[${r.JoinView}] WHERE [${r.JoinEntityJoinField}]=${quotes}\${${instanceName}.${filterFieldName}}${quotes}) \` + this.getRowLevelSecurityWhereClause('${r.RelatedEntity}', userPayload, EntityPermissionType.Read, 'AND');
|
|
586
|
+
const result = this.ArrayMapFieldNamesToCodeNames('${r.RelatedEntity}', await dataSource.query(sSQL));
|
|
587
|
+
return result;
|
|
588
|
+
}
|
|
589
|
+
`;
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
exports.GraphQLServerGeneratorBase = GraphQLServerGeneratorBase;
|
|
593
|
+
exports.GraphQLServerGeneratorBase = GraphQLServerGeneratorBase = __decorate([
|
|
594
|
+
(0, global_1.RegisterClass)(GraphQLServerGeneratorBase)
|
|
595
|
+
], GraphQLServerGeneratorBase);
|
|
575
596
|
//# sourceMappingURL=graphql_server_codegen.js.map
|