@memberjunction/server 0.9.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/.eslintignore +5 -0
- package/.eslintrc +24 -0
- package/README.md +141 -0
- package/config.json +15 -0
- package/dist/apolloServer/TransactionPlugin.js +46 -0
- package/dist/apolloServer/TransactionPlugin.js.map +1 -0
- package/dist/apolloServer/index.js +27 -0
- package/dist/apolloServer/index.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.js +68 -0
- package/dist/auth/exampleNewUserSubClass.js.map +1 -0
- package/dist/auth/index.js +88 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/newUsers.js +67 -0
- package/dist/auth/newUsers.js.map +1 -0
- package/dist/cache.js +11 -0
- package/dist/cache.js.map +1 -0
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +101 -0
- package/dist/context.js.map +1 -0
- package/dist/directives/Public.js +34 -0
- package/dist/directives/Public.js.map +1 -0
- package/dist/directives/index.js +18 -0
- package/dist/directives/index.js.map +1 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -0
- package/dist/orm.js +23 -0
- package/dist/orm.js.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +74 -0
- package/src/apolloServer/TransactionPlugin.ts +54 -0
- package/src/apolloServer/index.ts +34 -0
- package/src/auth/exampleNewUserSubClass.ts +71 -0
- package/src/auth/index.ts +117 -0
- package/src/auth/newUsers.ts +56 -0
- package/src/cache.ts +10 -0
- package/src/config.ts +67 -0
- package/src/context.ts +105 -0
- package/src/directives/Public.ts +42 -0
- package/src/directives/index.ts +1 -0
- package/src/index.ts +103 -0
- package/src/orm.ts +20 -0
- package/src/types.ts +19 -0
- package/tsconfig.json +27 -0
package/dist/context.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.contextFunction = exports.getUserPayload = void 0;
|
|
27
|
+
const url = __importStar(require("url"));
|
|
28
|
+
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
29
|
+
require("reflect-metadata");
|
|
30
|
+
const rxjs_1 = require("rxjs");
|
|
31
|
+
const type_graphql_1 = require("type-graphql");
|
|
32
|
+
const auth_1 = require("./auth");
|
|
33
|
+
const cache_1 = require("./cache");
|
|
34
|
+
const config_1 = require("./config");
|
|
35
|
+
const verifyAsync = async (issuer, options, token) => new Promise((resolve, reject) => {
|
|
36
|
+
(0, jsonwebtoken_1.verify)(token, (0, auth_1.getSigningKeys)(issuer), options, (err, jwt) => {
|
|
37
|
+
if (jwt && typeof jwt !== 'string' && !err) {
|
|
38
|
+
const payload = jwt.payload ?? jwt;
|
|
39
|
+
console.log(`Valid token: ${payload.name} (${payload.email ? payload.email : payload.preferred_username})`);
|
|
40
|
+
resolve(payload);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.warn('Invalid token');
|
|
44
|
+
reject(err);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
const getUserPayload = async (bearerToken, sessionId = 'default', dataSource, requestDomain) => {
|
|
49
|
+
try {
|
|
50
|
+
const token = bearerToken.replace('Bearer ', '');
|
|
51
|
+
if (!token) {
|
|
52
|
+
console.warn('No token to validate');
|
|
53
|
+
throw new type_graphql_1.AuthenticationError('Missing token');
|
|
54
|
+
}
|
|
55
|
+
const payload = (0, jsonwebtoken_1.decode)(token);
|
|
56
|
+
if (!payload || typeof payload === 'string') {
|
|
57
|
+
throw new type_graphql_1.AuthenticationError('Invalid token payload');
|
|
58
|
+
}
|
|
59
|
+
if (!cache_1.authCache.has(token)) {
|
|
60
|
+
const issuer = payload.iss;
|
|
61
|
+
if (!issuer) {
|
|
62
|
+
console.warn('No issuer claim on token');
|
|
63
|
+
throw new type_graphql_1.AuthenticationError('Missing issuer claim on token');
|
|
64
|
+
}
|
|
65
|
+
await verifyAsync(issuer, auth_1.validationOptions[issuer], token);
|
|
66
|
+
cache_1.authCache.set(token, true);
|
|
67
|
+
}
|
|
68
|
+
const email = payload?.email
|
|
69
|
+
? config_1.userEmailMap[payload?.email] ?? payload?.email
|
|
70
|
+
: payload?.preferred_username;
|
|
71
|
+
const fullName = payload?.name;
|
|
72
|
+
const firstName = payload?.given_name || fullName?.split(' ')[0];
|
|
73
|
+
const lastName = payload?.family_name || fullName?.split(' ')[1] || fullName?.split(' ')[0];
|
|
74
|
+
const userRecord = await (0, auth_1.verifyUserRecord)(email, firstName, lastName, requestDomain, dataSource);
|
|
75
|
+
if (!userRecord) {
|
|
76
|
+
console.error(`User ${email} not found`);
|
|
77
|
+
throw new type_graphql_1.AuthorizationError();
|
|
78
|
+
}
|
|
79
|
+
else if (!userRecord.IsActive) {
|
|
80
|
+
console.error(`User ${email} found but inactive`);
|
|
81
|
+
throw new type_graphql_1.AuthorizationError();
|
|
82
|
+
}
|
|
83
|
+
return { userRecord, email, sessionId };
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
exports.getUserPayload = getUserPayload;
|
|
90
|
+
const contextFunction = ({ setupComplete$, dataSource }) => async ({ req }) => {
|
|
91
|
+
await (0, rxjs_1.firstValueFrom)(setupComplete$);
|
|
92
|
+
const sessionIdRaw = req.headers['x-session-id'];
|
|
93
|
+
const requestDomain = url.parse(req.headers.origin || '');
|
|
94
|
+
const sessionId = sessionIdRaw ? sessionIdRaw.toString() : '';
|
|
95
|
+
const bearerToken = req.headers.authorization ?? '';
|
|
96
|
+
const userPayload = await (0, exports.getUserPayload)(bearerToken, sessionId, dataSource, requestDomain?.hostname ? requestDomain.hostname : undefined);
|
|
97
|
+
console.log(req.body?.operationName);
|
|
98
|
+
return { dataSource, userPayload };
|
|
99
|
+
};
|
|
100
|
+
exports.contextFunction = contextFunction;
|
|
101
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.publicDirective = exports.Public = void 0;
|
|
4
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const DIRECTIVE_NAME = 'Public';
|
|
8
|
+
function Public() {
|
|
9
|
+
return (targetOrPrototype, propertyKey, descriptor) => (0, type_graphql_1.Directive)(`@${DIRECTIVE_NAME}`)(targetOrPrototype, propertyKey, descriptor);
|
|
10
|
+
}
|
|
11
|
+
exports.Public = Public;
|
|
12
|
+
exports.publicDirective = {
|
|
13
|
+
typeDefs: `directive @${DIRECTIVE_NAME} on FIELD_DEFINITION`,
|
|
14
|
+
transformer: (schema) => {
|
|
15
|
+
const fieldMapper = (fieldConfig) => {
|
|
16
|
+
const directive = (0, utils_1.getDirective)(schema, fieldConfig, DIRECTIVE_NAME)?.[0];
|
|
17
|
+
if (directive) {
|
|
18
|
+
return fieldConfig;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const { resolve = graphql_1.defaultFieldResolver } = fieldConfig;
|
|
22
|
+
const directiveResolver = async (source, args, context, info) => {
|
|
23
|
+
if (!context?.userPayload?.userRecord?.IsActive) {
|
|
24
|
+
throw new type_graphql_1.AuthorizationError();
|
|
25
|
+
}
|
|
26
|
+
return await resolve(source, args, context, info);
|
|
27
|
+
};
|
|
28
|
+
return { ...fieldConfig, resolve: directiveResolver };
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return (0, utils_1.mapSchema)(schema, { [utils_1.MapperKind.OBJECT_FIELD]: fieldMapper });
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=Public.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Public.js","sourceRoot":"","sources":["../../src/directives/Public.ts"],"names":[],"mappings":";;;AAAA,gDAAwF;AACxF,qCAAqE;AACrE,+CAA6D;AAG7D,MAAM,cAAc,GAAG,QAAQ,CAAC;AAGhC,SAAgB,MAAM;IACpB,OAAO,CAAC,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,CACpD,IAAA,wBAAS,EAAC,IAAI,cAAc,EAAE,CAAC,CAAC,iBAAiB,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;AAChF,CAAC;AAHD,wBAGC;AAEY,QAAA,eAAe,GAAqB;IAC/C,QAAQ,EAAE,cAAc,cAAc,sBAAsB;IAC5D,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE;QACtB,MAAM,WAAW,GAAgB,CAAC,WAAW,EAAE,EAAE;YAC/C,MAAM,SAAS,GAAG,IAAA,oBAAY,EAAC,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACzE,IAAI,SAAS,EAAE;gBACb,OAAO,WAAW,CAAC;aACpB;iBAAM;gBAEL,MAAM,EAAE,OAAO,GAAG,8BAAoB,EAAE,GAAG,WAAW,CAAC;gBACvD,MAAM,iBAAiB,GAA8C,KAAK,EACxE,MAAM,EACN,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,EAAE;oBAEF,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE;wBAC/C,MAAM,IAAI,iCAAkB,EAAE,CAAC;qBAChC;oBACD,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;gBACpD,CAAC,CAAC;gBAEF,OAAO,EAAE,GAAG,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;aACvD;QACH,CAAC,CAAC;QACF,OAAO,IAAA,iBAAS,EAAC,MAAM,EAAE,EAAE,CAAC,kBAAU,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IACvE,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Public"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/directives/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
|
+
if (mod && mod.__esModule) return mod;
|
|
23
|
+
var result = {};
|
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
25
|
+
__setModuleDefault(result, mod);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
29
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.serve = exports.MaxLength = exports.NewUserBase = exports.configInfo = void 0;
|
|
33
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
34
|
+
dotenv_1.default.config();
|
|
35
|
+
const express4_1 = require("@apollo/server/express4");
|
|
36
|
+
const schema_1 = require("@graphql-tools/schema");
|
|
37
|
+
const core_1 = require("@memberjunction/core");
|
|
38
|
+
const sqlserver_dataprovider_1 = require("@memberjunction/sqlserver-dataprovider");
|
|
39
|
+
const body_parser_1 = require("body-parser");
|
|
40
|
+
const cors_1 = __importDefault(require("cors"));
|
|
41
|
+
const express_1 = __importDefault(require("express"));
|
|
42
|
+
const fast_glob_1 = require("fast-glob");
|
|
43
|
+
const ws_1 = require("graphql-ws/lib/use/ws");
|
|
44
|
+
const node_http_1 = require("node:http");
|
|
45
|
+
require("reflect-metadata");
|
|
46
|
+
const rxjs_1 = require("rxjs");
|
|
47
|
+
const type_graphql_1 = require("type-graphql");
|
|
48
|
+
const typeorm_1 = require("typeorm");
|
|
49
|
+
const ws_2 = require("ws");
|
|
50
|
+
const apolloServer_1 = __importDefault(require("./apolloServer"));
|
|
51
|
+
const config_1 = require("./config");
|
|
52
|
+
const context_1 = require("./context");
|
|
53
|
+
const directives_1 = require("./directives");
|
|
54
|
+
const orm_1 = __importDefault(require("./orm"));
|
|
55
|
+
const cacheRefreshInterval = config_1.configInfo.databaseSettings.metadataCacheRefreshInterval;
|
|
56
|
+
var config_2 = require("./config");
|
|
57
|
+
Object.defineProperty(exports, "configInfo", { enumerable: true, get: function () { return config_2.configInfo; } });
|
|
58
|
+
var newUsers_1 = require("./auth/newUsers");
|
|
59
|
+
Object.defineProperty(exports, "NewUserBase", { enumerable: true, get: function () { return newUsers_1.NewUserBase; } });
|
|
60
|
+
var class_validator_1 = require("class-validator");
|
|
61
|
+
Object.defineProperty(exports, "MaxLength", { enumerable: true, get: function () { return class_validator_1.MaxLength; } });
|
|
62
|
+
__exportStar(require("./types"), exports);
|
|
63
|
+
__exportStar(require("./directives"), exports);
|
|
64
|
+
__exportStar(require("type-graphql"), exports);
|
|
65
|
+
const serve = async (resolverPaths) => {
|
|
66
|
+
const dataSource = new typeorm_1.DataSource(orm_1.default);
|
|
67
|
+
const setupComplete$ = new rxjs_1.ReplaySubject(1);
|
|
68
|
+
dataSource
|
|
69
|
+
.initialize()
|
|
70
|
+
.then(async () => {
|
|
71
|
+
const config = new sqlserver_dataprovider_1.SQLServerProviderConfigData(dataSource, '', config_1.mj_core_schema, cacheRefreshInterval);
|
|
72
|
+
await (0, sqlserver_dataprovider_1.setupSQLServerClient)(config);
|
|
73
|
+
const md = new core_1.Metadata();
|
|
74
|
+
console.log(`Data Source has been initialized. ${md?.Entities ? md.Entities.length : 0} entities loaded.`);
|
|
75
|
+
setupComplete$.next(true);
|
|
76
|
+
})
|
|
77
|
+
.catch((err) => {
|
|
78
|
+
console.error('Error during Data Source initialization', err);
|
|
79
|
+
});
|
|
80
|
+
const paths = resolverPaths.flatMap((path) => (0, fast_glob_1.globSync)(path));
|
|
81
|
+
const dynamicModules = await Promise.all(paths.map((modulePath) => { var _a; return _a = modulePath.replace(/\.[jt]s$/, ''), Promise.resolve().then(() => __importStar(require(_a))); }));
|
|
82
|
+
const resolvers = dynamicModules.flatMap((module) => Object.values(module).filter((value) => typeof value === 'function'));
|
|
83
|
+
const schema = directives_1.publicDirective.transformer((0, schema_1.mergeSchemas)({
|
|
84
|
+
schemas: [
|
|
85
|
+
(0, type_graphql_1.buildSchemaSync)({
|
|
86
|
+
resolvers,
|
|
87
|
+
validate: false,
|
|
88
|
+
scalarsMap: [{ type: Date, scalar: type_graphql_1.GraphQLTimestamp }],
|
|
89
|
+
emitSchemaFile: config_1.websiteRunFromPackage !== 1,
|
|
90
|
+
}),
|
|
91
|
+
],
|
|
92
|
+
typeDefs: [directives_1.publicDirective.typeDefs],
|
|
93
|
+
}));
|
|
94
|
+
const app = (0, express_1.default)();
|
|
95
|
+
const httpServer = (0, node_http_1.createServer)(app);
|
|
96
|
+
const webSocketServer = new ws_2.WebSocketServer({ server: httpServer, path: config_1.graphqlRootPath });
|
|
97
|
+
const serverCleanup = (0, ws_1.useServer)({
|
|
98
|
+
schema,
|
|
99
|
+
context: async ({ connectionParams }) => {
|
|
100
|
+
const userPayload = await (0, context_1.getUserPayload)(String(connectionParams?.Authorization), undefined, dataSource);
|
|
101
|
+
return { userPayload };
|
|
102
|
+
},
|
|
103
|
+
}, webSocketServer);
|
|
104
|
+
const apolloServer = (0, apolloServer_1.default)({ schema }, { httpServer, serverCleanup });
|
|
105
|
+
await apolloServer.start();
|
|
106
|
+
app.use(config_1.graphqlRootPath, (0, cors_1.default)(), (0, body_parser_1.json)(), (0, express4_1.expressMiddleware)(apolloServer, {
|
|
107
|
+
context: (0, context_1.contextFunction)({ setupComplete$, dataSource }),
|
|
108
|
+
}));
|
|
109
|
+
await new Promise((resolve) => httpServer.listen({ port: config_1.graphqlPort }, resolve));
|
|
110
|
+
console.log(`🚀 Server ready at http://localhost:${config_1.graphqlPort}/`);
|
|
111
|
+
};
|
|
112
|
+
exports.serve = serve;
|
|
113
|
+
exports.default = exports.serve;
|
|
114
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/orm.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
const orm = {
|
|
9
|
+
type: 'mssql',
|
|
10
|
+
entities: [node_path_1.default.resolve(__dirname, './generated/**')],
|
|
11
|
+
migrations: [node_path_1.default.resolve(__dirname, './migrations/**')],
|
|
12
|
+
logging: false,
|
|
13
|
+
host: config_1.dbHost,
|
|
14
|
+
port: config_1.dbPort,
|
|
15
|
+
username: config_1.dbUsername,
|
|
16
|
+
password: config_1.dbPassword,
|
|
17
|
+
database: config_1.dbDatabase,
|
|
18
|
+
synchronize: false,
|
|
19
|
+
requestTimeout: config_1.configInfo.databaseSettings.requestTimeout,
|
|
20
|
+
connectionTimeout: config_1.configInfo.databaseSettings.connectionTimeout,
|
|
21
|
+
};
|
|
22
|
+
exports.default = orm;
|
|
23
|
+
//# sourceMappingURL=orm.js.map
|
package/dist/orm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orm.js","sourceRoot":"","sources":["../src/orm.ts"],"names":[],"mappings":";;;;;AAAA,0DAA6B;AAC7B,qCAA0F;AAG1F,MAAM,GAAG,GAAsB;IAC7B,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,CAAC,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACrD,UAAU,EAAE,CAAC,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IACxD,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,eAAM;IACZ,IAAI,EAAE,eAAM;IACZ,QAAQ,EAAE,mBAAU;IACpB,QAAQ,EAAE,mBAAU;IACpB,QAAQ,EAAE,mBAAU;IACpB,WAAW,EAAE,KAAK;IAClB,cAAc,EAAE,mBAAU,CAAC,gBAAgB,CAAC,cAAc;IAC1D,iBAAiB,EAAE,mBAAU,CAAC,gBAAgB,CAAC,iBAAiB;CACjE,CAAC;AAEF,kBAAe,GAAG,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@memberjunction/server",
|
|
3
|
+
"version": "0.9.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": "^0.9.17",
|
|
25
|
+
"@memberjunction/core": "^0.9.20",
|
|
26
|
+
"@memberjunction/global": "^0.9.19",
|
|
27
|
+
"@memberjunction/queue": "^0.9.17",
|
|
28
|
+
"@memberjunction/sqlserver-dataprovider": "^0.9.17",
|
|
29
|
+
"axios": "^1.4.0",
|
|
30
|
+
"body-parser": "^1.20.2",
|
|
31
|
+
"class-validator": "^0.14.0",
|
|
32
|
+
"cors": "^2.8.5",
|
|
33
|
+
"dotenv": "^16.0.3",
|
|
34
|
+
"env-var": "^7.3.0",
|
|
35
|
+
"express": "^4.18.2",
|
|
36
|
+
"fast-glob": "^3.3.1",
|
|
37
|
+
"graphql": "^16.8.0",
|
|
38
|
+
"graphql-ws": "^5.14.0",
|
|
39
|
+
"jsonwebtoken": "^8.5.1",
|
|
40
|
+
"jwks-rsa": "^3.0.0",
|
|
41
|
+
"lru-cache": "^10.0.0",
|
|
42
|
+
"mssql": "^9.1.1",
|
|
43
|
+
"reflect-metadata": "^0.1.13",
|
|
44
|
+
"rxjs": "^7.8.1",
|
|
45
|
+
"type-graphql": "^2.0.0-beta.3",
|
|
46
|
+
"typedi": "^0.10.0",
|
|
47
|
+
"typeorm": "^0.3.13",
|
|
48
|
+
"ws": "^8.13.0",
|
|
49
|
+
"zod": "^3.22.4"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/axios": "^0.14.0",
|
|
53
|
+
"@types/cors": "^2.8.13",
|
|
54
|
+
"@types/jsonwebtoken": "^8.5.9",
|
|
55
|
+
"@types/node": "^18.11.14",
|
|
56
|
+
"@types/ws": "^8.5.5",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
|
58
|
+
"@typescript-eslint/parser": "^5.46.1",
|
|
59
|
+
"concurrently": "^7.6.0",
|
|
60
|
+
"cpy-cli": "^4.2.0",
|
|
61
|
+
"eslint": "^8.29.0",
|
|
62
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
63
|
+
"eslint-config-prettier": "^8.5.0",
|
|
64
|
+
"eslint-import-resolver-typescript": "^3.5.2",
|
|
65
|
+
"eslint-plugin-import": "^2.26.0",
|
|
66
|
+
"eslint-plugin-jsx-a11y": "^6.6.1",
|
|
67
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
68
|
+
"prettier": "^2.8.1",
|
|
69
|
+
"rimraf": "^4.4.0",
|
|
70
|
+
"ts-node": "^10.9.1",
|
|
71
|
+
"ts-node-dev": "^2.0.0",
|
|
72
|
+
"typescript": "^4.9.4"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ApolloServerPlugin } 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;
|
|
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
|
+
executionDidStart: async () => {
|
|
27
|
+
return {
|
|
28
|
+
executionDidEnd: async (err) => {
|
|
29
|
+
try {
|
|
30
|
+
if (err) {
|
|
31
|
+
console.log(
|
|
32
|
+
'Error in transaction, rolling back, time spent: ',
|
|
33
|
+
Date.now() - start,
|
|
34
|
+
'ms '
|
|
35
|
+
);
|
|
36
|
+
console.error('Rolling back transaction', err);
|
|
37
|
+
await queryRunner.rollbackTransaction();
|
|
38
|
+
} else {
|
|
39
|
+
console.log('Committing transaction, time spent: ', Date.now() - start, 'ms ');
|
|
40
|
+
await queryRunner.commitTransaction();
|
|
41
|
+
}
|
|
42
|
+
} catch (execErr) {
|
|
43
|
+
console.log('Execution Error, time spent: ', Date.now() - start, 'ms ');
|
|
44
|
+
console.error(execErr);
|
|
45
|
+
} finally {
|
|
46
|
+
await queryRunner.release();
|
|
47
|
+
console.log('Transaction complete, time spent: ', Date.now() - start, 'ms ');
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -0,0 +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
|
+
|
|
34
|
+
export default buildApolloServer;
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
@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*/
|
|
13
|
+
export class ExampleNewUserSubClass extends NewUserBase {
|
|
14
|
+
public override async createNewUser(firstName: string, lastName: string, email: string) {
|
|
15
|
+
try {
|
|
16
|
+
const md = new Metadata();
|
|
17
|
+
const contextUser = UserCache.Instance.Users.find(u => u.Email.trim().toLowerCase() === configInfo?.userHandling?.contextUserForNewUserCreation?.trim().toLowerCase())
|
|
18
|
+
if(!contextUser) {
|
|
19
|
+
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.`);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const pEntity = md.Entities.find(e => e.Name === 'Persons'); // look up the entity info for the Persons entity
|
|
24
|
+
if (!pEntity) {
|
|
25
|
+
LogError('Failed to find Persons entity');
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let personId;
|
|
30
|
+
// this block of code only executes if we have an entity called Persons
|
|
31
|
+
const rv = new RunView();
|
|
32
|
+
const viewResults = await rv.RunView({
|
|
33
|
+
EntityName: 'Persons',
|
|
34
|
+
ExtraFilter: `Email = '${email}'`
|
|
35
|
+
}, contextUser)
|
|
36
|
+
|
|
37
|
+
if (viewResults && viewResults.Success && Array.isArray(viewResults.Results) && viewResults.Results.length > 0) {
|
|
38
|
+
// we have a match so use it
|
|
39
|
+
const row = (viewResults.Results as { ID: number }[])[0]; // we know the rows will have an ID number
|
|
40
|
+
personId = row['ID'];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!personId) {
|
|
44
|
+
// we don't have a match so create a new person record
|
|
45
|
+
const p = await md.GetEntityObject('Persons', contextUser);
|
|
46
|
+
p.NewRecord(); // assumes we have an entity called Persons that has FirstName/LastName/Email fields
|
|
47
|
+
p.FirstName = firstName;
|
|
48
|
+
p.LastName = lastName;
|
|
49
|
+
p.Email = email;
|
|
50
|
+
p.Status = 'active';
|
|
51
|
+
if (await p.Save()) {
|
|
52
|
+
personId = p.ID;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
LogError(`Failed to create new person ${firstName} ${lastName} ${email}`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// now call the base class to create the user, and pass in our LinkedRecordType and ID
|
|
60
|
+
return super.createNewUser(firstName, lastName, email, 'Other', pEntity?.ID, personId);
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
LogError(`Error creating new user ${email} ${e}`);
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function LoadExampleNewUserSubClass() {
|
|
70
|
+
// do nothing, just having this forces the above class to get registered via its @RegisterClass decorator
|
|
71
|
+
}
|