Skip to content

Commit 397ed4f

Browse files
committed
revert to former pattern base + specific query runner
1 parent a1d207f commit 397ed4f

File tree

41 files changed

+875
-891
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+875
-891
lines changed

packages/twenty-server/src/engine/api/common/common-query-runners/common-base-query-runner.service.ts

Lines changed: 142 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
import { Inject, Injectable } from '@nestjs/common';
22

3-
import { type ObjectRecord } from 'twenty-shared/types';
43
import { isDefined } from 'twenty-shared/utils';
4+
import { Omit } from 'zod/v4/core/util.cjs';
55

66
import { WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
7+
import { QueryResultFieldValue } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-field-value';
78

89
import { CommonSelectedFieldsHandler } from 'src/engine/api/common/common-args-handlers/common-query-selected-fields/common-selected-fields.handler';
10+
import {
11+
CommonQueryRunnerException,
12+
CommonQueryRunnerExceptionCode,
13+
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
914
import { CommonResultGettersService } from 'src/engine/api/common/common-result-getters/common-result-getters.service';
10-
import { CommonQueryNames } from 'src/engine/api/common/types/common-query-args.type';
15+
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
16+
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
17+
import {
18+
CommonExtendedInput,
19+
CommonInput,
20+
CommonQueryArgs,
21+
CommonQueryNames,
22+
} from 'src/engine/api/common/types/common-query-args.type';
23+
import { CommonQueryResult } from 'src/engine/api/common/types/common-query-result.type';
24+
import { isWorkspaceAuthContext } from 'src/engine/api/common/utils/is-workspace-auth-context.util';
1125
import { OBJECTS_WITH_SETTINGS_PERMISSIONS_REQUIREMENTS } from 'src/engine/api/graphql/graphql-query-runner/constants/objects-with-settings-permissions-requirements';
26+
import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser';
1227
import { ProcessNestedRelationsHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-nested-relations.helper';
1328
import { QueryResultGettersFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/query-result-getters.factory';
1429
import { QueryRunnerArgsFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-runner-args.factory';
30+
import { WorkspacePreQueryHookPayload } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
1531
import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service';
1632
import { ApiKeyRoleService } from 'src/engine/core-modules/api-key/api-key-role.service';
1733
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
@@ -29,7 +45,10 @@ import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/wo
2945
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
3046

3147
@Injectable()
32-
export abstract class CommonBaseQueryRunnerService {
48+
export abstract class CommonBaseQueryRunnerService<
49+
Args extends CommonQueryArgs,
50+
Output extends CommonQueryResult,
51+
> {
3352
@Inject()
3453
protected readonly workspaceQueryHookService: WorkspaceQueryHookService;
3554
@Inject()
@@ -53,60 +72,117 @@ export abstract class CommonBaseQueryRunnerService {
5372
@Inject()
5473
protected readonly commonResultGettersService: CommonResultGettersService;
5574

56-
public async prepareQueryRunnerContext({
57-
authContext,
58-
objectMetadataItemWithFieldMaps,
59-
}: {
60-
authContext: WorkspaceAuthContext;
61-
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps;
62-
}) {
75+
public async execute(
76+
args: CommonInput<Args>,
77+
queryRunnerContext: CommonBaseQueryRunnerContext,
78+
operationName: CommonQueryNames,
79+
): Promise<Output> {
80+
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
81+
queryRunnerContext;
82+
83+
if (!isWorkspaceAuthContext(authContext)) {
84+
throw new CommonQueryRunnerException(
85+
'Invalid auth context',
86+
CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT,
87+
);
88+
}
89+
90+
await this.validate(args, queryRunnerContext);
91+
6392
if (objectMetadataItemWithFieldMaps.isSystem === true) {
6493
await this.validateSettingsPermissionsOnObjectOrThrow(
6594
authContext,
66-
objectMetadataItemWithFieldMaps,
95+
queryRunnerContext,
6796
);
6897
}
6998

70-
const workspace = authContext.workspace;
71-
72-
const workspaceDataSource =
73-
await this.twentyORMGlobalManager.getDataSourceForWorkspace({
74-
workspaceId: workspace.id,
75-
});
99+
const commonQueryParser = new GraphqlQueryParser(
100+
objectMetadataItemWithFieldMaps,
101+
objectMetadataMaps,
102+
);
76103

77-
const { roleId } = await this.getRoleIdAndObjectsPermissions(
78-
authContext,
79-
workspace.id,
104+
const processedArgs = await this.processArgs(
105+
args,
106+
queryRunnerContext,
107+
operationName,
108+
commonQueryParser,
80109
);
81110

82-
const rolePermissionConfig = { unionOf: [roleId] };
111+
const extendedQueryRunnerContext =
112+
await this.prepareExtendedQueryRunnerContext(
113+
authContext,
114+
queryRunnerContext,
115+
);
83116

84-
const repository = workspaceDataSource.getRepository(
85-
objectMetadataItemWithFieldMaps.nameSingular,
86-
rolePermissionConfig,
117+
const results = await this.run(processedArgs, {
118+
...extendedQueryRunnerContext,
119+
commonQueryParser,
120+
});
121+
122+
return this.enrichResultsWithGettersAndHooks({
123+
results,
124+
operationName,
87125
authContext,
126+
objectMetadataItemWithFieldMaps,
127+
objectMetadataMaps,
128+
});
129+
}
130+
131+
protected abstract run(
132+
args: CommonExtendedInput<Args>,
133+
queryRunnerContext: CommonExtendedQueryRunnerContext,
134+
): Promise<Output>;
135+
136+
protected abstract validate(
137+
args: CommonInput<Args>,
138+
queryRunnerContext: CommonBaseQueryRunnerContext,
139+
): Promise<void>;
140+
141+
protected abstract computeArgs(
142+
args: CommonInput<Args>,
143+
queryRunnerContext: CommonBaseQueryRunnerContext,
144+
): Promise<CommonInput<Args>>;
145+
146+
private async processArgs(
147+
args: CommonInput<Args>,
148+
queryRunnerContext: CommonBaseQueryRunnerContext,
149+
operationName: CommonQueryNames,
150+
commonQueryParser: GraphqlQueryParser,
151+
): Promise<CommonExtendedInput<Args>> {
152+
const selectedFieldsResult = commonQueryParser.parseSelectedFields(
153+
args.selectedFields,
88154
);
89155

156+
const { authContext, objectMetadataItemWithFieldMaps } = queryRunnerContext;
157+
const hookedArgs =
158+
(await this.workspaceQueryHookService.executePreQueryHooks(
159+
authContext,
160+
objectMetadataItemWithFieldMaps.nameSingular,
161+
operationName,
162+
args as WorkspacePreQueryHookPayload<CommonQueryNames>,
163+
)) as CommonInput<Args>;
164+
165+
const computedArgs = await this.computeArgs(hookedArgs, queryRunnerContext);
166+
90167
return {
91-
workspaceDataSource,
92-
repository,
93-
rolePermissionConfig,
168+
...computedArgs,
169+
selectedFieldsResult,
94170
};
95171
}
96172

97-
public async enrichResultsWithGettersAndHooks({
173+
private async enrichResultsWithGettersAndHooks({
98174
results,
99175
operationName,
100176
authContext,
101177
objectMetadataItemWithFieldMaps,
102178
objectMetadataMaps,
103179
}: {
104-
results: ObjectRecord[];
180+
results: Output;
105181
operationName: CommonQueryNames;
106182
authContext: WorkspaceAuthContext;
107183
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps;
108184
objectMetadataMaps: ObjectMetadataMaps;
109-
}): Promise<ObjectRecord[]> {
185+
}): Promise<Output> {
110186
const resultWithGetters =
111187
await this.commonResultGettersService.processQueryResult(
112188
results,
@@ -119,16 +195,18 @@ export abstract class CommonBaseQueryRunnerService {
119195
authContext,
120196
objectMetadataItemWithFieldMaps.nameSingular,
121197
operationName,
122-
resultWithGetters,
198+
resultWithGetters as QueryResultFieldValue,
123199
);
124200

125-
return resultWithGetters;
201+
return resultWithGetters as Output;
126202
}
127203

128204
private async validateSettingsPermissionsOnObjectOrThrow(
129205
authContext: WorkspaceAuthContext,
130-
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
206+
queryRunnerContext: CommonBaseQueryRunnerContext,
131207
) {
208+
const { objectMetadataItemWithFieldMaps } = queryRunnerContext;
209+
132210
const workspace = authContext.workspace;
133211

134212
if (
@@ -206,4 +284,35 @@ export abstract class CommonBaseQueryRunnerService {
206284

207285
return { roleId, objectsPermissions: objectMetadataPermissions[roleId] };
208286
}
287+
288+
private async prepareExtendedQueryRunnerContext(
289+
authContext: WorkspaceAuthContext,
290+
queryRunnerContext: CommonBaseQueryRunnerContext,
291+
): Promise<Omit<CommonExtendedQueryRunnerContext, 'commonQueryParser'>> {
292+
const workspaceDataSource =
293+
await this.twentyORMGlobalManager.getDataSourceForWorkspace({
294+
workspaceId: authContext.workspace.id,
295+
});
296+
297+
const { roleId } = await this.getRoleIdAndObjectsPermissions(
298+
authContext,
299+
authContext.workspace.id,
300+
);
301+
302+
const rolePermissionConfig = { unionOf: [roleId] };
303+
304+
const repository = workspaceDataSource.getRepository(
305+
queryRunnerContext.objectMetadataItemWithFieldMaps.nameSingular,
306+
rolePermissionConfig,
307+
authContext,
308+
);
309+
310+
return {
311+
...queryRunnerContext,
312+
authContext,
313+
workspaceDataSource,
314+
rolePermissionConfig,
315+
repository,
316+
};
317+
}
209318
}

0 commit comments

Comments
 (0)