Create query runner context from request context instead of schema builder internal context (#16858)
## Context
This PR refactors how authentication context is handled in the GraphQL
resolver layer. Previously, the auth context was baked into the schema
builder context at schema creation time. Now, the auth context is
extracted from the request at query execution time, enabling better
schema caching.
## Implementation
- Removed user-specific data from schema cache key: The schema cache key
no longer includes userId and apiKeyId, allowing the same schema to be
shared across all users in a workspace
- Cache key simplified from
${workspaceId}-${userId}-${apiKeyId}-${url}-${cacheVersion} to
${workspaceId}-${url}-${cacheVersion}
- Removed authContext from WorkspaceSchemaBuilderContext: The schema
builder context is now purely about object/field metadata, not about who
is accessing it
- Created createQueryRunnerContext utility: A new helper that combines
the schema builder context with the auth context from the actual request
- Updated all resolver factories: All 15 resolver factories now use
createQueryRunnerContext to build the full context needed by query
runners at execution time
## Benefits
- Improved cache efficiency: GraphQL schemas are now cached per
workspace rather than per user, significantly reducing memory usage and
schema regeneration
- Cleaner separation of concerns: Schema building (metadata-driven) is
now separate from query execution (auth-driven)
- Fresh auth context: Auth context is always retrieved from the current
request, ensuring it reflects the latest state
- Reduced complexity: Simplified the schema creation path by removing
unnecessary auth checks
## Next steps
- Introduce a hash in redis and expose it in the req object so the yoga
patch can access the hash and use it during its own cache key
computation. This way we will be able to invalidate the local cache in
yoga graphql schema generation without restarting pods.
This commit is contained in:
+12
-6
@@ -14,6 +14,7 @@ import { CommonCreateManyQueryRunnerService } from 'src/engine/api/common/common
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class CreateManyResolverFactory
|
||||
@@ -30,26 +31,31 @@ export class CreateManyResolverFactory
|
||||
): Resolver<CreateManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const records = await this.commonCreateManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return records.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
}),
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonCreateOneQueryRunnerService } from 'src/engine/api/common/common-
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class CreateOneResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class CreateOneResolverFactory
|
||||
): Resolver<CreateOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const record = await this.commonCreateOneQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonDeleteManyQueryRunnerService } from 'src/engine/api/common/common
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteManyResolverFactory
|
||||
@@ -30,26 +31,31 @@ export class DeleteManyResolverFactory
|
||||
): Resolver<DeleteManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const records = await this.commonDeleteManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return records.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
}),
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonDeleteOneQueryRunnerService } from 'src/engine/api/common/common-
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteOneResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class DeleteOneResolverFactory
|
||||
): Resolver<DeleteOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const record = await this.commonDeleteOneQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonDestroyManyQueryRunnerService } from 'src/engine/api/common/commo
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class DestroyManyResolverFactory
|
||||
@@ -30,26 +31,31 @@ export class DestroyManyResolverFactory
|
||||
): Resolver<DestroyManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const records = await this.commonDestroyManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return records.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
}),
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonDestroyOneQueryRunnerService } from 'src/engine/api/common/common
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class DestroyOneResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class DestroyOneResolverFactory
|
||||
): Resolver<DestroyOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const record = await this.commonDestroyOneQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonFindDuplicatesQueryRunnerService } from 'src/engine/api/common/co
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class FindDuplicatesResolverFactory
|
||||
@@ -30,27 +31,32 @@ export class FindDuplicatesResolverFactory
|
||||
): Resolver<FindDuplicatesResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const paginatedDuplicates =
|
||||
await this.commonFindDuplicatesQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return paginatedDuplicates.map((duplicate) =>
|
||||
typeORMObjectRecordsParser.createConnection({
|
||||
objectRecords: duplicate.records,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: duplicate.records.length,
|
||||
totalCount: duplicate.totalCount,
|
||||
order: [{ id: OrderByDirection.AscNullsFirst }],
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonFindManyQueryRunnerService } from 'src/engine/api/common/common-q
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class FindManyResolverFactory
|
||||
@@ -30,9 +31,14 @@ export class FindManyResolverFactory
|
||||
): Resolver<FindManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const {
|
||||
records,
|
||||
@@ -42,21 +48,21 @@ export class FindManyResolverFactory
|
||||
selectedFieldsResult,
|
||||
} = await this.commonFindManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.createConnection({
|
||||
objectRecords: records,
|
||||
objectRecordsAggregatedValues: aggregatedValues,
|
||||
selectedAggregatedFields: selectedFieldsResult.aggregate,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: args.first ?? args.last ?? QUERY_MAX_RECORDS,
|
||||
totalCount,
|
||||
order: args.orderBy,
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonFindOneQueryRunnerService } from 'src/engine/api/common/common-qu
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class FindOneResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class FindOneResolverFactory
|
||||
): Resolver<FindOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
try {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
const record = await this.commonFindOneQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonGroupByQueryRunnerService } from 'src/engine/api/common/common-qu
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class GroupByResolverFactory
|
||||
@@ -30,9 +31,14 @@ export class GroupByResolverFactory
|
||||
): Resolver<GroupByResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
const shouldIncludeRecords =
|
||||
isDefined(selectedFields.edges?.node) &&
|
||||
Object.keys(selectedFields.edges?.node).length > 0;
|
||||
@@ -40,20 +46,20 @@ export class GroupByResolverFactory
|
||||
try {
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
const results = await this.commonGroupByQueryRunnerService.execute(
|
||||
{ ...args, selectedFields, includeRecords: shouldIncludeRecords },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const formattedResults = results.map((group) => {
|
||||
const formattedRecords = typeORMObjectRecordsParser.createConnection({
|
||||
objectRecords: group.records ?? [],
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
objectRecordsAggregatedValues: {},
|
||||
selectedAggregatedFields: {},
|
||||
take: group.records?.length || 0,
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonMergeManyQueryRunnerService } from 'src/engine/api/common/common-
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class MergeManyResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class MergeManyResolverFactory
|
||||
): Resolver<MergeManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const record = await this.commonMergeManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonRestoreManyQueryRunnerService } from 'src/engine/api/common/commo
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class RestoreManyResolverFactory
|
||||
@@ -30,26 +31,31 @@ export class RestoreManyResolverFactory
|
||||
): Resolver<RestoreManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const records = await this.commonRestoreManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return records.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
}),
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonRestoreOneQueryRunnerService } from 'src/engine/api/common/common
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class RestoreOneResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class RestoreOneResolverFactory
|
||||
): Resolver<RestoreOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const record = await this.commonRestoreOneQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+12
-6
@@ -14,6 +14,7 @@ import { CommonUpdateManyQueryRunnerService } from 'src/engine/api/common/common
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateManyResolverFactory
|
||||
@@ -30,26 +31,31 @@ export class UpdateManyResolverFactory
|
||||
): Resolver<UpdateManyResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const records = await this.commonUpdateManyQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return records.map((record: ObjectRecord) =>
|
||||
typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
}),
|
||||
|
||||
+12
-6
@@ -13,6 +13,7 @@ import { CommonUpdateOneQueryRunnerService } from 'src/engine/api/common/common-
|
||||
import { ObjectRecordsToGraphqlConnectionHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/object-records-to-graphql-connection.helper';
|
||||
import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util';
|
||||
import { RESOLVER_METHOD_NAMES } from 'src/engine/api/graphql/workspace-resolver-builder/constants/resolver-method-names';
|
||||
import { createQueryRunnerContext } from 'src/engine/api/graphql/workspace-resolver-builder/utils/create-query-runner-context.util';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateOneResolverFactory
|
||||
@@ -29,25 +30,30 @@ export class UpdateOneResolverFactory
|
||||
): Resolver<UpdateOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return async (_source, args, _context, info) => {
|
||||
return async (_source, args, requestContext, info) => {
|
||||
const selectedFields = graphqlFields(info);
|
||||
|
||||
const resolverContext = createQueryRunnerContext({
|
||||
workspaceSchemaBuilderContext: internalContext,
|
||||
request: requestContext.req,
|
||||
});
|
||||
|
||||
try {
|
||||
const record = await this.commonUpdateOneQueryRunnerService.execute(
|
||||
{ ...args, selectedFields },
|
||||
internalContext,
|
||||
resolverContext,
|
||||
);
|
||||
|
||||
const typeORMObjectRecordsParser =
|
||||
new ObjectRecordsToGraphqlConnectionHelper(
|
||||
internalContext.flatObjectMetadataMaps,
|
||||
internalContext.flatFieldMetadataMaps,
|
||||
internalContext.objectIdByNameSingular,
|
||||
resolverContext.flatObjectMetadataMaps,
|
||||
resolverContext.flatFieldMetadataMaps,
|
||||
resolverContext.objectIdByNameSingular,
|
||||
);
|
||||
|
||||
return typeORMObjectRecordsParser.processRecord({
|
||||
objectRecord: record,
|
||||
objectName: internalContext.flatObjectMetadata.nameSingular,
|
||||
objectName: resolverContext.flatObjectMetadata.nameSingular,
|
||||
take: 1,
|
||||
totalCount: 1,
|
||||
});
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { type WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface';
|
||||
|
||||
import { type CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
|
||||
export const createQueryRunnerContext = ({
|
||||
workspaceSchemaBuilderContext,
|
||||
request,
|
||||
}: {
|
||||
workspaceSchemaBuilderContext: WorkspaceSchemaBuilderContext;
|
||||
request: AuthContext;
|
||||
}): CommonBaseQueryRunnerContext => {
|
||||
const {
|
||||
user,
|
||||
workspace,
|
||||
apiKey,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
userWorkspace,
|
||||
authProvider,
|
||||
impersonationContext,
|
||||
} = request;
|
||||
|
||||
return {
|
||||
...workspaceSchemaBuilderContext,
|
||||
authContext: {
|
||||
user,
|
||||
workspace,
|
||||
apiKey,
|
||||
workspaceMemberId,
|
||||
userWorkspaceId,
|
||||
userWorkspace,
|
||||
authProvider,
|
||||
impersonationContext,
|
||||
},
|
||||
};
|
||||
};
|
||||
-17
@@ -12,11 +12,6 @@ import { RestoreManyResolverFactory } from 'src/engine/api/graphql/workspace-res
|
||||
import { RestoreOneResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/restore-one-resolver.factory';
|
||||
import { UpdateManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/update-many-resolver.factory';
|
||||
import { WorkspaceResolverBuilderService } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.service';
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -59,7 +54,6 @@ export class WorkspaceResolverFactory {
|
||||
) {}
|
||||
|
||||
async create(
|
||||
authContext: AuthContext,
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>,
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>,
|
||||
objectIdByNameSingular: Record<string, string>,
|
||||
@@ -90,15 +84,6 @@ export class WorkspaceResolverFactory {
|
||||
Mutation: {},
|
||||
};
|
||||
|
||||
const workspaceId = authContext.workspace?.id;
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new AuthException(
|
||||
'Unauthenticated',
|
||||
AuthExceptionCode.UNAUTHENTICATED,
|
||||
);
|
||||
}
|
||||
|
||||
for (const flatObjectMetadata of Object.values(
|
||||
flatObjectMetadataMaps.byId,
|
||||
).filter(isDefined)) {
|
||||
@@ -125,7 +110,6 @@ export class WorkspaceResolverFactory {
|
||||
) {
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
resolvers.Query[resolverName] = resolverFactory.create({
|
||||
authContext,
|
||||
flatObjectMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
@@ -157,7 +141,6 @@ export class WorkspaceResolverFactory {
|
||||
) {
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
resolvers.Mutation[resolverName] = resolverFactory.create({
|
||||
authContext,
|
||||
flatObjectMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
|
||||
Reference in New Issue
Block a user