@memberjunction/server 2.1.4 → 2.2.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/apolloServer/TransactionPlugin.d.ts +1 -1
- package/dist/apolloServer/TransactionPlugin.d.ts.map +1 -1
- package/dist/apolloServer/TransactionPlugin.js.map +1 -1
- package/dist/apolloServer/index.d.ts +1 -1
- package/dist/apolloServer/index.d.ts.map +1 -1
- package/dist/apolloServer/index.js +2 -2
- package/dist/apolloServer/index.js.map +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +7 -7
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +18 -8
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/newUsers.js +1 -1
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +4 -4
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.d.ts +1 -1
- package/dist/directives/Public.d.ts.map +1 -1
- package/dist/directives/index.d.ts +1 -1
- package/dist/directives/index.d.ts.map +1 -1
- package/dist/directives/index.js +1 -1
- package/dist/directives/index.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +5 -6
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +5 -31
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +33 -189
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +3 -3
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +1 -1
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +2 -2
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +1 -1
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +21 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -27
- package/dist/index.js.map +1 -1
- package/dist/orm.js +4 -4
- package/dist/orm.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +3 -3
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +57 -55
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/ColorResolver.d.ts +1 -1
- package/dist/resolvers/ColorResolver.d.ts.map +1 -1
- package/dist/resolvers/ColorResolver.js +1 -1
- package/dist/resolvers/ColorResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +1 -1
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +2 -2
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +9 -4
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -2
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +2 -2
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/EntityResolver.d.ts +2 -2
- package/dist/resolvers/EntityResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityResolver.js +1 -1
- package/dist/resolvers/EntityResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +2 -2
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +2 -2
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +3 -3
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +2 -2
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +4 -2
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts +2 -2
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.d.ts +1 -1
- package/dist/resolvers/ReportResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.js +16 -14
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +17 -16
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +1 -1
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +1 -1
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +2 -2
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +11 -5
- package/dist/util.js.map +1 -1
- package/package.json +27 -23
- package/src/apolloServer/TransactionPlugin.ts +53 -0
- package/src/apolloServer/index.ts +33 -0
- package/src/auth/exampleNewUserSubClass.ts +79 -0
- package/src/auth/index.ts +171 -0
- package/src/auth/newUsers.ts +58 -0
- package/src/auth/tokenExpiredError.ts +12 -0
- package/src/cache.ts +10 -0
- package/src/config.ts +89 -0
- package/src/context.ts +111 -0
- package/src/directives/Public.ts +42 -0
- package/src/directives/index.ts +1 -0
- package/src/entitySubclasses/DuplicateRunEntity.server.ts +29 -0
- package/src/entitySubclasses/entityPermissions.server.ts +104 -0
- package/src/entitySubclasses/userViewEntity.server.ts +187 -0
- package/src/generated/generated.ts +25265 -0
- package/src/generic/DeleteOptionsInput.ts +13 -0
- package/src/generic/KeyInputOutputTypes.ts +35 -0
- package/src/generic/KeyValuePairInput.ts +14 -0
- package/src/generic/PushStatusResolver.ts +40 -0
- package/src/generic/ResolverBase.ts +767 -0
- package/src/generic/RunViewResolver.ts +579 -0
- package/src/index.ts +171 -0
- package/src/orm.ts +36 -0
- package/src/resolvers/AskSkipResolver.ts +1109 -0
- package/src/resolvers/ColorResolver.ts +61 -0
- package/src/resolvers/DatasetResolver.ts +115 -0
- package/src/resolvers/EntityCommunicationsResolver.ts +221 -0
- package/src/resolvers/EntityRecordNameResolver.ts +75 -0
- package/src/resolvers/EntityResolver.ts +35 -0
- package/src/resolvers/FileCategoryResolver.ts +69 -0
- package/src/resolvers/FileResolver.ts +152 -0
- package/src/resolvers/MergeRecordsResolver.ts +175 -0
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +91 -0
- package/src/resolvers/QueryResolver.ts +42 -0
- package/src/resolvers/ReportResolver.ts +144 -0
- package/src/resolvers/UserFavoriteResolver.ts +176 -0
- package/src/resolvers/UserResolver.ts +33 -0
- package/src/resolvers/UserViewResolver.ts +64 -0
- package/src/types.ts +40 -0
- package/src/util.ts +112 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Metadata, KeyValuePair, CompositeKey, UserInfo } from '@memberjunction/core';
|
|
2
|
+
import {
|
|
3
|
+
AppContext,
|
|
4
|
+
Arg,
|
|
5
|
+
CompositeKeyInputType,
|
|
6
|
+
CompositeKeyOutputType,
|
|
7
|
+
Ctx,
|
|
8
|
+
Field,
|
|
9
|
+
InputType,
|
|
10
|
+
Int,
|
|
11
|
+
Mutation,
|
|
12
|
+
ObjectType,
|
|
13
|
+
Query,
|
|
14
|
+
Resolver,
|
|
15
|
+
} from '@memberjunction/server';
|
|
16
|
+
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
17
|
+
import { UserFavoriteEntity } from '@memberjunction/core-entities';
|
|
18
|
+
|
|
19
|
+
import { UserFavorite_, UserFavoriteResolverBase } from '../generated/generated.js';
|
|
20
|
+
|
|
21
|
+
//****************************************************************************
|
|
22
|
+
// INPUT TYPE for User Favorite Queries
|
|
23
|
+
//****************************************************************************
|
|
24
|
+
@InputType()
|
|
25
|
+
export class UserFavoriteSearchParams {
|
|
26
|
+
@Field(() => String)
|
|
27
|
+
EntityID: string;
|
|
28
|
+
|
|
29
|
+
@Field(() => CompositeKeyInputType)
|
|
30
|
+
CompositeKey: CompositeKeyInputType;
|
|
31
|
+
|
|
32
|
+
@Field(() => String)
|
|
33
|
+
UserID: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@InputType()
|
|
37
|
+
export class UserFavoriteSetParams {
|
|
38
|
+
@Field(() => String)
|
|
39
|
+
EntityID: string;
|
|
40
|
+
|
|
41
|
+
@Field(() => CompositeKeyInputType)
|
|
42
|
+
CompositeKey: CompositeKeyInputType;
|
|
43
|
+
|
|
44
|
+
@Field(() => String)
|
|
45
|
+
UserID: string;
|
|
46
|
+
|
|
47
|
+
@Field(() => Boolean)
|
|
48
|
+
IsFavorite: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@ObjectType()
|
|
52
|
+
export class UserFavoriteResult {
|
|
53
|
+
@Field(() => Int)
|
|
54
|
+
EntityID: number;
|
|
55
|
+
|
|
56
|
+
@Field(() => CompositeKeyOutputType)
|
|
57
|
+
CompositeKey: CompositeKeyOutputType;
|
|
58
|
+
|
|
59
|
+
@Field(() => Int)
|
|
60
|
+
UserID: number;
|
|
61
|
+
|
|
62
|
+
@Field(() => Boolean)
|
|
63
|
+
IsFavorite: boolean;
|
|
64
|
+
|
|
65
|
+
@Field(() => Boolean)
|
|
66
|
+
Success: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@Resolver(UserFavorite_)
|
|
70
|
+
export class UserFavoriteResolver extends UserFavoriteResolverBase {
|
|
71
|
+
@Query(() => [UserFavorite_])
|
|
72
|
+
async UserFavoritesByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() { dataSource }: AppContext) {
|
|
73
|
+
return await this.findBy(dataSource, 'User Favorites', { UserID });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Query(() => [UserFavorite_])
|
|
77
|
+
async UserFavoriteSearchByParams(@Arg('params', () => Int) params: UserFavoriteSearchParams, @Ctx() { dataSource }: AppContext) {
|
|
78
|
+
return await this.findBy(dataSource, 'User Favorites', params);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Query(() => UserFavoriteResult)
|
|
82
|
+
async GetRecordFavoriteStatus(@Arg('params', () => UserFavoriteSearchParams) params: UserFavoriteSearchParams, @Ctx() {}: AppContext) {
|
|
83
|
+
const md = new Metadata();
|
|
84
|
+
const pk = new CompositeKey(params.CompositeKey.KeyValuePairs);
|
|
85
|
+
|
|
86
|
+
const e = md.Entities.find((e) => e.ID === params.EntityID);
|
|
87
|
+
if (e)
|
|
88
|
+
return {
|
|
89
|
+
EntityID: params.EntityID,
|
|
90
|
+
UserID: params.UserID,
|
|
91
|
+
CompositeKey: pk,
|
|
92
|
+
IsFavorite: await md.GetRecordFavoriteStatus(params.UserID, e.Name, pk),
|
|
93
|
+
Success: true,
|
|
94
|
+
};
|
|
95
|
+
else throw new Error(`Entity ID:${params.EntityID} not found`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@Mutation(() => UserFavoriteResult)
|
|
99
|
+
SetRecordFavoriteStatus(@Arg('params', () => UserFavoriteSetParams) params: UserFavoriteSetParams, @Ctx() { userPayload }: AppContext) {
|
|
100
|
+
const md = new Metadata();
|
|
101
|
+
const pk = new CompositeKey(params.CompositeKey.KeyValuePairs);
|
|
102
|
+
const e = md.Entities.find((e) => e.ID === params.EntityID);
|
|
103
|
+
const u = UserCache.Users.find((u) => u.ID === userPayload.userRecord.ID);
|
|
104
|
+
if (e) {
|
|
105
|
+
md.SetRecordFavoriteStatus(params.UserID, e.Name, pk, params.IsFavorite, u);
|
|
106
|
+
return {
|
|
107
|
+
Success: true,
|
|
108
|
+
EntityID: params.EntityID,
|
|
109
|
+
UserID: params.UserID,
|
|
110
|
+
CompositeKey: params.CompositeKey,
|
|
111
|
+
IsFavorite: params.IsFavorite,
|
|
112
|
+
};
|
|
113
|
+
} else throw new Error(`Entity ID:${params.EntityID} not found`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private GetTestData() {
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
firstName: 'John',
|
|
120
|
+
lastName: 'Doe',
|
|
121
|
+
title: 'Software Engineer II',
|
|
122
|
+
email: 'amith+john.doe@nagarajan.org',
|
|
123
|
+
age: 25,
|
|
124
|
+
address: {
|
|
125
|
+
street: '123 Main St',
|
|
126
|
+
city: 'Springfield',
|
|
127
|
+
state: 'IL',
|
|
128
|
+
zip: '62701',
|
|
129
|
+
},
|
|
130
|
+
recommendedArticles: [
|
|
131
|
+
{
|
|
132
|
+
title: 'How to Write Better Code',
|
|
133
|
+
url: 'https://example.com/article1',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
title: 'The Art of Debugging',
|
|
137
|
+
url: 'https://example.com/article2',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
title: 'Using Templates Effectively',
|
|
141
|
+
url: 'https://example.com/article3',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
firstName: 'Jane',
|
|
147
|
+
lastName: 'Smith',
|
|
148
|
+
title: 'Executive Vice President of Software Development',
|
|
149
|
+
email: 'amith+jane.smith@nagarajan.org',
|
|
150
|
+
age: 30,
|
|
151
|
+
address: {
|
|
152
|
+
street: '456 Elm St',
|
|
153
|
+
city: 'Chicago',
|
|
154
|
+
state: 'IL',
|
|
155
|
+
zip: '62702',
|
|
156
|
+
},
|
|
157
|
+
recommendedArticles: [
|
|
158
|
+
{
|
|
159
|
+
title: 'Exemplifying the Importance of Code Reviews',
|
|
160
|
+
url: 'https://example.com/article1',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
title: 'AI and Software Development: A New Frontier',
|
|
164
|
+
url: 'https://example.com/article2',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
title: 'Gardening Tips for Fun Loving Software Developers',
|
|
168
|
+
url: 'https://example.com/article3',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export default UserFavoriteResolver;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AppContext, Arg, Ctx, Int, Query, Resolver } from '@memberjunction/server';
|
|
2
|
+
import { User_, UserResolverBase } from '../generated/generated.js';
|
|
3
|
+
|
|
4
|
+
@Resolver(User_)
|
|
5
|
+
export class UserResolver extends UserResolverBase {
|
|
6
|
+
@Query(() => User_)
|
|
7
|
+
async CurrentUser(@Ctx() { dataSource, userPayload }: AppContext) {
|
|
8
|
+
const result = await this.UserByEmail(userPayload.email, { dataSource, userPayload });
|
|
9
|
+
console.log('CurrentUser', result);
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@Query(() => User_)
|
|
14
|
+
async UserByID(@Arg('ID', () => Int) ID: number, @Ctx() { dataSource }: AppContext) {
|
|
15
|
+
const retVal = super.safeFirstArrayElement(await this.findBy(dataSource, 'Users', { ID }));
|
|
16
|
+
return this.MapFieldNamesToCodeNames('Users', retVal);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@Query(() => User_)
|
|
20
|
+
async UserByEmployeeID(@Arg('EmployeeID', () => Int) EmployeeID: number, @Ctx() { dataSource }: AppContext) {
|
|
21
|
+
const retVal = super.safeFirstArrayElement(await this.findBy(dataSource, 'Users', { EmployeeID }));
|
|
22
|
+
return this.MapFieldNamesToCodeNames('Users', retVal);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Query(() => User_)
|
|
26
|
+
async UserByEmail(@Arg('Email', () => String) Email: string, @Ctx() { dataSource }: AppContext) {
|
|
27
|
+
// const searchEmail = userEmailMap[Email] ?? Email;
|
|
28
|
+
const searchEmail = Email;
|
|
29
|
+
const returnVal = super.safeFirstArrayElement(await this.findBy(dataSource, 'Users', { Email: searchEmail }));
|
|
30
|
+
return this.MapFieldNamesToCodeNames('Users', returnVal);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export default UserResolver;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { Metadata } from '@memberjunction/core';
|
|
3
|
+
import { AppContext, Arg, Ctx, Int, Query, Resolver, UserPayload } from '@memberjunction/server';
|
|
4
|
+
import { DataSource } from 'typeorm';
|
|
5
|
+
import { UserView_, UserViewResolverBase } from '../generated/generated.js';
|
|
6
|
+
import { UserResolver } from './UserResolver.js';
|
|
7
|
+
import { UserViewEntity, UserViewEntityExtended } from '@memberjunction/core-entities';
|
|
8
|
+
|
|
9
|
+
@Resolver(UserView_)
|
|
10
|
+
export class UserViewResolver extends UserViewResolverBase {
|
|
11
|
+
@Query(() => [UserView_])
|
|
12
|
+
async UserViewsByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() { dataSource }: AppContext) {
|
|
13
|
+
return await this.findBy(dataSource, 'User Views', { UserID });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Query(() => [UserView_])
|
|
17
|
+
async DefaultViewByUserAndEntity(
|
|
18
|
+
@Arg('UserID', () => Int) UserID: number,
|
|
19
|
+
@Arg('EntityID', () => Int) EntityID: number,
|
|
20
|
+
@Ctx() { dataSource }: AppContext
|
|
21
|
+
) {
|
|
22
|
+
return await this.findBy(dataSource, 'User Views', { UserID, EntityID, IsDefault: true });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Query(() => [UserView_])
|
|
26
|
+
async CurrentUserDefaultViewByEntityID(@Arg('EntityID', () => Int) EntityID: number, @Ctx() { dataSource, userPayload }: AppContext) {
|
|
27
|
+
return await this.findBy(dataSource, 'User Views', {
|
|
28
|
+
UserID: await this.getCurrentUserID(dataSource, userPayload),
|
|
29
|
+
EntityID,
|
|
30
|
+
IsDefault: true,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected async getCurrentUserID(dataSource: DataSource, userPayload: UserPayload): Promise<number> {
|
|
35
|
+
const userResolver = new UserResolver();
|
|
36
|
+
const user = await userResolver.UserByEmail(userPayload.email, { dataSource, userPayload });
|
|
37
|
+
return user.ID;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Query(() => [UserView_])
|
|
41
|
+
async CurrentUserUserViewsByEntityID(@Arg('EntityID', () => Int) EntityID: number, @Ctx() { dataSource, userPayload }: AppContext) {
|
|
42
|
+
return this.findBy(dataSource, 'User Views', { UserID: await this.getCurrentUserID(dataSource, userPayload), EntityID });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Query(() => [UserView_])
|
|
46
|
+
async UpdateWhereClause(@Arg('ID', () => String) ID: string, @Ctx() { userPayload }: AppContext) {
|
|
47
|
+
// in this query we want to update the uesrView record in the DB with a new where clause
|
|
48
|
+
// this should normally not be a factor but we have this exposed in the GraphQL API so that
|
|
49
|
+
// a dev can force the update if desired from the client. The normal path is just to update
|
|
50
|
+
// filter state which in turn will be used to update the where clause in the entity sub-class.
|
|
51
|
+
const md = new Metadata();
|
|
52
|
+
const u = this.GetUserFromPayload(userPayload);
|
|
53
|
+
const viewEntity = <UserViewEntityExtended>await md.GetEntityObject('User Views', u);
|
|
54
|
+
await viewEntity.Load(ID);
|
|
55
|
+
viewEntity.UpdateWhereClause();
|
|
56
|
+
if (await viewEntity.Save()) {
|
|
57
|
+
return viewEntity.GetAll();
|
|
58
|
+
} else {
|
|
59
|
+
throw new Error('Failed to update where clause');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default UserViewResolver;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { UserViewEntity } from '@memberjunction/core-entities';
|
|
2
|
+
import { GraphQLSchema } from 'graphql';
|
|
3
|
+
import { PubSubEngine } from 'type-graphql';
|
|
4
|
+
import { DataSource, QueryRunner } from 'typeorm';
|
|
5
|
+
|
|
6
|
+
export type UserPayload = {
|
|
7
|
+
email: string;
|
|
8
|
+
userRecord: any;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type AppContext = {
|
|
13
|
+
dataSource: DataSource;
|
|
14
|
+
userPayload: UserPayload;
|
|
15
|
+
queryRunner?: QueryRunner;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type DirectiveBuilder = {
|
|
19
|
+
typeDefs: string;
|
|
20
|
+
transformer: (schema: GraphQLSchema) => GraphQLSchema;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type RunViewGenericParams = {
|
|
24
|
+
viewInfo: UserViewEntity;
|
|
25
|
+
dataSource: DataSource;
|
|
26
|
+
extraFilter: string;
|
|
27
|
+
orderBy: string;
|
|
28
|
+
userSearchString: string;
|
|
29
|
+
excludeUserViewRunID?: string;
|
|
30
|
+
overrideExcludeFilter?: string;
|
|
31
|
+
saveViewResults?: boolean;
|
|
32
|
+
fields?: string[];
|
|
33
|
+
ignoreMaxRows?: boolean;
|
|
34
|
+
excludeDataFromAllPriorViewRuns?: boolean;
|
|
35
|
+
forceAuditLog?: boolean;
|
|
36
|
+
auditLogDescription?: string;
|
|
37
|
+
resultType?: string;
|
|
38
|
+
userPayload?: UserPayload;
|
|
39
|
+
pubSub: PubSubEngine
|
|
40
|
+
}
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { request as httpRequest } from 'http';
|
|
2
|
+
import { request as httpsRequest } from 'https';
|
|
3
|
+
import { gzip as gzipCallback, createGunzip } from 'zlib';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import { URL } from 'url';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
|
|
8
|
+
const gzip = promisify(gzipCallback);
|
|
9
|
+
|
|
10
|
+
type StreamCallback = (jsonObject: any) => void;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Utility function to handle HTTP/HTTPS requests with optional compression, custom headers, and streaming response callback for JSON objects.
|
|
14
|
+
* This function accumulates data chunks and parses complete JSON objects, assuming newline-delimited JSON in the stream.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} url - The URL to which the request is sent.
|
|
17
|
+
* @param {any} payload - The payload to be sent with the request.
|
|
18
|
+
* @param {boolean} useCompression - Flag to determine if payload compression should be used.
|
|
19
|
+
* @param {Record<string, string> | null} headers - Custom headers for the request. Can be null.
|
|
20
|
+
* @param {StreamCallback} [streamCallback] - Optional callback for handling streaming JSON objects.
|
|
21
|
+
* @returns {Promise<any[]>} - A promise that resolves to an array of all JSON objects received during the streaming process.
|
|
22
|
+
*/
|
|
23
|
+
export async function sendPostRequest(url: string, payload: any, useCompression: boolean, headers: Record<string, string> | null, streamCallback?: StreamCallback): Promise<any[]> {
|
|
24
|
+
return new Promise(async (resolve, reject) => {
|
|
25
|
+
try {
|
|
26
|
+
const { protocol, hostname, port, pathname } = new URL(url);
|
|
27
|
+
let data;
|
|
28
|
+
if (useCompression) {
|
|
29
|
+
try {
|
|
30
|
+
data = await gzip(Buffer.from(JSON.stringify(payload)));
|
|
31
|
+
headers = headers || {}; // Ensure headers is an object
|
|
32
|
+
headers['Content-Encoding'] = 'gzip';
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const err = z.object({ message: z.string() }).safeParse(error);
|
|
35
|
+
console.error(`Error in sendPostRequest while compressing data: ${err.success ? err.data.message : error}`);
|
|
36
|
+
return reject(error);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
data = Buffer.from(JSON.stringify(payload));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const options = {
|
|
43
|
+
hostname,
|
|
44
|
+
port: port || (protocol === 'https:' ? 443 : 80),
|
|
45
|
+
path: pathname,
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
...headers
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const request = protocol === 'https:' ? httpsRequest : httpRequest;
|
|
54
|
+
const jsonObjects: any[] = [];
|
|
55
|
+
let buffer = '';
|
|
56
|
+
|
|
57
|
+
const req = request(options, (res) => {
|
|
58
|
+
const gunzip = createGunzip();
|
|
59
|
+
const stream = res.headers['content-encoding'] === 'gzip' ? res.pipe(gunzip) : res;
|
|
60
|
+
|
|
61
|
+
stream.on('data', (chunk) => {
|
|
62
|
+
buffer += chunk;
|
|
63
|
+
let boundary;
|
|
64
|
+
while ((boundary = buffer.indexOf('\n')) !== -1) {
|
|
65
|
+
const jsonString = buffer.substring(0, boundary);
|
|
66
|
+
buffer = buffer.substring(boundary + 1);
|
|
67
|
+
try {
|
|
68
|
+
const jsonObject = JSON.parse(jsonString);
|
|
69
|
+
jsonObjects.push(jsonObject);
|
|
70
|
+
streamCallback?.(jsonObject);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
const err = z.object({ message: z.string() }).safeParse(e);
|
|
73
|
+
// Handle JSON parse error for cases of malformed JSON objects
|
|
74
|
+
console.warn(`Error in postRequest().stream(data) while parsing JSON object: ${err.success ? err.data.message : e}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
stream.on('end', () => {
|
|
80
|
+
// Attempt to parse any remaining data in buffer in case it's a complete JSON object
|
|
81
|
+
if (buffer.trim()) {
|
|
82
|
+
try {
|
|
83
|
+
const jsonObject = JSON.parse(buffer.trim());
|
|
84
|
+
jsonObjects.push(jsonObject);
|
|
85
|
+
streamCallback?.(jsonObject);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
const err = z.object({ message: z.string() }).safeParse(e);
|
|
88
|
+
// Handle JSON parse error for the last chunk
|
|
89
|
+
console.warn(`Error in postRequest().stream(end) while parsing JSON object: ${err.success ? err.data.message : e}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
resolve(jsonObjects);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
req.on('error', (e) => {
|
|
97
|
+
const err = z.object({ message: z.string() }).safeParse(e);
|
|
98
|
+
console.error(`Error in sendPostRequest().req.on(error): ${err.success ? err.data.message : e}`);
|
|
99
|
+
reject(e);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
req.write(data);
|
|
103
|
+
req.end();
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
const err = z.object({ message: z.string() }).safeParse(e);
|
|
107
|
+
console.error(`Error in sendPostRequest: ${err.success ? err.data.message : e}`)
|
|
108
|
+
reject(e);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|