@memberjunction/server 1.0.6 → 1.0.7
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/.eslintignore +4 -4
- package/.eslintrc +24 -24
- package/CHANGELOG.json +92 -0
- package/CHANGELOG.md +25 -0
- package/README.md +141 -141
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +23 -0
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -0
- package/dist/entitySubclasses/entityPermissions.server.js +99 -0
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -0
- package/dist/entitySubclasses/userViewEntity.server.js +17 -17
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +10 -10
- package/dist/resolvers/FileCategoryResolver.js +2 -2
- package/dist/resolvers/ReportResolver.js +4 -4
- package/package.json +80 -80
- package/src/apolloServer/TransactionPlugin.ts +57 -57
- package/src/apolloServer/index.ts +33 -33
- package/src/auth/exampleNewUserSubClass.ts +73 -73
- package/src/auth/index.ts +151 -151
- package/src/auth/newUsers.ts +56 -56
- package/src/auth/tokenExpiredError.ts +12 -12
- package/src/cache.ts +10 -10
- package/src/config.ts +89 -84
- package/src/context.ts +119 -119
- package/src/directives/Public.ts +42 -42
- package/src/directives/index.ts +1 -1
- package/src/entitySubclasses/entityPermissions.server.ts +111 -0
- package/src/entitySubclasses/userViewEntity.server.ts +187 -187
- package/src/generated/generated.ts +2573 -2573
- package/src/generic/PushStatusResolver.ts +40 -40
- package/src/generic/ResolverBase.ts +331 -331
- package/src/generic/RunViewResolver.ts +350 -350
- package/src/index.ts +133 -137
- package/src/orm.ts +36 -36
- package/src/resolvers/AskSkipResolver.ts +782 -782
- package/src/resolvers/ColorResolver.ts +72 -72
- package/src/resolvers/DatasetResolver.ts +115 -115
- package/src/resolvers/EntityRecordNameResolver.ts +77 -77
- package/src/resolvers/EntityResolver.ts +37 -37
- package/src/resolvers/FileCategoryResolver.ts +38 -38
- package/src/resolvers/FileResolver.ts +110 -110
- package/src/resolvers/MergeRecordsResolver.ts +198 -198
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +59 -59
- package/src/resolvers/QueryResolver.ts +42 -42
- package/src/resolvers/ReportResolver.ts +131 -131
- package/src/resolvers/UserFavoriteResolver.ts +102 -102
- package/src/resolvers/UserResolver.ts +29 -29
- package/src/resolvers/UserViewResolver.ts +64 -64
- package/src/types.ts +19 -19
- package/src/util.ts +106 -106
- package/tsconfig.json +31 -31
- package/typedoc.json +4 -4
- package/build.log.json +0 -47
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { NewUserBase } from './auth/newUsers';
|
|
|
5
5
|
export { configInfo } from './config';
|
|
6
6
|
export * from './directives';
|
|
7
7
|
export * from './entitySubclasses/userViewEntity.server';
|
|
8
|
+
export * from './entitySubclasses/entityPermissions.server';
|
|
8
9
|
export * from './types';
|
|
9
10
|
export { TokenExpiredError } from './auth';
|
|
10
11
|
export * from './generic/PushStatusResolver';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,kBAAkB,CAAC;AAa1B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,0CAA0C,CAAC;AACzD,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAE3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,kBAAkB,CAAC;AAa1B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,0CAA0C,CAAC;AACzD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAE3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAE3C,cAAc,uBAAuB,CAAA;AAMrC,eAAO,MAAM,KAAK,kBAAyB,MAAM,MAAM,CAAC,kBA2EvD,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -63,6 +63,7 @@ var config_2 = require("./config");
|
|
|
63
63
|
Object.defineProperty(exports, "configInfo", { enumerable: true, get: function () { return config_2.configInfo; } });
|
|
64
64
|
__exportStar(require("./directives"), exports);
|
|
65
65
|
__exportStar(require("./entitySubclasses/userViewEntity.server"), exports);
|
|
66
|
+
__exportStar(require("./entitySubclasses/entityPermissions.server"), exports);
|
|
66
67
|
__exportStar(require("./types"), exports);
|
|
67
68
|
var auth_1 = require("./auth");
|
|
68
69
|
Object.defineProperty(exports, "TokenExpiredError", { enumerable: true, get: function () { return auth_1.TokenExpiredError; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAA4B;AAE5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,sDAA4D;AAC5D,kDAAqD;AACrD,+CAAgD;AAChD,mFAA2G;AAC3G,6CAAmC;AACnC,gDAAwB;AACxB,sDAA8B;AAC9B,yCAAqC;AACrC,8CAAkD;AAClD,yCAAyC;AACzC,yCAAgC;AAChC,4BAA0B;AAC1B,+BAAqC;AACrC,+CAAqF;AACrF,qCAAqC;AACrC,2BAAqC;AACrC,kEAA+C;AAC/C,qCAA2G;AAC3G,uCAA4D;AAC5D,6CAA+C;AAC/C,gDAAwB;AAExB,MAAM,oBAAoB,GAAG,mBAAU,CAAC,gBAAgB,CAAC,4BAA4B,CAAC;AAEtF,mDAA4C;AAAnC,4GAAA,SAAS,OAAA;AAClB,+CAA6B;AAC7B,4CAA8C;AAArC,uGAAA,WAAW,OAAA;AACpB,mCAAsC;AAA7B,oGAAA,UAAU,OAAA;AACnB,+CAA6B;AAC7B,2EAAyD;AACzD,0CAAwB;AACxB,+BAA2C;AAAlC,yGAAA,iBAAiB,OAAA;AAE1B,+DAA6C;AAC7C,yDAAuC;AACvC,4DAA0C;AAE1C,8DAA4C;AAC5C,4DAA0C;AAC1C,8DAA4C;AAC5C,uEAAqD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -318,13 +318,13 @@ let AskSkipResolver = AskSkipResolver_1 = class AskSkipResolver {
|
|
|
318
318
|
try {
|
|
319
319
|
const md = new core_1.Metadata();
|
|
320
320
|
const e = md.Entities.find((e) => e.Name === 'Conversation Details');
|
|
321
|
-
const sql = `SELECT
|
|
322
|
-
${maxHistoricalMessages ? 'TOP ' + maxHistoricalMessages : ''} ID, Message, Role, CreatedAt
|
|
323
|
-
FROM
|
|
324
|
-
${e.SchemaName}.${e.BaseView}
|
|
325
|
-
WHERE
|
|
326
|
-
ConversationID = ${ConversationId}
|
|
327
|
-
ORDER
|
|
321
|
+
const sql = `SELECT
|
|
322
|
+
${maxHistoricalMessages ? 'TOP ' + maxHistoricalMessages : ''} ID, Message, Role, CreatedAt
|
|
323
|
+
FROM
|
|
324
|
+
${e.SchemaName}.${e.BaseView}
|
|
325
|
+
WHERE
|
|
326
|
+
ConversationID = ${ConversationId}
|
|
327
|
+
ORDER
|
|
328
328
|
BY CreatedAt DESC`;
|
|
329
329
|
const result = await dataSource.query(sql);
|
|
330
330
|
if (!result)
|
|
@@ -518,7 +518,7 @@ let AskSkipResolver = AskSkipResolver_1 = class AskSkipResolver {
|
|
|
518
518
|
const executionErrors = [];
|
|
519
519
|
let dataRequest = apiResponse.dataRequest;
|
|
520
520
|
apiRequest.messages.push({
|
|
521
|
-
content: `Skip API Requested Data as shown below
|
|
521
|
+
content: `Skip API Requested Data as shown below
|
|
522
522
|
${JSON.stringify(apiResponse.dataRequest)}`,
|
|
523
523
|
role: 'system'
|
|
524
524
|
});
|
|
@@ -586,8 +586,8 @@ let AskSkipResolver = AskSkipResolver_1 = class AskSkipResolver {
|
|
|
586
586
|
(0, core_1.LogStatus)(`Execution errors for Skip data request occured, sending those errors back to the Skip API to get new instructions.`);
|
|
587
587
|
apiRequest.requestPhase = 'data_gathering_failure';
|
|
588
588
|
apiRequest.messages.push({
|
|
589
|
-
content: `${_dataGatheringFailureHeaderMessage} #${dataGatheringFailedAttemptCount} of ${_maxDataGatheringRetries} attempts to gather data failed. Errors:
|
|
590
|
-
${JSON.stringify(executionErrors)}
|
|
589
|
+
content: `${_dataGatheringFailureHeaderMessage} #${dataGatheringFailedAttemptCount} of ${_maxDataGatheringRetries} attempts to gather data failed. Errors:
|
|
590
|
+
${JSON.stringify(executionErrors)}
|
|
591
591
|
`,
|
|
592
592
|
role: 'user'
|
|
593
593
|
});
|
|
@@ -31,8 +31,8 @@ class FileResolver extends generated_1.FileCategoryResolver {
|
|
|
31
31
|
await fileCategoryEntity.Load(ID);
|
|
32
32
|
const returnValue = fileCategoryEntity.GetAll();
|
|
33
33
|
await dataSource.transaction(async () => {
|
|
34
|
-
const sSQL = `UPDATE [${config_1.mj_core_schema}].[File]
|
|
35
|
-
SET [CategoryID]=${fileCategoryEntity.ParentID}
|
|
34
|
+
const sSQL = `UPDATE [${config_1.mj_core_schema}].[File]
|
|
35
|
+
SET [CategoryID]=${fileCategoryEntity.ParentID}
|
|
36
36
|
WHERE [CategoryID]=${fileCategoryEntity.ID}`;
|
|
37
37
|
await dataSource.query(sSQL);
|
|
38
38
|
await fileCategoryEntity.Delete();
|
|
@@ -93,10 +93,10 @@ let ReportResolverExtended = class ReportResolverExtended {
|
|
|
93
93
|
const cd = md.Entities.find(e => e.Name === 'Conversations');
|
|
94
94
|
if (!cd)
|
|
95
95
|
throw new Error('Unable to find Conversations Entity metadata');
|
|
96
|
-
const sql = `SELECT cd.Message, cd.ConversationID, c.DataContextID
|
|
97
|
-
FROM ${cde.SchemaName}.${cde.BaseView} cd
|
|
98
|
-
INNER JOIN ${cd.SchemaName}.${cd.BaseView} c
|
|
99
|
-
ON cd.ConversationID = c.ID
|
|
96
|
+
const sql = `SELECT cd.Message, cd.ConversationID, c.DataContextID
|
|
97
|
+
FROM ${cde.SchemaName}.${cde.BaseView} cd
|
|
98
|
+
INNER JOIN ${cd.SchemaName}.${cd.BaseView} c
|
|
99
|
+
ON cd.ConversationID = c.ID
|
|
100
100
|
WHERE cd.ID=${ConversationDetailID}`;
|
|
101
101
|
const result = await dataSource.query(sql);
|
|
102
102
|
if (!result || result.length === 0)
|
package/package.json
CHANGED
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@memberjunction/server",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "src/index.ts",
|
|
7
|
-
"author": "MemberJunction.com",
|
|
8
|
-
"license": "ISC",
|
|
9
|
-
"scripts": {
|
|
10
|
-
"clean": "rimraf dist",
|
|
11
|
-
"build": "rimraf dist && tsc",
|
|
12
|
-
"watch": "tsc -w",
|
|
13
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
14
|
-
"lint:eslint": "eslint \"**/*.{ts,js,}\" --max-warnings=0",
|
|
15
|
-
"lint:tsc": "tsc --noemit",
|
|
16
|
-
"lint": "concurrently \"npm:lint:eslint\" \"npm:lint:tsc\"",
|
|
17
|
-
"pretty": "prettier --write \"**/*.{ts,js,}\"",
|
|
18
|
-
"codegen": "cpy --flat ../codegen/output/entities/*.ts src/entities",
|
|
19
|
-
"postcodegen": "npm run pretty"
|
|
20
|
-
},
|
|
21
|
-
"dependencies": {
|
|
22
|
-
"@apollo/server": "^4.9.1",
|
|
23
|
-
"@graphql-tools/utils": "^10.0.1",
|
|
24
|
-
"@memberjunction/ai": "^1.0.
|
|
25
|
-
"@memberjunction/ai-openai": "^1.0.
|
|
26
|
-
"@memberjunction/aiengine": "^1.0.
|
|
27
|
-
"@memberjunction/core": "^1.0.
|
|
28
|
-
"@memberjunction/core-entities": "^1.0.
|
|
29
|
-
"@memberjunction/data-context": "^1.0.
|
|
30
|
-
"@memberjunction/data-context-server": "^1.0.
|
|
31
|
-
"@memberjunction/global": "^1.0.
|
|
32
|
-
"@memberjunction/storage": "^1.0.
|
|
33
|
-
"@memberjunction/queue": "^1.0.
|
|
34
|
-
"@memberjunction/sqlserver-dataprovider": "^1.0.
|
|
35
|
-
"@memberjunction/skip-types": "^1.0.
|
|
36
|
-
"@types/cors": "^2.8.13",
|
|
37
|
-
"@types/jsonwebtoken": "^8.5.9",
|
|
38
|
-
"@types/node": "^18.11.14",
|
|
39
|
-
"@types/ws": "^8.5.5",
|
|
40
|
-
"axios": "^1.4.0",
|
|
41
|
-
"body-parser": "^1.20.2",
|
|
42
|
-
"class-validator": "^0.14.0",
|
|
43
|
-
"cors": "^2.8.5",
|
|
44
|
-
"dotenv": "^16.0.3",
|
|
45
|
-
"env-var": "^7.3.0",
|
|
46
|
-
"express": "^4.18.2",
|
|
47
|
-
"fast-glob": "^3.3.1",
|
|
48
|
-
"graphql": "^16.8.0",
|
|
49
|
-
"graphql-ws": "^5.14.0",
|
|
50
|
-
"jsonwebtoken": "^8.5.1",
|
|
51
|
-
"jwks-rsa": "^3.0.0",
|
|
52
|
-
"lru-cache": "^10.0.0",
|
|
53
|
-
"mssql": "^10.0.2",
|
|
54
|
-
"reflect-metadata": "^0.1.13",
|
|
55
|
-
"rxjs": "^7.8.1",
|
|
56
|
-
"type-graphql": "2.0.0-beta.3",
|
|
57
|
-
"typedi": "^0.10.0",
|
|
58
|
-
"typeorm": "^0.3.20",
|
|
59
|
-
"ws": "^8.13.0",
|
|
60
|
-
"zod": "^3.22.4"
|
|
61
|
-
},
|
|
62
|
-
"devDependencies": {
|
|
63
|
-
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
|
64
|
-
"@typescript-eslint/parser": "^5.46.1",
|
|
65
|
-
"concurrently": "^7.6.0",
|
|
66
|
-
"cpy-cli": "^4.2.0",
|
|
67
|
-
"eslint": "^8.29.0",
|
|
68
|
-
"eslint-config-airbnb": "^19.0.4",
|
|
69
|
-
"eslint-config-prettier": "^8.5.0",
|
|
70
|
-
"eslint-import-resolver-typescript": "^3.5.2",
|
|
71
|
-
"eslint-plugin-import": "^2.26.0",
|
|
72
|
-
"eslint-plugin-jsx-a11y": "^6.6.1",
|
|
73
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
74
|
-
"prettier": "^2.8.1",
|
|
75
|
-
"rimraf": "^4.4.0",
|
|
76
|
-
"ts-node": "^10.9.1",
|
|
77
|
-
"ts-node-dev": "^2.0.0",
|
|
78
|
-
"typescript": "^5.3.3"
|
|
79
|
-
}
|
|
80
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@memberjunction/server",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "src/index.ts",
|
|
7
|
+
"author": "MemberJunction.com",
|
|
8
|
+
"license": "ISC",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"clean": "rimraf dist",
|
|
11
|
+
"build": "rimraf dist && tsc",
|
|
12
|
+
"watch": "tsc -w",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
14
|
+
"lint:eslint": "eslint \"**/*.{ts,js,}\" --max-warnings=0",
|
|
15
|
+
"lint:tsc": "tsc --noemit",
|
|
16
|
+
"lint": "concurrently \"npm:lint:eslint\" \"npm:lint:tsc\"",
|
|
17
|
+
"pretty": "prettier --write \"**/*.{ts,js,}\"",
|
|
18
|
+
"codegen": "cpy --flat ../codegen/output/entities/*.ts src/entities",
|
|
19
|
+
"postcodegen": "npm run pretty"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@apollo/server": "^4.9.1",
|
|
23
|
+
"@graphql-tools/utils": "^10.0.1",
|
|
24
|
+
"@memberjunction/ai": "^1.0.7",
|
|
25
|
+
"@memberjunction/ai-openai": "^1.0.7",
|
|
26
|
+
"@memberjunction/aiengine": "^1.0.7",
|
|
27
|
+
"@memberjunction/core": "^1.0.7",
|
|
28
|
+
"@memberjunction/core-entities": "^1.0.7",
|
|
29
|
+
"@memberjunction/data-context": "^1.0.7",
|
|
30
|
+
"@memberjunction/data-context-server": "^1.0.7",
|
|
31
|
+
"@memberjunction/global": "^1.0.7",
|
|
32
|
+
"@memberjunction/storage": "^1.0.7",
|
|
33
|
+
"@memberjunction/queue": "^1.0.7",
|
|
34
|
+
"@memberjunction/sqlserver-dataprovider": "^1.0.7",
|
|
35
|
+
"@memberjunction/skip-types": "^1.0.7",
|
|
36
|
+
"@types/cors": "^2.8.13",
|
|
37
|
+
"@types/jsonwebtoken": "^8.5.9",
|
|
38
|
+
"@types/node": "^18.11.14",
|
|
39
|
+
"@types/ws": "^8.5.5",
|
|
40
|
+
"axios": "^1.4.0",
|
|
41
|
+
"body-parser": "^1.20.2",
|
|
42
|
+
"class-validator": "^0.14.0",
|
|
43
|
+
"cors": "^2.8.5",
|
|
44
|
+
"dotenv": "^16.0.3",
|
|
45
|
+
"env-var": "^7.3.0",
|
|
46
|
+
"express": "^4.18.2",
|
|
47
|
+
"fast-glob": "^3.3.1",
|
|
48
|
+
"graphql": "^16.8.0",
|
|
49
|
+
"graphql-ws": "^5.14.0",
|
|
50
|
+
"jsonwebtoken": "^8.5.1",
|
|
51
|
+
"jwks-rsa": "^3.0.0",
|
|
52
|
+
"lru-cache": "^10.0.0",
|
|
53
|
+
"mssql": "^10.0.2",
|
|
54
|
+
"reflect-metadata": "^0.1.13",
|
|
55
|
+
"rxjs": "^7.8.1",
|
|
56
|
+
"type-graphql": "2.0.0-beta.3",
|
|
57
|
+
"typedi": "^0.10.0",
|
|
58
|
+
"typeorm": "^0.3.20",
|
|
59
|
+
"ws": "^8.13.0",
|
|
60
|
+
"zod": "^3.22.4"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
|
64
|
+
"@typescript-eslint/parser": "^5.46.1",
|
|
65
|
+
"concurrently": "^7.6.0",
|
|
66
|
+
"cpy-cli": "^4.2.0",
|
|
67
|
+
"eslint": "^8.29.0",
|
|
68
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
69
|
+
"eslint-config-prettier": "^8.5.0",
|
|
70
|
+
"eslint-import-resolver-typescript": "^3.5.2",
|
|
71
|
+
"eslint-plugin-import": "^2.26.0",
|
|
72
|
+
"eslint-plugin-jsx-a11y": "^6.6.1",
|
|
73
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
74
|
+
"prettier": "^2.8.1",
|
|
75
|
+
"rimraf": "^4.4.0",
|
|
76
|
+
"ts-node": "^10.9.1",
|
|
77
|
+
"ts-node-dev": "^2.0.0",
|
|
78
|
+
"typescript": "^5.3.3"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
import { ApolloServerPlugin, GraphQLRequestContextDidEncounterErrors, GraphQLRequestListenerParsingDidEnd } from '@apollo/server';
|
|
2
|
-
import { DataSource } from 'typeorm';
|
|
3
|
-
import { AppContext } from '../types';
|
|
4
|
-
|
|
5
|
-
export const TransactionPlugin: ApolloServerPlugin<AppContext> = {
|
|
6
|
-
async requestDidStart(requestContext) {
|
|
7
|
-
const start = Date.now();
|
|
8
|
-
const query = requestContext.request.query || '';
|
|
9
|
-
const isMutation = /^\s*mutation\b/i.test(query);
|
|
10
|
-
|
|
11
|
-
if (!isMutation) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Start transaction, one or more mutations. If it is just one mutation, this trans wrapper isn't really needed
|
|
16
|
-
// but there's no good way to know if it's one or more mutations, so we just start a transaction anyway and it isn't terribly expensive
|
|
17
|
-
// to do so with SQL Server anyway.
|
|
18
|
-
const dataSource: DataSource = requestContext.contextValue.dataSource;
|
|
19
|
-
const queryRunner = dataSource.createQueryRunner();
|
|
20
|
-
|
|
21
|
-
requestContext.contextValue.queryRunner = queryRunner;
|
|
22
|
-
console.log('Starting transaction wrapper, time spent: ', Date.now() - start, 'ms ');
|
|
23
|
-
await queryRunner.startTransaction();
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
didEncounterErrors: async (requestContext) => {
|
|
27
|
-
console.log('Error in transaction wrapper: ' + requestContext.errors, 'time spent: ', Date.now() - start, 'ms');
|
|
28
|
-
},
|
|
29
|
-
executionDidStart: async () => {
|
|
30
|
-
return {
|
|
31
|
-
executionDidEnd: async (err) => {
|
|
32
|
-
try {
|
|
33
|
-
if (err) {
|
|
34
|
-
console.log(
|
|
35
|
-
'Error in transaction, rolling back, time spent: ',
|
|
36
|
-
Date.now() - start,
|
|
37
|
-
'ms '
|
|
38
|
-
);
|
|
39
|
-
console.error('Rolling back transaction', err);
|
|
40
|
-
await queryRunner.rollbackTransaction();
|
|
41
|
-
} else {
|
|
42
|
-
console.log('Committing transaction, time spent: ', Date.now() - start, 'ms ');
|
|
43
|
-
await queryRunner.commitTransaction();
|
|
44
|
-
}
|
|
45
|
-
} catch (execErr) {
|
|
46
|
-
console.log('Execution Error, time spent: ', Date.now() - start, 'ms ');
|
|
47
|
-
console.error(execErr);
|
|
48
|
-
} finally {
|
|
49
|
-
await queryRunner.release();
|
|
50
|
-
console.log('Transaction complete, time spent: ', Date.now() - start, 'ms ');
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
},
|
|
57
|
-
};
|
|
1
|
+
import { ApolloServerPlugin, GraphQLRequestContextDidEncounterErrors, GraphQLRequestListenerParsingDidEnd } from '@apollo/server';
|
|
2
|
+
import { DataSource } from 'typeorm';
|
|
3
|
+
import { AppContext } from '../types';
|
|
4
|
+
|
|
5
|
+
export const TransactionPlugin: ApolloServerPlugin<AppContext> = {
|
|
6
|
+
async requestDidStart(requestContext) {
|
|
7
|
+
const start = Date.now();
|
|
8
|
+
const query = requestContext.request.query || '';
|
|
9
|
+
const isMutation = /^\s*mutation\b/i.test(query);
|
|
10
|
+
|
|
11
|
+
if (!isMutation) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Start transaction, one or more mutations. If it is just one mutation, this trans wrapper isn't really needed
|
|
16
|
+
// but there's no good way to know if it's one or more mutations, so we just start a transaction anyway and it isn't terribly expensive
|
|
17
|
+
// to do so with SQL Server anyway.
|
|
18
|
+
const dataSource: DataSource = requestContext.contextValue.dataSource;
|
|
19
|
+
const queryRunner = dataSource.createQueryRunner();
|
|
20
|
+
|
|
21
|
+
requestContext.contextValue.queryRunner = queryRunner;
|
|
22
|
+
console.log('Starting transaction wrapper, time spent: ', Date.now() - start, 'ms ');
|
|
23
|
+
await queryRunner.startTransaction();
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
didEncounterErrors: async (requestContext) => {
|
|
27
|
+
console.log('Error in transaction wrapper: ' + requestContext.errors, 'time spent: ', Date.now() - start, 'ms');
|
|
28
|
+
},
|
|
29
|
+
executionDidStart: async () => {
|
|
30
|
+
return {
|
|
31
|
+
executionDidEnd: async (err) => {
|
|
32
|
+
try {
|
|
33
|
+
if (err) {
|
|
34
|
+
console.log(
|
|
35
|
+
'Error in transaction, rolling back, time spent: ',
|
|
36
|
+
Date.now() - start,
|
|
37
|
+
'ms '
|
|
38
|
+
);
|
|
39
|
+
console.error('Rolling back transaction', err);
|
|
40
|
+
await queryRunner.rollbackTransaction();
|
|
41
|
+
} else {
|
|
42
|
+
console.log('Committing transaction, time spent: ', Date.now() - start, 'ms ');
|
|
43
|
+
await queryRunner.commitTransaction();
|
|
44
|
+
}
|
|
45
|
+
} catch (execErr) {
|
|
46
|
+
console.log('Execution Error, time spent: ', Date.now() - start, 'ms ');
|
|
47
|
+
console.error(execErr);
|
|
48
|
+
} finally {
|
|
49
|
+
await queryRunner.release();
|
|
50
|
+
console.log('Transaction complete, time spent: ', Date.now() - start, 'ms ');
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { ApolloServer, ApolloServerOptions } from '@apollo/server';
|
|
2
|
-
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
|
|
3
|
-
import { PubSub } from 'graphql-subscriptions';
|
|
4
|
-
import { Disposable } from 'graphql-ws';
|
|
5
|
-
import { Server } from 'http';
|
|
6
|
-
import { enableIntrospection } from '../config';
|
|
7
|
-
import { AppContext } from '../types';
|
|
8
|
-
import { TransactionPlugin } from './TransactionPlugin';
|
|
9
|
-
|
|
10
|
-
const buildApolloServer = (
|
|
11
|
-
configOverride: ApolloServerOptions<AppContext>,
|
|
12
|
-
{ httpServer, serverCleanup }: { httpServer: Server; serverCleanup: Disposable }
|
|
13
|
-
) =>
|
|
14
|
-
new ApolloServer({
|
|
15
|
-
csrfPrevention: true,
|
|
16
|
-
cache: 'bounded',
|
|
17
|
-
plugins: [
|
|
18
|
-
ApolloServerPluginDrainHttpServer({ httpServer }),
|
|
19
|
-
TransactionPlugin,
|
|
20
|
-
{
|
|
21
|
-
async serverWillStart() {
|
|
22
|
-
return {
|
|
23
|
-
async drainServer() {
|
|
24
|
-
await serverCleanup.dispose();
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
introspection: enableIntrospection,
|
|
31
|
-
...configOverride,
|
|
32
|
-
});
|
|
33
|
-
|
|
1
|
+
import { ApolloServer, ApolloServerOptions } from '@apollo/server';
|
|
2
|
+
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
|
|
3
|
+
import { PubSub } from 'graphql-subscriptions';
|
|
4
|
+
import { Disposable } from 'graphql-ws';
|
|
5
|
+
import { Server } from 'http';
|
|
6
|
+
import { enableIntrospection } from '../config';
|
|
7
|
+
import { AppContext } from '../types';
|
|
8
|
+
import { TransactionPlugin } from './TransactionPlugin';
|
|
9
|
+
|
|
10
|
+
const buildApolloServer = (
|
|
11
|
+
configOverride: ApolloServerOptions<AppContext>,
|
|
12
|
+
{ httpServer, serverCleanup }: { httpServer: Server; serverCleanup: Disposable }
|
|
13
|
+
) =>
|
|
14
|
+
new ApolloServer({
|
|
15
|
+
csrfPrevention: true,
|
|
16
|
+
cache: 'bounded',
|
|
17
|
+
plugins: [
|
|
18
|
+
ApolloServerPluginDrainHttpServer({ httpServer }),
|
|
19
|
+
TransactionPlugin,
|
|
20
|
+
{
|
|
21
|
+
async serverWillStart() {
|
|
22
|
+
return {
|
|
23
|
+
async drainServer() {
|
|
24
|
+
await serverCleanup.dispose();
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
introspection: enableIntrospection,
|
|
31
|
+
...configOverride,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
34
|
export default buildApolloServer;
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import { RegisterClass } from "@memberjunction/global";
|
|
2
|
-
import { Metadata, RunView, LogError } from "@memberjunction/core";
|
|
3
|
-
import { NewUserBase } from "./newUsers";
|
|
4
|
-
import { UserCache } from "@memberjunction/sqlserver-dataprovider";
|
|
5
|
-
import { configInfo } from "../config";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* This example class subclasses the @NewUserBase class and overrides the createNewUser method to create a new person record and then call the base class to create the user record. In this example there is an entity
|
|
9
|
-
* called "Persons" that is mapped to the User table in the core MemberJunction schema. You can sub-class the NewUserBase to do whatever behavior you want and pre-process, post-process or entirely override the base
|
|
10
|
-
* class behavior.
|
|
11
|
-
*/
|
|
12
|
-
// NOTE: This is commented out becuase it is turned off by default. To make this work, you'd have to do a real implementation below, and then uncomment this decorator
|
|
13
|
-
// so that your class is actually used.
|
|
14
|
-
//@RegisterClass(NewUserBase, undefined, 1) /*by putting 1 into the priority setting, MJGlobal ClassFactory will use this instead of the base class as that registration had no priority*/
|
|
15
|
-
export class ExampleNewUserSubClass extends NewUserBase {
|
|
16
|
-
public override async createNewUser(firstName: string, lastName: string, email: string) {
|
|
17
|
-
try {
|
|
18
|
-
const md = new Metadata();
|
|
19
|
-
const contextUser = UserCache.Instance.Users.find(u => u.Email.trim().toLowerCase() === configInfo?.userHandling?.contextUserForNewUserCreation?.trim().toLowerCase())
|
|
20
|
-
if(!contextUser) {
|
|
21
|
-
LogError(`Failed to load context user ${configInfo?.userHandling?.contextUserForNewUserCreation}, if you've not specified this on your config.json you must do so. This is the user that is contextually used for creating a new user record dynamically.`);
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const pEntity = md.Entities.find(e => e.Name === 'Persons'); // look up the entity info for the Persons entity
|
|
26
|
-
if (!pEntity) {
|
|
27
|
-
LogError('Failed to find Persons entity');
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let personId;
|
|
32
|
-
// this block of code only executes if we have an entity called Persons
|
|
33
|
-
const rv = new RunView();
|
|
34
|
-
const viewResults = await rv.RunView({
|
|
35
|
-
EntityName: 'Persons',
|
|
36
|
-
ExtraFilter: `Email = '${email}'`
|
|
37
|
-
}, contextUser)
|
|
38
|
-
|
|
39
|
-
if (viewResults && viewResults.Success && Array.isArray(viewResults.Results) && viewResults.Results.length > 0) {
|
|
40
|
-
// we have a match so use it
|
|
41
|
-
const row = (viewResults.Results as { ID: number }[])[0]; // we know the rows will have an ID number
|
|
42
|
-
personId = row['ID'];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!personId) {
|
|
46
|
-
// we don't have a match so create a new person record
|
|
47
|
-
const p = await md.GetEntityObject('Persons', contextUser);
|
|
48
|
-
p.NewRecord(); // assumes we have an entity called Persons that has FirstName/LastName/Email fields
|
|
49
|
-
// this code is commented out because we don't have a strongly typed sub-class generatd for this "Persons" entity as it is a demo/hypothetical example
|
|
50
|
-
//p.FirstName = firstName;
|
|
51
|
-
//p.LastName = lastName;
|
|
52
|
-
//p.Email = email;
|
|
53
|
-
//p.Status = 'active';
|
|
54
|
-
if (await p.Save()) {
|
|
55
|
-
personId = p.PrimaryKey.Value; // if we had a strongly typed sub-class above, we could use this code p.ID;
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
LogError(`Failed to create new person ${firstName} ${lastName} ${email}`)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// now call the base class to create the user, and pass in our LinkedRecordType and ID
|
|
63
|
-
return super.createNewUser(firstName, lastName, email, 'Other', pEntity?.ID, personId);
|
|
64
|
-
}
|
|
65
|
-
catch (e) {
|
|
66
|
-
LogError(`Error creating new user ${email} ${e}`);
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function LoadExampleNewUserSubClass() {
|
|
73
|
-
// do nothing, just having this forces the above class to get registered via its @RegisterClass decorator
|
|
1
|
+
import { RegisterClass } from "@memberjunction/global";
|
|
2
|
+
import { Metadata, RunView, LogError } from "@memberjunction/core";
|
|
3
|
+
import { NewUserBase } from "./newUsers";
|
|
4
|
+
import { UserCache } from "@memberjunction/sqlserver-dataprovider";
|
|
5
|
+
import { configInfo } from "../config";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This example class subclasses the @NewUserBase class and overrides the createNewUser method to create a new person record and then call the base class to create the user record. In this example there is an entity
|
|
9
|
+
* called "Persons" that is mapped to the User table in the core MemberJunction schema. You can sub-class the NewUserBase to do whatever behavior you want and pre-process, post-process or entirely override the base
|
|
10
|
+
* class behavior.
|
|
11
|
+
*/
|
|
12
|
+
// NOTE: This is commented out becuase it is turned off by default. To make this work, you'd have to do a real implementation below, and then uncomment this decorator
|
|
13
|
+
// so that your class is actually used.
|
|
14
|
+
//@RegisterClass(NewUserBase, undefined, 1) /*by putting 1 into the priority setting, MJGlobal ClassFactory will use this instead of the base class as that registration had no priority*/
|
|
15
|
+
export class ExampleNewUserSubClass extends NewUserBase {
|
|
16
|
+
public override async createNewUser(firstName: string, lastName: string, email: string) {
|
|
17
|
+
try {
|
|
18
|
+
const md = new Metadata();
|
|
19
|
+
const contextUser = UserCache.Instance.Users.find(u => u.Email.trim().toLowerCase() === configInfo?.userHandling?.contextUserForNewUserCreation?.trim().toLowerCase())
|
|
20
|
+
if(!contextUser) {
|
|
21
|
+
LogError(`Failed to load context user ${configInfo?.userHandling?.contextUserForNewUserCreation}, if you've not specified this on your config.json you must do so. This is the user that is contextually used for creating a new user record dynamically.`);
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const pEntity = md.Entities.find(e => e.Name === 'Persons'); // look up the entity info for the Persons entity
|
|
26
|
+
if (!pEntity) {
|
|
27
|
+
LogError('Failed to find Persons entity');
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let personId;
|
|
32
|
+
// this block of code only executes if we have an entity called Persons
|
|
33
|
+
const rv = new RunView();
|
|
34
|
+
const viewResults = await rv.RunView({
|
|
35
|
+
EntityName: 'Persons',
|
|
36
|
+
ExtraFilter: `Email = '${email}'`
|
|
37
|
+
}, contextUser)
|
|
38
|
+
|
|
39
|
+
if (viewResults && viewResults.Success && Array.isArray(viewResults.Results) && viewResults.Results.length > 0) {
|
|
40
|
+
// we have a match so use it
|
|
41
|
+
const row = (viewResults.Results as { ID: number }[])[0]; // we know the rows will have an ID number
|
|
42
|
+
personId = row['ID'];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!personId) {
|
|
46
|
+
// we don't have a match so create a new person record
|
|
47
|
+
const p = await md.GetEntityObject('Persons', contextUser);
|
|
48
|
+
p.NewRecord(); // assumes we have an entity called Persons that has FirstName/LastName/Email fields
|
|
49
|
+
// this code is commented out because we don't have a strongly typed sub-class generatd for this "Persons" entity as it is a demo/hypothetical example
|
|
50
|
+
//p.FirstName = firstName;
|
|
51
|
+
//p.LastName = lastName;
|
|
52
|
+
//p.Email = email;
|
|
53
|
+
//p.Status = 'active';
|
|
54
|
+
if (await p.Save()) {
|
|
55
|
+
personId = p.PrimaryKey.Value; // if we had a strongly typed sub-class above, we could use this code p.ID;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
LogError(`Failed to create new person ${firstName} ${lastName} ${email}`)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// now call the base class to create the user, and pass in our LinkedRecordType and ID
|
|
63
|
+
return super.createNewUser(firstName, lastName, email, 'Other', pEntity?.ID, personId);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
LogError(`Error creating new user ${email} ${e}`);
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function LoadExampleNewUserSubClass() {
|
|
73
|
+
// do nothing, just having this forces the above class to get registered via its @RegisterClass decorator
|
|
74
74
|
}
|