@memberjunction/server 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +357 -1
- package/CHANGELOG.md +75 -2
- package/dist/generated/generated.d.ts +525 -307
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +1406 -253
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +2 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +42 -8
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +1 -1
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +5 -3
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/package.json +21 -22
- package/src/generated/generated.ts +1046 -230
- package/src/generic/ResolverBase.ts +52 -11
- package/src/index.ts +15 -8
- package/src/resolvers/UserResolver.ts +5 -3
|
@@ -24,10 +24,16 @@ export class ResolverBase {
|
|
|
24
24
|
const entityInfo = md.Entities.find((e) => e.Name === entityName);
|
|
25
25
|
if (!entityInfo)
|
|
26
26
|
throw new Error(`Entity ${entityName} not found in metadata`);
|
|
27
|
-
const fields = entityInfo.Fields.filter((f) => f.Name !== f.CodeName);
|
|
27
|
+
const fields = entityInfo.Fields.filter((f) => f.Name !== f.CodeName || f.Name.startsWith('__mj_'));
|
|
28
28
|
fields.forEach((f) => {
|
|
29
29
|
if (dataObject.hasOwnProperty(f.Name)) {
|
|
30
|
-
|
|
30
|
+
if (f.CodeName.startsWith('__mj_')) { // GraphQL doesn't allow us to pass back fields with __ so we are mapping our special field cases that start with __mj_ to _mj__ for transport - they are converted back on the other side automatically
|
|
31
|
+
const newCodeName = `_mj__${f.CodeName.substring(5)}`;
|
|
32
|
+
dataObject[newCodeName] = dataObject[f.Name];
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
dataObject[f.CodeName] = dataObject[f.Name];
|
|
36
|
+
}
|
|
31
37
|
delete dataObject[f.Name];
|
|
32
38
|
}
|
|
33
39
|
});
|
|
@@ -205,14 +211,12 @@ export class ResolverBase {
|
|
|
205
211
|
// figure out the result type from the input string (if provided)
|
|
206
212
|
let rt: 'simple' | 'entity_object' | 'count_only' = 'simple';
|
|
207
213
|
switch (resultType?.trim().toLowerCase()) {
|
|
208
|
-
case 'entity_object':
|
|
209
|
-
rt = 'entity_object';
|
|
210
|
-
break;
|
|
211
214
|
case 'count_only':
|
|
212
215
|
rt = 'count_only';
|
|
213
216
|
break;
|
|
217
|
+
case 'entity_object':
|
|
214
218
|
default:
|
|
215
|
-
rt = 'simple';
|
|
219
|
+
rt = 'simple'; // use simple as the default AND for entity_object becuase on teh server we don't really pass back a true entity_object anyway, just passing back the simple object anyway
|
|
216
220
|
break;
|
|
217
221
|
}
|
|
218
222
|
|
|
@@ -236,9 +240,25 @@ export class ResolverBase {
|
|
|
236
240
|
},
|
|
237
241
|
user
|
|
238
242
|
);
|
|
243
|
+
// go through the result and convert all fields that start with __mj_*** to _mj__*** for GraphQL transport
|
|
244
|
+
if (result && result.Success) {
|
|
245
|
+
for (const r of result.Results) {
|
|
246
|
+
const keys = Object.keys(r);
|
|
247
|
+
keys.forEach((k) => {
|
|
248
|
+
if (k.trim().toLowerCase().startsWith('__mj_')) {
|
|
249
|
+
r[`_mj__${k.substring(5)}`] = r[k];
|
|
250
|
+
delete r[k];
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
}
|
|
255
|
+
}
|
|
239
256
|
return result;
|
|
240
|
-
}
|
|
241
|
-
|
|
257
|
+
}
|
|
258
|
+
else
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
242
262
|
console.log(err);
|
|
243
263
|
throw err;
|
|
244
264
|
}
|
|
@@ -385,7 +405,7 @@ export class ResolverBase {
|
|
|
385
405
|
if (await entityObject.Save()) {
|
|
386
406
|
// save worked, fire the AfterCreate event and then return all the data
|
|
387
407
|
await this.AfterCreate(dataSource, input); // fire event
|
|
388
|
-
return entityObject.GetAll();
|
|
408
|
+
return this.MapFieldNamesToCodeNames(entityName, entityObject.GetAll());
|
|
389
409
|
}
|
|
390
410
|
else
|
|
391
411
|
// save failed, return null
|
|
@@ -458,7 +478,7 @@ export class ResolverBase {
|
|
|
458
478
|
if (await entityObject.Save()) {
|
|
459
479
|
// save worked, fire afterevent and return all the data
|
|
460
480
|
await this.AfterUpdate(dataSource, input); // fire event
|
|
461
|
-
return entityObject.GetAll();
|
|
481
|
+
return this.MapFieldNamesToCodeNames(entityName, entityObject.GetAll());
|
|
462
482
|
}
|
|
463
483
|
else {
|
|
464
484
|
throw new GraphQLError(entityObject.LatestResult?.Message ?? 'Unknown error', {
|
|
@@ -499,6 +519,10 @@ export class ResolverBase {
|
|
|
499
519
|
val = (val === null || val === undefined || val === 'false' || val === '0' || parseInt(val) === 0) ? false : true;
|
|
500
520
|
break;
|
|
501
521
|
case EntityFieldTSType.Date:
|
|
522
|
+
// first, if val is a string and it is actually a number (milliseconds since epoch), convert it to a number.
|
|
523
|
+
if (val !== null && val !== undefined && val.toString().trim() !== '' && !isNaN(val))
|
|
524
|
+
val = parseInt(val);
|
|
525
|
+
|
|
502
526
|
val = val !== null && val !== undefined ? new Date(val) : null;
|
|
503
527
|
break;
|
|
504
528
|
default:
|
|
@@ -516,7 +540,24 @@ export class ResolverBase {
|
|
|
516
540
|
const dbDifferences = [];
|
|
517
541
|
Object.keys(clientOldValues).forEach((key) => {
|
|
518
542
|
const f = entityObject.EntityInfo.Fields.find((f) => f.CodeName === key);
|
|
519
|
-
|
|
543
|
+
let different = false;
|
|
544
|
+
switch (typeof clientOldValues[key]) {
|
|
545
|
+
case 'number':
|
|
546
|
+
different = clientOldValues[key] !== dbValues[key];
|
|
547
|
+
break;
|
|
548
|
+
case 'boolean':
|
|
549
|
+
different = clientOldValues[key] !== dbValues[key];
|
|
550
|
+
break;
|
|
551
|
+
case 'object':
|
|
552
|
+
if (clientOldValues[key] instanceof Date) {
|
|
553
|
+
different = clientOldValues[key].getTime() !== dbValues[key].getTime();
|
|
554
|
+
}
|
|
555
|
+
break;
|
|
556
|
+
default:
|
|
557
|
+
different = clientOldValues[key] !== dbValues[key];
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
if (different && f && !f.ReadOnly ) {
|
|
520
561
|
// only include updateable fields
|
|
521
562
|
dbDifferences.push({
|
|
522
563
|
FieldName: key,
|
package/src/index.ts
CHANGED
|
@@ -89,18 +89,25 @@ export const serve = async (resolverPaths: Array<string>) => {
|
|
|
89
89
|
const config = new SQLServerProviderConfigData(dataSource, '', mj_core_schema, cacheRefreshInterval);
|
|
90
90
|
await setupSQLServerClient(config); // datasource is already initialized, so we can setup the client right away
|
|
91
91
|
const md = new Metadata();
|
|
92
|
-
|
|
92
|
+
console.log(`Data Source has been initialized. ${md?.Entities ? md.Entities.length : 0} entities loaded.`);
|
|
93
|
+
setupComplete$.next(true);
|
|
93
94
|
|
|
94
95
|
/******TEST HARNESS FOR CHANGE DETECTION */
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
/******TEST HARNESS FOR CHANGE DETECTION */
|
|
97
|
+
// const cd = ExternalChangeDetectorEngine.Instance;
|
|
98
|
+
// await cd.Config(false, UserCache.Users[0]);
|
|
99
|
+
|
|
100
|
+
// // don't wait for this, just run it and show in console whenever done.
|
|
101
|
+
// cd.DetectChangesForAllEligibleEntities().then(result => {
|
|
102
|
+
// console.log(result)
|
|
103
|
+
// cd.ReplayChanges(result.Changes).then(replayResult => {
|
|
104
|
+
// console.log(replayResult)
|
|
105
|
+
// });
|
|
106
|
+
// });
|
|
107
|
+
/******TEST HARNESS FOR CHANGE DETECTION */
|
|
108
|
+
/******TEST HARNESS FOR CHANGE DETECTION */
|
|
100
109
|
|
|
101
|
-
console.log(`Data Source has been initialized. ${md?.Entities ? md.Entities.length : 0} entities loaded.`);
|
|
102
110
|
|
|
103
|
-
setupComplete$.next(true);
|
|
104
111
|
|
|
105
112
|
const dynamicModules = await Promise.all(paths.map((modulePath) => import(modulePath.replace(/\.[jt]s$/, ''))));
|
|
106
113
|
const resolvers = dynamicModules.flatMap((module) =>
|
|
@@ -10,12 +10,14 @@ export class UserResolver extends UserResolverBase {
|
|
|
10
10
|
|
|
11
11
|
@Query(() => User_)
|
|
12
12
|
async UserByID(@Arg('ID', () => Int) ID: number, @Ctx() { dataSource }: AppContext) {
|
|
13
|
-
|
|
13
|
+
const retVal = super.safeFirstArrayElement(await this.findBy(dataSource, 'Users', { ID }));
|
|
14
|
+
return this.MapFieldNamesToCodeNames('Users', retVal);
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
@Query(() => User_)
|
|
17
18
|
async UserByEmployeeID(@Arg('EmployeeID', () => Int) EmployeeID: number, @Ctx() { dataSource }: AppContext) {
|
|
18
|
-
|
|
19
|
+
const retVal = super.safeFirstArrayElement(await this.findBy(dataSource, 'Users', { EmployeeID }));
|
|
20
|
+
return this.MapFieldNamesToCodeNames('Users', retVal);
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
@Query(() => User_)
|
|
@@ -23,7 +25,7 @@ export class UserResolver extends UserResolverBase {
|
|
|
23
25
|
// const searchEmail = userEmailMap[Email] ?? Email;
|
|
24
26
|
const searchEmail = Email;
|
|
25
27
|
const returnVal = super.safeFirstArrayElement(await this.findBy(dataSource, 'Users', { Email: searchEmail }));
|
|
26
|
-
return returnVal;
|
|
28
|
+
return this.MapFieldNamesToCodeNames('Users', returnVal);
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
export default UserResolver;
|