From 72e81bbd24a2acad04bf731b715fbb80a0a58aaf Mon Sep 17 00:00:00 2001 From: Juan Mrad Date: Thu, 30 Apr 2026 08:45:59 -0500 Subject: [PATCH] [kysely] Migrate User schema and auth out of sequelize (#349) * [kysely] Migrate User schema and auth out of sequelize * fix test * address code review * fix codegen --- codegen.yaml | 2 +- server/api.ts | 49 +- server/graphql/datasources/RuleApi.ts | 21 +- server/graphql/datasources/UserApi.ts | 253 +++- .../datasources/buildGraphqlRuleParent.ts | 12 +- .../datasources/userKyselyPersistence.test.ts | 438 ++++++ .../datasources/userKyselyPersistence.ts | 346 +++++ .../datasources/userValidation.test.ts | 179 +++ server/graphql/datasources/userValidation.ts | 169 +++ server/graphql/generated.ts | 1274 +++++++++-------- server/graphql/resolvers.ts | 6 +- server/models/rules/ruleTypes.ts | 4 +- server/services/coreAppTables.ts | 24 + .../services/userManagementService/dbTypes.ts | 18 +- .../services/userManagementService/index.ts | 2 +- .../services/userManagementService/utils.ts | 13 + 16 files changed, 2085 insertions(+), 725 deletions(-) create mode 100644 server/graphql/datasources/userKyselyPersistence.test.ts create mode 100644 server/graphql/datasources/userKyselyPersistence.ts create mode 100644 server/graphql/datasources/userValidation.test.ts create mode 100644 server/graphql/datasources/userValidation.ts diff --git a/codegen.yaml b/codegen.yaml index 5e48f4d..d13ec88 100644 --- a/codegen.yaml +++ b/codegen.yaml @@ -104,7 +104,7 @@ generates: # parent, and its sub-resolvers only read `org.id`. A bit unusual, as # `MatchingBanks` could be a standalone type — may expand later. MatchingBanks: ../graphql/datasources/orgKyselyPersistence.js#GraphQLOrgParent - User: ../models/UserModel.js#User + User: ../graphql/datasources/userKyselyPersistence.js#GraphQLUserParent LocationBank: ./datasources/LocationBankApi.js#LocationBankWithoutFullPlacesAPIResponse # TODO(Kysely migration): these parents will flip to # `../models/rules/ruleTypes.js#Rule` once the Action/Policy resolvers diff --git a/server/api.ts b/server/api.ts index bd77c6e..cded2fb 100644 --- a/server/api.ts +++ b/server/api.ts @@ -29,7 +29,12 @@ import { makeLoginSsoRequiredError, makeLoginUserDoesNotExistError, } from './graphql/datasources/UserApi.js'; +import { + kyselyUserFindByEmail, + kyselyUserFindById, +} from './graphql/datasources/userKyselyPersistence.js'; import resolvers, { type Context } from './graphql/resolvers.js'; +import { passwordMatchesHash } from './services/userManagementService/index.js'; import typeDefs from './graphql/schema.js'; import { authSchemaWrapper } from './graphql/utils/authorization.js'; import { type Dependencies } from './iocContainer/index.js'; @@ -91,7 +96,7 @@ const sessionStore = connectPgSimple(session); export default async function makeApiServer(deps: Dependencies) { const app = express(); - const { User } = deps.Sequelize; + const { KyselyPg } = deps; app.use(cors()); @@ -213,9 +218,10 @@ export default async function makeApiServer(deps: Dependencies) { }, async (_req, profile, done) => { try { - const user = await User.findOne({ - where: { email: String(profile?.email) }, - }); + const user = await kyselyUserFindByEmail( + KyselyPg, + String(profile?.email), + ); // we should have already checked for this, but couldn't hurt to check // again if (user == null) { @@ -235,9 +241,10 @@ export default async function makeApiServer(deps: Dependencies) { }, async (_req, profile, done) => { try { - const user = await User.findOne({ - where: { email: String(profile?.email) }, - }); + const user = await kyselyUserFindByEmail( + KyselyPg, + String(profile?.email), + ); // we should have already checked for this, but couldn't hurt to check // again if (user == null) { @@ -278,7 +285,7 @@ export default async function makeApiServer(deps: Dependencies) { passport.use( new GraphQLLocalStrategy(async (email, password, done) => { try { - const user = await User.findOne({ where: { email: String(email) } }); + const user = await kyselyUserFindByEmail(KyselyPg, String(email)); if (user == null) { return done( makeLoginUserDoesNotExistError({ shouldErrorSpan: true }), @@ -313,12 +320,11 @@ export default async function makeApiServer(deps: Dependencies) { ); } - // if loginMethod is password, password should be set + // `loginMethods` includes 'password', so the DB CHECK constraint + // guarantees `user.password` is non-null here. if ( - await User.passwordMatchesHash( - String(password), - user.password satisfies string | null as string, - ) + user.password != null && + (await passwordMatchesHash(String(password), user.password)) ) { done(null, user); } else { @@ -340,9 +346,19 @@ export default async function makeApiServer(deps: Dependencies) { }); passport.deserializeUser(async (id, done) => { - return User.findByPk(String(id), { rejectOnEmpty: true }).then((user) => { - done(null, user); - }, done); + try { + const user = await kyselyUserFindById(KyselyPg, String(id)); + if (user == null) { + return done( + makeNotFoundError(`Session user ${String(id)} not found`, { + shouldErrorSpan: true, + }), + ); + } + return done(null, user); + } catch (e) { + return done(e); + } }); /** @@ -551,7 +567,6 @@ function makeGqlServices(deps: Dependencies) { 'PartialItemsService', 'ReportingService', 'RuleEvaluator', - 'Sequelize', 'SignalsService', 'SigningKeyPairService', 'Tracer', diff --git a/server/graphql/datasources/RuleApi.ts b/server/graphql/datasources/RuleApi.ts index 2eb4491..88e3da2 100644 --- a/server/graphql/datasources/RuleApi.ts +++ b/server/graphql/datasources/RuleApi.ts @@ -8,7 +8,6 @@ import { uid } from 'uid'; import { inject, type Dependencies } from '../../iocContainer/index.js'; import { type Backtest } from '../../models/rules/BacktestModel.js'; -import { type User } from '../../models/UserModel.js'; import { type ActionCountsInput } from '../../services/actionStatisticsService/index.js'; import { type AggregationClause } from '../../services/aggregationsService/index.js'; import { type ConditionSetWithResultAsLogged } from '../../services/analyticsLoggers/index.js'; @@ -68,6 +67,10 @@ import { kyselyListBacktestsForRule, kyselyUpdateRule, } from './ruleKyselyPersistence.js'; +import { + type GraphQLUserParent, + kyselyUserFindByIdAndOrg, +} from './userKyselyPersistence.js'; import { locationAreaInputToLocationArea } from './LocationBankApi.js'; import { unauthenticatedError } from '../utils/errors.js'; import { isUniqueViolationError } from '../../utils/kysely.js'; @@ -302,7 +305,6 @@ class RuleAPI { public readonly ruleInsights: Dependencies['RuleActionInsights'], private readonly actionStats: Dependencies['ActionStatisticsService'], private readonly kyselyPg: Dependencies['KyselyPg'], - private readonly models: Dependencies['Sequelize'], private readonly moderationConfigService: Dependencies['ModerationConfigService'], private readonly tracer: Dependencies['Tracer'], private readonly signalsService: Dependencies['SignalsService'], @@ -315,10 +317,8 @@ class RuleAPI { ); this.graphQlRuleParentDeps = { moderationConfigService: this.moderationConfigService, - // TODO(Kysely migration): replace with a ModerationConfigService / - // user-service-backed lookup once users are migrated off Sequelize. findUserByIdAndOrg: async (opts) => - this.models.User.findOne({ where: opts.where }), + kyselyUserFindByIdAndOrg(this.kyselyPg, opts), }; } @@ -667,7 +667,10 @@ class RuleAPI { * `ruleKyselyPersistence.ts`, and the deleted private helpers (`getContentItemTypeIdsForRule`, * `runSampledRuleExecutions`, `queryWarehouseSubmissionsForRule`). */ - async createBacktest(_input: GQLCreateBacktestInput, _user: User): Promise { + async createBacktest( + _input: GQLCreateBacktestInput, + _user: GraphQLUserParent, + ): Promise { throw new Error( 'createBacktest is temporarily disabled (TODO BACKTEST_RETROACTION: no UI / env to validate).', ); @@ -777,7 +780,10 @@ class RuleAPI { * TODO(BACKTEST_RETROACTION): Same as `createBacktest` — re-enable when UI and env * support validation. */ - async runRetroaction(_input: GQLRunRetroactionInput, _user: User): Promise<{ _: boolean }> { + async runRetroaction( + _input: GQLRunRetroactionInput, + _user: GraphQLUserParent, + ): Promise<{ _: boolean }> { throw new Error( 'runRetroaction is temporarily disabled (TODO BACKTEST_RETROACTION: no UI / env to validate).', ); @@ -856,7 +862,6 @@ export default inject( 'RuleActionInsights', 'ActionStatisticsService', 'KyselyPg', - 'Sequelize', 'ModerationConfigService', 'Tracer', 'SignalsService', diff --git a/server/graphql/datasources/UserApi.ts b/server/graphql/datasources/UserApi.ts index cd7ddfc..10585ba 100644 --- a/server/graphql/datasources/UserApi.ts +++ b/server/graphql/datasources/UserApi.ts @@ -4,49 +4,74 @@ import { uid } from 'uid'; import { inject, type Dependencies } from '../../iocContainer/index.js'; import { type Rule } from '../../models/rules/RuleModel.js'; -import { type User as TUser } from '../../models/UserModel.js'; -import { hashPassword } from '../../services/userManagementService/index.js'; +import { type LoginMethod } from '../../services/coreAppTables.js'; +import { + hashPassword, + passwordMatchesHash, +} from '../../services/userManagementService/index.js'; import { CoopError, ErrorType, makeBadRequestError, makeInternalServerError, + makeNotFoundError, makeUnauthorizedError, type ErrorInstanceData, } from '../../utils/errors.js'; import { safePick } from '../../utils/misc.js'; import { WEEK_MS } from '../../utils/time.js'; +import { buildGraphqlRuleParent } from './buildGraphqlRuleParent.js'; +import { + type GraphQLUserParent, + kyselyUserAddFavoriteRule, + kyselyUserFindByEmail, + kyselyUserFindByIdAndOrg, + kyselyUserFindById, + kyselyUserFindByIds, + kyselyUserInsert, + kyselyUserListFavoriteRuleIds, + kyselyUserRemoveFavoriteRule, + kyselyUserUpdate, +} from './userKyselyPersistence.js'; +import { + type UserValidationFailure, + validateUserCreateInput, + validateUserUpdatePatch, +} from './userValidation.js'; /** * GraphQL Object for a User */ class UserAPI { constructor( - private readonly sequelize: Dependencies['Sequelize'], + private readonly kyselyPg: Dependencies['KyselyPg'], private readonly tracer: Dependencies['Tracer'], private readonly userManagementService: Dependencies['UserManagementService'], - ) { - } - - async getGraphQLUserFromId(opts: { id: string; orgId: string }) { - const { id, orgId } = opts; - - return this.sequelize.User.findOne({ - where: { - id, - orgId, - }, - rejectOnEmpty: true, - }); + private readonly moderationConfigService: Dependencies['ModerationConfigService'], + ) {} + + async getGraphQLUserFromId(opts: { + id: string; + orgId: string; + }): Promise { + const user = await kyselyUserFindByIdAndOrg(this.kyselyPg, opts); + if (user === undefined) { + // Matches the `rejectOnEmpty: true` semantics of the Sequelize call + // this method replaced (callers rely on a throw when the row is + // missing, e.g. `getFavoriteRules`). + throw makeNotFoundError( + `User ${opts.id} not found in org ${opts.orgId}`, + { shouldErrorSpan: true }, + ); + } + return user; } - async getGraphQLUsersFromIds(ids: string[]) { - return this.sequelize.User.findAll({ - where: { id: ids }, - }); + async getGraphQLUsersFromIds(ids: string[]): Promise { + return kyselyUserFindByIds(this.kyselyPg, ids); } - async login(params: any, context: PassportContext) { + async login(params: any, context: PassportContext) { const credentials = safePick(params.input, ['email', 'password']); // NB: this will throw for bad credentials; will be handled in the resolver. @@ -72,7 +97,7 @@ class UserAPI { } } - async signUp(params: any, _: any) { + async signUp(params: any, _: any): Promise { const { role } = params.input; const { email, @@ -90,9 +115,7 @@ class UserAPI { { shouldErrorSpan: true }, ); - const existingUser = await this.sequelize.User.findOne({ - where: { email }, - }); + const existingUser = await kyselyUserFindByEmail(this.kyselyPg, email); if (existingUser != null) { throw makeSignUpUserExistsError({ shouldErrorSpan: true }); } @@ -119,16 +142,32 @@ class UserAPI { }); } - const user = await this.sequelize.User.create({ + const loginMethodNormalized = String(loginMethod).toLowerCase() as LoginMethod; + const createInput = { + email, + firstName, + lastName, + role: token.role, + loginMethods: [loginMethodNormalized] as const, + password: passwordToSave, + }; + + const validation = validateUserCreateInput(createInput); + if (!validation.ok) { + throw userValidationFailureToBadRequestError(validation.failure); + } + + const user = await kyselyUserInsert({ + db: this.kyselyPg, id: uid(), + orgId, email, password: passwordToSave, firstName, lastName, role: token.role, approvedByAdmin: true, - orgId, - loginMethods: [loginMethod.toLowerCase()], + loginMethods: [loginMethodNormalized], }); // Delete the invite token after successful user creation @@ -138,26 +177,35 @@ class UserAPI { } async updateAccountInfo( - user: TUser, + user: GraphQLUserParent, params: { firstName?: string | null; lastName?: string | null }, - ) { - const { firstName, lastName } = params; - if (firstName != null) { - user.firstName = firstName; + ): Promise { + const patch = { + firstName: params.firstName ?? undefined, + lastName: params.lastName ?? undefined, + }; + + const validation = validateUserUpdatePatch(patch); + if (!validation.ok) { + throw userValidationFailureToBadRequestError(validation.failure); } - if (lastName != null) { - user.lastName = lastName; + + const updated = await kyselyUserUpdate(this.kyselyPg, user.id, patch); + if (updated == null) { + // Row went missing between load and update (e.g. concurrent delete). + throw makeNotFoundError(`User ${user.id} not found`, { + shouldErrorSpan: true, + }); } - await user.save(); + return updated; } async changePassword( - user: TUser, + user: GraphQLUserParent, params: { currentPassword: string; newPassword: string }, ) { const { currentPassword, newPassword } = params; - // Check if user has password login method if (!user.loginMethods.includes('password')) { throw makeChangePasswordNotAllowedError({ detail: 'Password login is not enabled for this user.', @@ -165,7 +213,6 @@ class UserAPI { }); } - // Verify current password if (user.password == null) { throw makeChangePasswordIncorrectPasswordError({ detail: 'Current password is not set.', @@ -173,11 +220,10 @@ class UserAPI { }); } - const isCurrentPasswordValid = - await this.sequelize.User.passwordMatchesHash( - currentPassword, - user.password, - ); + const isCurrentPasswordValid = await passwordMatchesHash( + currentPassword, + user.password, + ); if (!isCurrentPasswordValid) { throw makeChangePasswordIncorrectPasswordError({ @@ -185,10 +231,16 @@ class UserAPI { }); } - // Hash and save new password const hashedNewPassword = await hashPassword(newPassword); - user.password = hashedNewPassword; - await user.save(); + const updated = await kyselyUserUpdate(this.kyselyPg, user.id, { + password: hashedNewPassword, + }); + if (updated == null) { + // Row went missing between load and update (e.g. concurrent delete). + throw makeNotFoundError(`User ${user.id} not found`, { + shouldErrorSpan: true, + }); + } return { __typename: 'ChangePasswordSuccessResponse' as const, @@ -199,8 +251,17 @@ class UserAPI { async deleteUser(opts: { id: string; orgId: string }) { const { id, orgId } = opts; try { - const user = await this.sequelize.User.findOne({ where: { id, orgId } }); - await user?.destroy(); + const user = await kyselyUserFindByIdAndOrg(this.kyselyPg, { + id, + orgId, + }); + if (user != null) { + await this.kyselyPg + .deleteFrom('public.users') + .where('id', '=', id) + .where('org_id', '=', orgId) + .execute(); + } } catch (exception) { const activeSpan = this.tracer.getActiveSpan(); if (activeSpan?.isRecording()) { @@ -212,11 +273,14 @@ class UserAPI { } async approveUser(id: string, invokerOrgId: string) { - const user = await this.sequelize.User.findByPk(id, { - rejectOnEmpty: true, - }); + const user = await kyselyUserFindById(this.kyselyPg, id); + if (user == null) { + throw makeNotFoundError(`User ${id} not found`, { + shouldErrorSpan: true, + }); + } - // Security check: ensure admin can only approve users in their own org + // Security check: ensure admin can only approve users in their own org. if (user.orgId !== invokerOrgId) { throw makeUnauthorizedError( 'You can only approve users in your organization', @@ -224,17 +288,27 @@ class UserAPI { ); } - user.approvedByAdmin = true; - await user.save(); + const updated = await kyselyUserUpdate(this.kyselyPg, id, { + approvedByAdmin: true, + }); + if (updated == null) { + // Row went missing between load and update (e.g. concurrent delete). + throw makeNotFoundError(`User ${id} not found`, { + shouldErrorSpan: true, + }); + } return true; } async rejectUser(id: string, invokerOrgId: string) { - const user = await this.sequelize.User.findByPk(id, { - rejectOnEmpty: true, - }); + const user = await kyselyUserFindById(this.kyselyPg, id); + if (user == null) { + throw makeNotFoundError(`User ${id} not found`, { + shouldErrorSpan: true, + }); + } - // Security check: ensure admin can only reject users in their own org + // Security check: ensure admin can only reject users in their own org. if (user.orgId !== invokerOrgId) { throw makeUnauthorizedError( 'You can only reject users in your organization', @@ -242,30 +316,71 @@ class UserAPI { ); } - user.rejectedByAdmin = true; - await user.save(); + const updated = await kyselyUserUpdate(this.kyselyPg, id, { + rejectedByAdmin: true, + }); + if (updated == null) { + // Row went missing between load and update (e.g. concurrent delete). + throw makeNotFoundError(`User ${id} not found`, { + shouldErrorSpan: true, + }); + } return true; } async getFavoriteRules(id: string, orgId: string): Promise> { - const user = await this.getGraphQLUserFromId({ id, orgId }); - const rules = await user.getFavoriteRules(); - return rules; + // Make sure the requested user lives in the invoker's org (the caller + // always passes the invoker's orgId), then scope rule lookups to that + // org so cross-org data can't leak even if stale favorites exist. + await this.getGraphQLUserFromId({ id, orgId }); + const ruleIds = await kyselyUserListFavoriteRuleIds(this.kyselyPg, id); + const plains = ( + await Promise.all( + ruleIds.map(async (ruleId) => + this.moderationConfigService.getRuleByIdAndOrg(ruleId, orgId), + ), + ) + ).filter((plain): plain is NonNullable => plain != null); + return plains.map((plain) => + buildGraphqlRuleParent(plain, { + moderationConfigService: this.moderationConfigService, + findUserByIdAndOrg: async (opts) => + kyselyUserFindByIdAndOrg(this.kyselyPg, opts), + }), + ); } async addFavoriteRule(userId: string, ruleId: string, orgId: string) { - const user = await this.getGraphQLUserFromId({ id: userId, orgId }); - await user.addFavoriteRules([ruleId]); + // Scope by org so a caller can't add a favorite targeting a rule in a + // different org (the Sequelize association was unscoped). + await this.getGraphQLUserFromId({ id: userId, orgId }); + const rule = await this.moderationConfigService.getRuleByIdAndOrg( + ruleId, + orgId, + ); + if (rule == null) { + throw makeNotFoundError(`Rule ${ruleId} not found in org ${orgId}`, { + shouldErrorSpan: true, + }); + } + await kyselyUserAddFavoriteRule(this.kyselyPg, userId, ruleId); } async removeFavoriteRule(userId: string, ruleId: string, orgId: string) { - const user = await this.getGraphQLUserFromId({ id: userId, orgId }); - await user.removeFavoriteRules([ruleId]); + await this.getGraphQLUserFromId({ id: userId, orgId }); + await kyselyUserRemoveFavoriteRule(this.kyselyPg, userId, ruleId); } } +function userValidationFailureToBadRequestError(failure: UserValidationFailure) { + return makeBadRequestError(failure.message, { + pointer: `/input/${failure.field}`, + shouldErrorSpan: false, + }); +} + export default inject( - ['Sequelize', 'Tracer', 'UserManagementService'], + ['KyselyPg', 'Tracer', 'UserManagementService', 'ModerationConfigService'], UserAPI, ); export type { UserAPI }; diff --git a/server/graphql/datasources/buildGraphqlRuleParent.ts b/server/graphql/datasources/buildGraphqlRuleParent.ts index 786ffb1..2245ec9 100644 --- a/server/graphql/datasources/buildGraphqlRuleParent.ts +++ b/server/graphql/datasources/buildGraphqlRuleParent.ts @@ -1,19 +1,20 @@ import { type Rule as SequelizeRule } from '../../models/rules/RuleModel.js'; -import { type User } from '../../models/UserModel.js'; import { type PlainRuleWithLatestVersion, type Rule as RuleGraphqlParent, } from '../../models/rules/ruleTypes.js'; import { type ModerationConfigService } from '../../services/moderationConfigService/index.js'; +import { type GraphQLUserParent } from './userKyselyPersistence.js'; type FindUserByIdAndOrg = (opts: { - where: { id: string; orgId: string }; -}) => Promise; + id: string; + orgId: string; +}) => Promise; /** * Builds a GraphQL Rule parent (plain row fields + the three association * getters our resolvers actually use) backed by ModerationConfigService - * reads and a Sequelize-backed User lookup for the creator. + * reads and a Kysely-backed User lookup for the creator. * * The returned object only implements the {@link RuleGraphqlParent} contract * (`getCreator` / `getActions` / `getPolicies`). We cast to `SequelizeRule` @@ -34,7 +35,8 @@ export function buildGraphqlRuleParent( ...plain, async getCreator() { const user = await deps.findUserByIdAndOrg({ - where: { id: plain.creatorId, orgId: plain.orgId }, + id: plain.creatorId, + orgId: plain.orgId, }); if (user == null) { throw new Error(`User not found for rule creator ${plain.creatorId}`); diff --git a/server/graphql/datasources/userKyselyPersistence.test.ts b/server/graphql/datasources/userKyselyPersistence.test.ts new file mode 100644 index 0000000..272207c --- /dev/null +++ b/server/graphql/datasources/userKyselyPersistence.test.ts @@ -0,0 +1,438 @@ +import { faker } from '@faker-js/faker'; +import { uid } from 'uid'; + +import { UserRole } from '../../models/types/permissioning.js'; +import createOrg from '../../test/fixtureHelpers/createOrg.js'; +import createRule from '../../test/fixtureHelpers/createRule.js'; +import { makeMockedServer } from '../../test/setupMockedServer.js'; +import { makeTestWithFixture } from '../../test/utils.js'; +import { + kyselyUserAddFavoriteRule, + kyselyUserDeleteById, + kyselyUserFindByEmail, + kyselyUserFindById, + kyselyUserFindByIdAndOrg, + kyselyUserFindByIds, + kyselyUserInsert, + kyselyUserListByOrg, + kyselyUserListFavoriteRuleIds, + kyselyUserRemoveFavoriteRule, + kyselyUserUpdate, +} from './userKyselyPersistence.js'; + +/** + * Builds a valid `kyselyUserInsert` input with SAML-only login (no password), + * so we don't need bcrypt in the unit-ish happy paths. + */ +function samlUserInput(orgId: string) { + return { + id: uid(), + orgId, + email: faker.internet.email(), + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + role: UserRole.ADMIN, + loginMethods: ['saml'] as const, + password: null, + }; +} + +describe('userKyselyPersistence', () => { + const testWithFixture = makeTestWithFixture(async () => { + const { deps, shutdown } = await makeMockedServer(); + const { org, cleanup: orgCleanup } = await createOrg( + { + KyselyPg: deps.KyselyPg, + ModerationConfigService: deps.ModerationConfigService, + ApiKeyService: deps.ApiKeyService, + }, + uid(), + ); + return { + deps, + org, + async cleanup() { + await orgCleanup(); + await shutdown(); + }, + }; + }); + + describe('kyselyUserInsert', () => { + testWithFixture( + 'inserts a SAML user and round-trips fields + getPermissions()', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + const inserted = await kyselyUserInsert({ + db: deps.KyselyPg, + ...input, + }); + try { + expect(inserted).toMatchObject({ + id: input.id, + orgId: org.id, + email: input.email, + firstName: input.firstName, + lastName: input.lastName, + role: UserRole.ADMIN, + loginMethods: ['saml'], + password: null, + approvedByAdmin: false, + rejectedByAdmin: false, + }); + expect(Array.isArray(inserted.getPermissions())).toBe(true); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + testWithFixture( + 'inserts a password-login user with a password set', + async ({ deps, org }) => { + const id = uid(); + const row = await kyselyUserInsert({ + db: deps.KyselyPg, + id, + orgId: org.id, + email: faker.internet.email(), + firstName: 'Jane', + lastName: 'Doe', + role: UserRole.ADMIN, + loginMethods: ['password'], + password: 'hashed-password-placeholder', + }); + try { + expect(row.loginMethods).toEqual(['password']); + expect(row.password).toBe('hashed-password-placeholder'); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, id); + } + }, + ); + + testWithFixture( + 'throws an invariant error for malformed input (defense-in-depth)', + async ({ deps, org }) => { + await expect( + kyselyUserInsert({ + db: deps.KyselyPg, + id: uid(), + orgId: org.id, + email: 'not-an-email', + firstName: 'A', + lastName: 'B', + role: UserRole.ADMIN, + loginMethods: ['saml'], + password: null, + }), + ).rejects.toThrow(/kyselyUserInsert invariant violated: email/); + }, + ); + + testWithFixture( + "throws an invariant error when password/loginMethods disagree (CHECK constraint shape)", + async ({ deps, org }) => { + await expect( + kyselyUserInsert({ + db: deps.KyselyPg, + id: uid(), + orgId: org.id, + email: faker.internet.email(), + firstName: 'A', + lastName: 'B', + role: UserRole.ADMIN, + loginMethods: ['saml'], + password: 'should-not-be-set', + }), + ).rejects.toThrow(/kyselyUserInsert invariant violated: password/); + }, + ); + }); + + describe('kyselyUserFindBy*', () => { + testWithFixture( + 'findById / findByEmail / findByIdAndOrg return the row when it exists', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + const byId = await kyselyUserFindById(deps.KyselyPg, input.id); + const byEmail = await kyselyUserFindByEmail( + deps.KyselyPg, + input.email, + ); + const byIdAndOrg = await kyselyUserFindByIdAndOrg(deps.KyselyPg, { + id: input.id, + orgId: org.id, + }); + + expect(byId).toMatchObject({ id: input.id, email: input.email }); + expect(byEmail).toMatchObject({ id: input.id }); + expect(byIdAndOrg).toMatchObject({ id: input.id, orgId: org.id }); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + testWithFixture( + 'find helpers return undefined (not null) when missing', + async ({ deps, org }) => { + const byId = await kyselyUserFindById( + deps.KyselyPg, + `missing-${uid()}`, + ); + const byEmail = await kyselyUserFindByEmail( + deps.KyselyPg, + `missing-${uid()}@example.com`, + ); + const byIdAndOrg = await kyselyUserFindByIdAndOrg(deps.KyselyPg, { + id: `missing-${uid()}`, + orgId: org.id, + }); + + expect(byId).toBeUndefined(); + expect(byEmail).toBeUndefined(); + expect(byIdAndOrg).toBeUndefined(); + }, + ); + + testWithFixture( + 'findByIdAndOrg returns undefined when the user exists in a different org', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + const result = await kyselyUserFindByIdAndOrg(deps.KyselyPg, { + id: input.id, + orgId: `different-org-${uid()}`, + }); + expect(result).toBeUndefined(); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + testWithFixture( + 'findByIds returns [] for an empty input and handles mixed hits', + async ({ deps, org }) => { + expect(await kyselyUserFindByIds(deps.KyselyPg, [])).toEqual([]); + + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + const rows = await kyselyUserFindByIds(deps.KyselyPg, [ + input.id, + `missing-${uid()}`, + ]); + expect(rows).toHaveLength(1); + expect(rows[0].id).toBe(input.id); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + testWithFixture( + 'listByOrg scopes results to the provided org', + async ({ deps, org }) => { + const a = samlUserInput(org.id); + const b = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...a }); + await kyselyUserInsert({ db: deps.KyselyPg, ...b }); + try { + const rows = await kyselyUserListByOrg(deps.KyselyPg, org.id); + const ids = rows.map((r) => r.id); + expect(ids).toEqual(expect.arrayContaining([a.id, b.id])); + expect(rows.every((r) => r.orgId === org.id)).toBe(true); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, a.id); + await kyselyUserDeleteById(deps.KyselyPg, b.id); + } + }, + ); + }); + + describe('kyselyUserUpdate', () => { + testWithFixture( + 'throws an invariant error for a malformed patch', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + await expect( + kyselyUserUpdate(deps.KyselyPg, input.id, { + email: 'not-an-email', + }), + ).rejects.toThrow(/kyselyUserUpdate invariant violated: email/); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + testWithFixture( + 'returns undefined when the user does not exist', + async ({ deps }) => { + const result = await kyselyUserUpdate( + deps.KyselyPg, + `missing-${uid()}`, + { firstName: 'Nobody' }, + ); + expect(result).toBeUndefined(); + }, + ); + + testWithFixture( + 'null firstName / lastName / email / role are skipped (password untouched)', + async ({ deps, org }) => { + const input = { + ...samlUserInput(org.id), + loginMethods: ['password'] as const, + password: 'placeholder', + }; + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + const skipped = await kyselyUserUpdate(deps.KyselyPg, input.id, { + firstName: null, + lastName: null, + email: null, + role: null, + }); + expect(skipped).toBeDefined(); + expect(skipped!.firstName).toBe(input.firstName); + expect(skipped!.lastName).toBe(input.lastName); + expect(skipped!.email).toBe(input.email); + expect(skipped!.role).toBe(input.role); + expect(skipped!.password).toBe('placeholder'); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + // NB: `kyselyUserUpdate` doesn't expose `loginMethods`, so we can't + // *cleanly* clear a password on a password-login user through this helper + // (the DB CHECK constraint — and our app-layer `validateUserCreateInput` + // mirror of it — requires `password IS NOT NULL ⇔ 'password' ∈ login_methods`). + // A SAML user already has `password: null`, so the `password: null` path + // is a shape-valid no-op we can verify end-to-end here. + testWithFixture( + 'password: null is a valid patch and leaves the column null on a SAML user', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + const updated = await kyselyUserUpdate(deps.KyselyPg, input.id, { + password: null, + }); + expect(updated!.password).toBeNull(); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + // And conversely: trying to clear a password on a password-login user + // without transitioning `loginMethods` must surface the DB CHECK + // constraint. This protects against regressions if we ever loosen + // `validateUserUpdatePatch`. + testWithFixture( + "clearing password on a password-login user violates password_null_when_not_present", + async ({ deps, org }) => { + const input = { + ...samlUserInput(org.id), + loginMethods: ['password'] as const, + password: 'placeholder', + }; + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + await expect( + kyselyUserUpdate(deps.KyselyPg, input.id, { password: null }), + ).rejects.toThrow(/password_null_when_not_present/); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + + testWithFixture( + 'updates provided fields and bumps updated_at', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + try { + const beforeRow = await deps.KyselyPg + .selectFrom('public.users') + .select(['updated_at']) + .where('id', '=', input.id) + .executeTakeFirstOrThrow(); + + await new Promise((resolve) => setTimeout(resolve, 5)); + + const updated = await kyselyUserUpdate(deps.KyselyPg, input.id, { + firstName: 'Updated', + approvedByAdmin: true, + }); + expect(updated!.firstName).toBe('Updated'); + expect(updated!.approvedByAdmin).toBe(true); + + const afterRow = await deps.KyselyPg + .selectFrom('public.users') + .select(['updated_at']) + .where('id', '=', input.id) + .executeTakeFirstOrThrow(); + expect(afterRow.updated_at.getTime()).toBeGreaterThan( + beforeRow.updated_at.getTime(), + ); + } finally { + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + }); + + describe('favorite rules helpers', () => { + testWithFixture( + 'add / list / remove round-trip (and add is idempotent)', + async ({ deps, org }) => { + const input = samlUserInput(org.id); + await kyselyUserInsert({ db: deps.KyselyPg, ...input }); + // `users_and_favorite_rules.rule_id` has a FK to `public.rules`, so + // we need a real rule row. Reuse the existing Sequelize fixture until + // rule fixtures are themselves Kysely-backed. + const rule = await createRule(deps.Sequelize, org.id, { + creatorId: input.id, + }); + try { + expect( + await kyselyUserListFavoriteRuleIds(deps.KyselyPg, input.id), + ).toEqual([]); + + await kyselyUserAddFavoriteRule(deps.KyselyPg, input.id, rule.id); + // Second add must be a no-op (matches Sequelize `addFavoriteRules`). + await kyselyUserAddFavoriteRule(deps.KyselyPg, input.id, rule.id); + + expect( + await kyselyUserListFavoriteRuleIds(deps.KyselyPg, input.id), + ).toEqual([rule.id]); + + await kyselyUserRemoveFavoriteRule(deps.KyselyPg, input.id, rule.id); + expect( + await kyselyUserListFavoriteRuleIds(deps.KyselyPg, input.id), + ).toEqual([]); + } finally { + await kyselyUserRemoveFavoriteRule( + deps.KyselyPg, + input.id, + rule.id, + ).catch(() => undefined); + await rule.destroy().catch(() => undefined); + await kyselyUserDeleteById(deps.KyselyPg, input.id); + } + }, + ); + }); +}); diff --git a/server/graphql/datasources/userKyselyPersistence.ts b/server/graphql/datasources/userKyselyPersistence.ts new file mode 100644 index 0000000..6b8680f --- /dev/null +++ b/server/graphql/datasources/userKyselyPersistence.ts @@ -0,0 +1,346 @@ +import { type Kysely, sql } from 'kysely'; + +import { + getPermissionsForRole, + type UserPermission, + type UserRole, +} from '../../models/types/permissioning.js'; +import { + type CoreAppTablesPg, + type LoginMethod, +} from '../../services/coreAppTables.js'; +import { + validateUserCreateInput, + validateUserUpdatePatch, +} from './userValidation.js'; + +/** + * GraphQL `User` parent shape. Mirrors the columns on `public.users` plus a + * `getPermissions()` helper that resolvers call (e.g. in permission checks + * and in `UserResolvers.permissions`). Intentionally mirrors the public + * surface of the now-removed Sequelize `User` instance for a drop-in swap. + * + * `password` is included because the Passport local strategy needs it for + * `passwordMatchesHash`; resolvers must not leak it to clients. + */ +export type GraphQLUserParent = { + id: string; + email: string; + password: string | null; + firstName: string; + lastName: string; + orgId: string; + role: UserRole; + approvedByAdmin: boolean; + rejectedByAdmin: boolean; + loginMethods: LoginMethod[]; + createdAt: Date; + updatedAt: Date; + getPermissions(): UserPermission[]; +}; + +type UsersDb = Kysely; + +type UserRow = { + id: string; + email: string; + password: string | null; + first_name: string; + last_name: string; + role: UserRole; + approved_by_admin: boolean; + rejected_by_admin: boolean; + login_methods: LoginMethod[]; + created_at: Date; + updated_at: Date; + org_id: string; +}; + +// `public.users.login_methods` is a `login_method_enum[]`. Node-postgres ships +// parsers for built-in array types (`text[]`, `int[]`, etc.) but not for +// user-defined enum arrays, so without an explicit cast we get the raw +// `"{password,saml}"` string back and GraphQL fails with +// "Expected Iterable, but did not find one for field User.loginMethods". +// Casting to `text[]` leans on the stock array parser and keeps the column +// type aligned with our `LoginMethod` union (validated before writes). +const loginMethodsAsTextArray = sql`login_methods::text[]`.as( + 'login_methods', +); + +const USER_COLUMNS = [ + 'id', + 'email', + 'password', + 'first_name', + 'last_name', + 'role', + 'approved_by_admin', + 'rejected_by_admin', + 'created_at', + 'updated_at', + 'org_id', +] as const; + +function rowToGraphQLUserParent(row: UserRow): GraphQLUserParent { + return { + id: row.id, + email: row.email, + password: row.password, + firstName: row.first_name, + lastName: row.last_name, + orgId: row.org_id, + role: row.role, + approvedByAdmin: row.approved_by_admin, + rejectedByAdmin: row.rejected_by_admin, + loginMethods: row.login_methods, + createdAt: row.created_at, + updatedAt: row.updated_at, + getPermissions() { + return getPermissionsForRole(row.role); + }, + }; +} + +export async function kyselyUserFindById( + db: UsersDb, + id: string, +): Promise { + const row = await db + .selectFrom('public.users') + .select(USER_COLUMNS) + .select(loginMethodsAsTextArray) + .where('id', '=', id) + .executeTakeFirst(); + return row === undefined ? undefined : rowToGraphQLUserParent(row); +} + +export async function kyselyUserFindByIdAndOrg( + db: UsersDb, + opts: { id: string; orgId: string }, +): Promise { + const row = await db + .selectFrom('public.users') + .select(USER_COLUMNS) + .select(loginMethodsAsTextArray) + .where('id', '=', opts.id) + .where('org_id', '=', opts.orgId) + .executeTakeFirst(); + return row === undefined ? undefined : rowToGraphQLUserParent(row); +} + +export async function kyselyUserFindByEmail( + db: UsersDb, + email: string, +): Promise { + const row = await db + .selectFrom('public.users') + .select(USER_COLUMNS) + .select(loginMethodsAsTextArray) + .where('email', '=', email) + .executeTakeFirst(); + return row === undefined ? undefined : rowToGraphQLUserParent(row); +} + +export async function kyselyUserFindByIds( + db: UsersDb, + ids: readonly string[], +): Promise { + if (ids.length === 0) { + return []; + } + const rows = await db + .selectFrom('public.users') + .select(USER_COLUMNS) + .select(loginMethodsAsTextArray) + .where('id', 'in', ids) + .execute(); + return rows.map(rowToGraphQLUserParent); +} + +export async function kyselyUserListByOrg( + db: UsersDb, + orgId: string, +): Promise { + const rows = await db + .selectFrom('public.users') + .select(USER_COLUMNS) + .select(loginMethodsAsTextArray) + .where('org_id', '=', orgId) + .execute(); + return rows.map(rowToGraphQLUserParent); +} + +export async function kyselyUserInsert(opts: { + db: UsersDb; + id: string; + orgId: string; + email: string; + firstName: string; + lastName: string; + role: UserRole; + password: string | null; + loginMethods: readonly LoginMethod[]; + approvedByAdmin?: boolean; + rejectedByAdmin?: boolean; +}): Promise { + // Defense-in-depth so non-GraphQL callers (fixtures, scripts) can't insert + // invalid rows; user-facing validation lives in `UserAPI`. + const validation = validateUserCreateInput({ + email: opts.email, + firstName: opts.firstName, + lastName: opts.lastName, + role: opts.role, + loginMethods: opts.loginMethods, + password: opts.password, + }); + if (!validation.ok) { + throw new Error( + `kyselyUserInsert invariant violated: ${validation.failure.field}: ${validation.failure.message}`, + ); + } + + const now = new Date(); + const row = await opts.db + .insertInto('public.users') + .values({ + id: opts.id, + org_id: opts.orgId, + email: opts.email, + password: opts.password, + first_name: opts.firstName, + last_name: opts.lastName, + role: opts.role, + approved_by_admin: opts.approvedByAdmin ?? false, + rejected_by_admin: opts.rejectedByAdmin ?? false, + login_methods: [...opts.loginMethods], + created_at: now, + updated_at: now, + }) + .returning(USER_COLUMNS) + .returning(loginMethodsAsTextArray) + .executeTakeFirstOrThrow(); + return rowToGraphQLUserParent(row); +} + +export async function kyselyUserUpdate( + db: UsersDb, + userId: string, + patch: { + email?: string | null; + firstName?: string | null; + lastName?: string | null; + role?: UserRole | null; + password?: string | null; + approvedByAdmin?: boolean | null; + rejectedByAdmin?: boolean | null; + }, +): Promise { + const validation = validateUserUpdatePatch(patch); + if (!validation.ok) { + throw new Error( + `kyselyUserUpdate invariant violated: ${validation.failure.field}: ${validation.failure.message}`, + ); + } + + // `password` is the only field where `null` is a meaningful set (clears + // the column); other nullable fields treat `null` as "skip". + const update: { + email?: string; + first_name?: string; + last_name?: string; + role?: UserRole; + password?: string | null; + approved_by_admin?: boolean; + rejected_by_admin?: boolean; + updated_at: Date; + } = { updated_at: new Date() }; + + if (patch.email != null) { + update.email = patch.email; + } + if (patch.firstName != null) { + update.first_name = patch.firstName; + } + if (patch.lastName != null) { + update.last_name = patch.lastName; + } + if (patch.role != null) { + update.role = patch.role; + } + if (patch.password !== undefined) { + update.password = patch.password; + } + if (patch.approvedByAdmin != null) { + update.approved_by_admin = patch.approvedByAdmin; + } + if (patch.rejectedByAdmin != null) { + update.rejected_by_admin = patch.rejectedByAdmin; + } + + const row = await db + .updateTable('public.users') + .set(update) + .where('id', '=', userId) + .returning(USER_COLUMNS) + .returning(loginMethodsAsTextArray) + .executeTakeFirst(); + + return row === undefined ? undefined : rowToGraphQLUserParent(row); +} + +export async function kyselyUserDeleteById( + db: UsersDb, + userId: string, +): Promise { + await db.deleteFrom('public.users').where('id', '=', userId).execute(); +} + +/** + * Favorite rules join-table helpers. The Sequelize association used the + * auto-generated `users_and_favorite_rules` join table; preserving that + * exact schema means existing rows keep working during/after the cutover. + */ + +export async function kyselyUserListFavoriteRuleIds( + db: UsersDb, + userId: string, +): Promise { + const rows = await db + .selectFrom('public.users_and_favorite_rules') + .select('rule_id') + .where('user_id', '=', userId) + .execute(); + return rows.map((r) => r.rule_id); +} + +export async function kyselyUserAddFavoriteRule( + db: UsersDb, + userId: string, + ruleId: string, +): Promise { + // `onConflict().doNothing()` matches Sequelize's `addFavoriteRules` semantics + // when a favorite already exists (the composite PK on (user_id, rule_id) is + // what de-duplicates). + const now = new Date(); + await db + .insertInto('public.users_and_favorite_rules') + .values({ + user_id: userId, + rule_id: ruleId, + updated_at: now, + }) + .onConflict((oc) => oc.columns(['user_id', 'rule_id']).doNothing()) + .execute(); +} + +export async function kyselyUserRemoveFavoriteRule( + db: UsersDb, + userId: string, + ruleId: string, +): Promise { + await db + .deleteFrom('public.users_and_favorite_rules') + .where('user_id', '=', userId) + .where('rule_id', '=', ruleId) + .execute(); +} diff --git a/server/graphql/datasources/userValidation.test.ts b/server/graphql/datasources/userValidation.test.ts new file mode 100644 index 0000000..d91fd1f --- /dev/null +++ b/server/graphql/datasources/userValidation.test.ts @@ -0,0 +1,179 @@ +import { + validateUserCreateInput, + validateUserUpdatePatch, +} from './userValidation.js'; + +describe('userValidation', () => { + describe('validateUserCreateInput', () => { + const validInput = { + email: 'test_user@example.com', + firstName: 'Test', + lastName: 'User', + role: 'ADMIN', + loginMethods: ['saml'] as const, + password: null, + }; + + test('accepts a fully valid input (SAML, no password)', () => { + expect(validateUserCreateInput(validInput)).toEqual({ ok: true }); + }); + + test('accepts a valid password-login input', () => { + expect( + validateUserCreateInput({ + ...validInput, + loginMethods: ['password'], + password: 'hashed-password-placeholder', + }), + ).toEqual({ ok: true }); + }); + + test.each([ + ['empty', ''], + ['missing @', 'not-an-email'], + ['missing domain', 'foo@'], + ['contains space', 'foo @bar.com'], + ])('rejects email that is %s', (_label, email) => { + const result = validateUserCreateInput({ ...validInput, email }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('email'); + } + }); + + test.each([ + ['empty firstName', { firstName: '' }, 'firstName'], + ['whitespace firstName', { firstName: ' ' }, 'firstName'], + ['empty lastName', { lastName: '' }, 'lastName'], + ['whitespace lastName', { lastName: ' ' }, 'lastName'], + ] as const)('rejects %s', (_label, patch, expectedField) => { + const result = validateUserCreateInput({ ...validInput, ...patch }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe(expectedField); + } + }); + + test('rejects an unknown role', () => { + const result = validateUserCreateInput({ + ...validInput, + role: 'NOT_A_REAL_ROLE', + }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('role'); + } + }); + + test('rejects empty loginMethods', () => { + const result = validateUserCreateInput({ + ...validInput, + loginMethods: [], + }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('loginMethods'); + } + }); + + test('rejects unknown loginMethods entry', () => { + const result = validateUserCreateInput({ + ...validInput, + loginMethods: ['saml', 'oauth' as never], + }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('loginMethods'); + } + }); + + // Mirrors the DB `password_null_when_not_present` CHECK constraint. + test("rejects password set but 'password' not in loginMethods", () => { + const result = validateUserCreateInput({ + ...validInput, + loginMethods: ['saml'], + password: 'hashed', + }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('password'); + } + }); + + test("rejects 'password' in loginMethods without a password", () => { + const result = validateUserCreateInput({ + ...validInput, + loginMethods: ['password'], + password: null, + }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('password'); + } + }); + + test("rejects empty-string password when 'password' in loginMethods", () => { + const result = validateUserCreateInput({ + ...validInput, + loginMethods: ['password'], + password: '', + }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('password'); + } + }); + }); + + describe('validateUserUpdatePatch', () => { + test('accepts an empty patch (all fields undefined)', () => { + expect(validateUserUpdatePatch({})).toEqual({ ok: true }); + }); + + test('accepts explicit-null fields (skip semantics for non-password)', () => { + expect( + validateUserUpdatePatch({ + email: null, + firstName: null, + lastName: null, + role: null, + }), + ).toEqual({ ok: true }); + }); + + test('accepts password: null (clears password)', () => { + expect(validateUserUpdatePatch({ password: null })).toEqual({ ok: true }); + }); + + test('rejects password: "" (shape error)', () => { + const result = validateUserUpdatePatch({ password: '' }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('password'); + } + }); + + test('rejects empty / whitespace firstName / lastName', () => { + expect(validateUserUpdatePatch({ firstName: '' }).ok).toBe(false); + expect(validateUserUpdatePatch({ firstName: ' ' }).ok).toBe(false); + expect(validateUserUpdatePatch({ lastName: '' }).ok).toBe(false); + expect(validateUserUpdatePatch({ lastName: ' ' }).ok).toBe(false); + }); + + test('rejects malformed email', () => { + const result = validateUserUpdatePatch({ email: 'not-an-email' }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('email'); + } + }); + + test('rejects unknown role', () => { + const result = validateUserUpdatePatch({ role: 'NOT_A_REAL_ROLE' }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.failure.field).toBe('role'); + } + }); + }); +}); diff --git a/server/graphql/datasources/userValidation.ts b/server/graphql/datasources/userValidation.ts new file mode 100644 index 0000000..67d5ccb --- /dev/null +++ b/server/graphql/datasources/userValidation.ts @@ -0,0 +1,169 @@ +import { createRequire } from 'node:module'; +import type { IsEmailOptions } from 'validator/lib/isEmail.js'; + +import { UserRole } from '../../models/types/permissioning.js'; +import { type LoginMethod } from '../../services/coreAppTables.js'; + +// `validator` is CJS with UMD-style types whose `default` doesn't resolve to +// a callable under `module: NodeNext`; `createRequire` gives us `module.exports` +// directly, typed against the per-function defs that ship with `@types/validator`. +type ValidatorLib = { + isEmail: (str: string, options?: IsEmailOptions) => boolean; +}; +const validator = createRequire(import.meta.url)('validator') as ValidatorLib; + +/** + * Server-side validation for `User` inputs, replacing the `isEmail`, + * `notEmpty`, and `isIn` checks that lived on the Sequelize model, plus the + * DB `password_null_when_not_present` CHECK constraint (which we still rely + * on; this layer surfaces a useful error before the INSERT hits Postgres). + * + * Returned rather than thrown so each caller picks the right error surface: + * the data source wraps failures in `makeBadRequestError`, while persistence + * treats them as invariants. + */ + +export type UserValidationFailure = { + /** Kept stable for GraphQL JSON pointers. */ + field: + | 'email' + | 'firstName' + | 'lastName' + | 'role' + | 'loginMethods' + | 'password'; + message: string; +}; + +export type UserValidationResult = + | { ok: true } + | { ok: false; failure: UserValidationFailure }; + +function isEmailShape(value: string): boolean { + return validator.isEmail(value); +} + +function isNonEmptyTrimmed(value: string): boolean { + return value.trim().length > 0; +} + +function fail( + field: UserValidationFailure['field'], + message: string, +): UserValidationResult { + return { ok: false, failure: { field, message } }; +} + +const ALLOWED_LOGIN_METHODS: readonly LoginMethod[] = ['password', 'saml']; + +function validateLoginMethodsShape( + loginMethods: readonly string[], +): UserValidationResult { + if (loginMethods.length === 0) { + return fail('loginMethods', 'loginMethods must not be empty'); + } + for (const method of loginMethods) { + if (!ALLOWED_LOGIN_METHODS.includes(method as LoginMethod)) { + return fail( + 'loginMethods', + `loginMethods contains invalid entry '${method}'`, + ); + } + } + return { ok: true }; +} + +/** + * Mirrors the DB `password_null_when_not_present` CHECK: + * password IS NOT NULL ⇔ 'password' ∈ login_methods + */ +function validatePasswordLoginMethodsInvariant(input: { + password: string | null; + loginMethods: readonly LoginMethod[]; +}): UserValidationResult { + const hasPassword = input.password != null && input.password !== ''; + const usesPasswordLogin = input.loginMethods.includes('password'); + if (hasPassword && !usesPasswordLogin) { + return fail( + 'password', + "password must not be set when 'password' is not in loginMethods", + ); + } + if (!hasPassword && usesPasswordLogin) { + return fail( + 'password', + "password is required when 'password' is in loginMethods", + ); + } + return { ok: true }; +} + +export function validateUserCreateInput(input: { + email: string; + firstName: string; + lastName: string; + role: string; + loginMethods: readonly string[]; + password: string | null; +}): UserValidationResult { + if (!isNonEmptyTrimmed(input.email) || !isEmailShape(input.email)) { + return fail('email', 'email must be a valid email address'); + } + if (!isNonEmptyTrimmed(input.firstName)) { + return fail('firstName', 'firstName must not be empty'); + } + if (!isNonEmptyTrimmed(input.lastName)) { + return fail('lastName', 'lastName must not be empty'); + } + const roleValues: readonly string[] = Object.values(UserRole); + if (!roleValues.includes(input.role)) { + return fail('role', `role must be one of: ${roleValues.join(', ')}`); + } + const loginResult = validateLoginMethodsShape(input.loginMethods); + if (!loginResult.ok) { + return loginResult; + } + const invariantResult = validatePasswordLoginMethodsInvariant({ + password: input.password, + loginMethods: input.loginMethods as readonly LoginMethod[], + }); + if (!invariantResult.ok) { + return invariantResult; + } + return { ok: true }; +} + +/** + * Partial-update semantics match the Sequelize model: + * - `undefined` fields are skipped + * - `password: null` is a meaningful value (removes password login) + * - `password: ''` is rejected as a shape error + */ +export function validateUserUpdatePatch(patch: { + email?: string | null; + firstName?: string | null; + lastName?: string | null; + role?: string | null; + password?: string | null; +}): UserValidationResult { + if ( + patch.email != null && + (!isNonEmptyTrimmed(patch.email) || !isEmailShape(patch.email)) + ) { + return fail('email', 'email must be a valid email address'); + } + if (patch.firstName != null && !isNonEmptyTrimmed(patch.firstName)) { + return fail('firstName', 'firstName must not be empty'); + } + if (patch.lastName != null && !isNonEmptyTrimmed(patch.lastName)) { + return fail('lastName', 'lastName must not be empty'); + } + const roleValues: readonly string[] = Object.values(UserRole); + if (patch.role != null && !roleValues.includes(patch.role)) { + return fail('role', `role must be one of: ${roleValues.join(', ')}`); + } + if (patch.password === '') { + return fail('password', 'password must not be an empty string'); + } + return { ok: true }; +} diff --git a/server/graphql/generated.ts b/server/graphql/generated.ts index ccbfb71..52d8696 100644 --- a/server/graphql/generated.ts +++ b/server/graphql/generated.ts @@ -8,6 +8,7 @@ import { JsonObject, JsonValue } from 'type-fest'; import type { UserHistoryForGQL } from '../graphql/datasources/InvestigationApi.js'; import type { GraphQLOrgParent } from '../graphql/datasources/orgKyselyPersistence.js'; +import type { GraphQLUserParent } from '../graphql/datasources/userKyselyPersistence.js'; import type { ContentItemTypeResolversParentType, ItemTypeResolversParentType, @@ -21,7 +22,6 @@ import type { HashBank } from '../models/HashBankModel.js'; import type { Backtest } from '../models/rules/BacktestModel.js'; import type { ItemType } from '../models/rules/ItemTypeModel.js'; import type { Rule } from '../models/rules/RuleModel.js'; -import type { User } from '../models/UserModel.js'; import type { SignalWithScore } from '../services/analyticsQueries/RuleActionInsights.js'; import type { DerivedFieldSpecSource } from '../services/derivedFieldsService/helpers.js'; import type { @@ -60,12 +60,10 @@ import type { LocationBankWithoutFullPlacesAPIResponse } from './datasources/Loc import type { Context } from './resolvers.js'; import type { ItemSubmissionForGQL } from './types.js'; -export type Maybe = T extends Promise - ? Promise - : T | null; -export type InputMaybe = T extends Promise - ? Promise - : T | null; +export type Maybe = + T extends Promise ? Promise : T | null; +export type InputMaybe = + T extends Promise ? Promise : T | null; export type Exact = { [K in keyof T]: T[K]; }; @@ -6187,7 +6185,7 @@ export type GQLResolversTypes = { >; UpdateUserStrikeTTLInput: GQLUpdateUserStrikeTtlInput; UpdateUserStrikeTTLSuccessResponse: ResolverTypeWrapper; - User: ResolverTypeWrapper; + User: ResolverTypeWrapper; UserActionDecisionAction: GQLUserActionDecisionAction; UserActionDecisionPolicy: GQLUserActionDecisionPolicy; UserActionsHistory: ResolverTypeWrapper; @@ -6824,7 +6822,7 @@ export type GQLResolversParentTypes = { UpdateUserRuleResponse: GQLResolversUnionTypes['UpdateUserRuleResponse']; UpdateUserStrikeTTLInput: GQLUpdateUserStrikeTtlInput; UpdateUserStrikeTTLSuccessResponse: GQLUpdateUserStrikeTtlSuccessResponse; - User: User; + User: GraphQLUserParent; UserActionDecisionAction: GQLUserActionDecisionAction; UserActionDecisionPolicy: GQLUserActionDecisionPolicy; UserActionsHistory: GQLUserActionsHistory; @@ -6875,8 +6873,8 @@ export type GQLPublicResolverDirectiveResolver< export type GQLAcceptAppealDecisionComponentResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AcceptAppealDecisionComponent'] = GQLResolversParentTypes['AcceptAppealDecisionComponent'], + ParentType extends GQLResolversParentTypes['AcceptAppealDecisionComponent'] = + GQLResolversParentTypes['AcceptAppealDecisionComponent'], > = { actionIds?: Resolver< ReadonlyArray, @@ -6894,8 +6892,8 @@ export type GQLAcceptAppealDecisionComponentResolvers< export type GQLActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Action'] = GQLResolversParentTypes['Action'], + ParentType extends GQLResolversParentTypes['Action'] = + GQLResolversParentTypes['Action'], > = { __resolveType: TypeResolveFn< | 'CustomAction' @@ -6909,8 +6907,8 @@ export type GQLActionResolvers< export type GQLActionBaseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ActionBase'] = GQLResolversParentTypes['ActionBase'], + ParentType extends GQLResolversParentTypes['ActionBase'] = + GQLResolversParentTypes['ActionBase'], > = { __resolveType: TypeResolveFn< | 'CustomAction' @@ -6924,8 +6922,8 @@ export type GQLActionBaseResolvers< export type GQLActionDataResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ActionData'] = GQLResolversParentTypes['ActionData'], + ParentType extends GQLResolversParentTypes['ActionData'] = + GQLResolversParentTypes['ActionData'], > = { action_id?: Resolver< Maybe, @@ -6958,8 +6956,8 @@ export type GQLActionDataResolvers< export type GQLActionNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ActionNameExistsError'] = GQLResolversParentTypes['ActionNameExistsError'], + ParentType extends GQLResolversParentTypes['ActionNameExistsError'] = + GQLResolversParentTypes['ActionNameExistsError'], > = { detail?: Resolver< Maybe, @@ -6989,7 +6987,8 @@ export type GQLActionNameExistsErrorResolvers< export type GQLAddAccessibleQueuesToUserResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['AddAccessibleQueuesToUserResponse'] = GQLResolversParentTypes['AddAccessibleQueuesToUserResponse'], + GQLResolversParentTypes['AddAccessibleQueuesToUserResponse'] = + GQLResolversParentTypes['AddAccessibleQueuesToUserResponse'], > = { __resolveType: TypeResolveFn< 'MutateAccessibleQueuesForUserSuccessResponse', @@ -7000,8 +6999,8 @@ export type GQLAddAccessibleQueuesToUserResponseResolvers< export type GQLAddCommentFailedErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AddCommentFailedError'] = GQLResolversParentTypes['AddCommentFailedError'], + ParentType extends GQLResolversParentTypes['AddCommentFailedError'] = + GQLResolversParentTypes['AddCommentFailedError'], > = { detail?: Resolver< Maybe, @@ -7031,15 +7030,16 @@ export type GQLAddCommentFailedErrorResolvers< export type GQLAddFavoriteMrtQueueSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['AddFavoriteMRTQueueSuccessResponse'] = GQLResolversParentTypes['AddFavoriteMRTQueueSuccessResponse'], + GQLResolversParentTypes['AddFavoriteMRTQueueSuccessResponse'] = + GQLResolversParentTypes['AddFavoriteMRTQueueSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; export type GQLAddFavoriteRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AddFavoriteRuleResponse'] = GQLResolversParentTypes['AddFavoriteRuleResponse'], + ParentType extends GQLResolversParentTypes['AddFavoriteRuleResponse'] = + GQLResolversParentTypes['AddFavoriteRuleResponse'], > = { __resolveType: TypeResolveFn< 'AddFavoriteRuleSuccessResponse', @@ -7050,8 +7050,8 @@ export type GQLAddFavoriteRuleResponseResolvers< export type GQLAddFavoriteRuleSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AddFavoriteRuleSuccessResponse'] = GQLResolversParentTypes['AddFavoriteRuleSuccessResponse'], + ParentType extends GQLResolversParentTypes['AddFavoriteRuleSuccessResponse'] = + GQLResolversParentTypes['AddFavoriteRuleSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -7060,7 +7060,8 @@ export type GQLAddFavoriteRuleSuccessResponseResolvers< export type GQLAddManualReviewJobCommentResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['AddManualReviewJobCommentResponse'] = GQLResolversParentTypes['AddManualReviewJobCommentResponse'], + GQLResolversParentTypes['AddManualReviewJobCommentResponse'] = + GQLResolversParentTypes['AddManualReviewJobCommentResponse'], > = { __resolveType: TypeResolveFn< 'AddManualReviewJobCommentSuccessResponse' | 'NotFoundError', @@ -7072,7 +7073,8 @@ export type GQLAddManualReviewJobCommentResponseResolvers< export type GQLAddManualReviewJobCommentSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['AddManualReviewJobCommentSuccessResponse'] = GQLResolversParentTypes['AddManualReviewJobCommentSuccessResponse'], + GQLResolversParentTypes['AddManualReviewJobCommentSuccessResponse'] = + GQLResolversParentTypes['AddManualReviewJobCommentSuccessResponse'], > = { comment?: Resolver< GQLResolversTypes['ManualReviewJobComment'], @@ -7084,8 +7086,8 @@ export type GQLAddManualReviewJobCommentSuccessResponseResolvers< export type GQLAddPoliciesResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AddPoliciesResponse'] = GQLResolversParentTypes['AddPoliciesResponse'], + ParentType extends GQLResolversParentTypes['AddPoliciesResponse'] = + GQLResolversParentTypes['AddPoliciesResponse'], > = { failures?: Resolver< ReadonlyArray, @@ -7101,8 +7103,8 @@ export type GQLAddPoliciesResponseResolvers< export type GQLAggregationResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Aggregation'] = GQLResolversParentTypes['Aggregation'], + ParentType extends GQLResolversParentTypes['Aggregation'] = + GQLResolversParentTypes['Aggregation'], > = { type?: Resolver< GQLResolversTypes['AggregationType'], @@ -7113,8 +7115,8 @@ export type GQLAggregationResolvers< export type GQLAggregationClauseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AggregationClause'] = GQLResolversParentTypes['AggregationClause'], + ParentType extends GQLResolversParentTypes['AggregationClause'] = + GQLResolversParentTypes['AggregationClause'], > = { aggregation?: Resolver< Maybe, @@ -7141,8 +7143,8 @@ export type GQLAggregationClauseResolvers< export type GQLAggregationSignalArgsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AggregationSignalArgs'] = GQLResolversParentTypes['AggregationSignalArgs'], + ParentType extends GQLResolversParentTypes['AggregationSignalArgs'] = + GQLResolversParentTypes['AggregationSignalArgs'], > = { aggregationClause?: Resolver< Maybe, @@ -7154,8 +7156,8 @@ export type GQLAggregationSignalArgsResolvers< export type GQLAllLanguagesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AllLanguages'] = GQLResolversParentTypes['AllLanguages'], + ParentType extends GQLResolversParentTypes['AllLanguages'] = + GQLResolversParentTypes['AllLanguages'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -7163,8 +7165,8 @@ export type GQLAllLanguagesResolvers< export type GQLAllRuleInsightsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AllRuleInsights'] = GQLResolversParentTypes['AllRuleInsights'], + ParentType extends GQLResolversParentTypes['AllRuleInsights'] = + GQLResolversParentTypes['AllRuleInsights'], > = { actionedSubmissionsByActionByDay?: Resolver< ReadonlyArray, @@ -7195,8 +7197,8 @@ export type GQLAllRuleInsightsResolvers< export type GQLApiKeyResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ApiKey'] = GQLResolversParentTypes['ApiKey'], + ParentType extends GQLResolversParentTypes['ApiKey'] = + GQLResolversParentTypes['ApiKey'], > = { createdAt?: Resolver; createdBy?: Resolver< @@ -7221,8 +7223,8 @@ export type GQLApiKeyResolvers< export type GQLAppealEnqueueSourceInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AppealEnqueueSourceInfo'] = GQLResolversParentTypes['AppealEnqueueSourceInfo'], + ParentType extends GQLResolversParentTypes['AppealEnqueueSourceInfo'] = + GQLResolversParentTypes['AppealEnqueueSourceInfo'], > = { kind?: Resolver< GQLResolversTypes['JobCreationSourceOptions'], @@ -7234,8 +7236,8 @@ export type GQLAppealEnqueueSourceInfoResolvers< export type GQLAppealSettingsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['AppealSettings'] = GQLResolversParentTypes['AppealSettings'], + ParentType extends GQLResolversParentTypes['AppealSettings'] = + GQLResolversParentTypes['AppealSettings'], > = { appealsCallbackBody?: Resolver< Maybe, @@ -7257,7 +7259,8 @@ export type GQLAppealSettingsResolvers< export type GQLAutomaticCloseDecisionComponentResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['AutomaticCloseDecisionComponent'] = GQLResolversParentTypes['AutomaticCloseDecisionComponent'], + GQLResolversParentTypes['AutomaticCloseDecisionComponent'] = + GQLResolversParentTypes['AutomaticCloseDecisionComponent'], > = { type?: Resolver< GQLResolversTypes['ManualReviewDecisionType'], @@ -7269,8 +7272,8 @@ export type GQLAutomaticCloseDecisionComponentResolvers< export type GQLBacktestResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Backtest'] = GQLResolversParentTypes['Backtest'], + ParentType extends GQLResolversParentTypes['Backtest'] = + GQLResolversParentTypes['Backtest'], > = { contentItemsMatched?: Resolver< GQLResolversTypes['Int'], @@ -7320,8 +7323,8 @@ export type GQLBacktestResolvers< export type GQLBaseFieldResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['BaseField'] = GQLResolversParentTypes['BaseField'], + ParentType extends GQLResolversParentTypes['BaseField'] = + GQLResolversParentTypes['BaseField'], > = { container?: Resolver< Maybe, @@ -7336,8 +7339,8 @@ export type GQLBaseFieldResolvers< export type GQLCannotDeleteDefaultUserErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CannotDeleteDefaultUserError'] = GQLResolversParentTypes['CannotDeleteDefaultUserError'], + ParentType extends GQLResolversParentTypes['CannotDeleteDefaultUserError'] = + GQLResolversParentTypes['CannotDeleteDefaultUserError'], > = { detail?: Resolver< Maybe, @@ -7366,8 +7369,8 @@ export type GQLCannotDeleteDefaultUserErrorResolvers< export type GQLChangePasswordErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ChangePasswordError'] = GQLResolversParentTypes['ChangePasswordError'], + ParentType extends GQLResolversParentTypes['ChangePasswordError'] = + GQLResolversParentTypes['ChangePasswordError'], > = { detail?: Resolver< Maybe, @@ -7396,8 +7399,8 @@ export type GQLChangePasswordErrorResolvers< export type GQLChangePasswordResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ChangePasswordResponse'] = GQLResolversParentTypes['ChangePasswordResponse'], + ParentType extends GQLResolversParentTypes['ChangePasswordResponse'] = + GQLResolversParentTypes['ChangePasswordResponse'], > = { __resolveType: TypeResolveFn< 'ChangePasswordError' | 'ChangePasswordSuccessResponse', @@ -7408,8 +7411,8 @@ export type GQLChangePasswordResponseResolvers< export type GQLChangePasswordSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ChangePasswordSuccessResponse'] = GQLResolversParentTypes['ChangePasswordSuccessResponse'], + ParentType extends GQLResolversParentTypes['ChangePasswordSuccessResponse'] = + GQLResolversParentTypes['ChangePasswordSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -7417,8 +7420,8 @@ export type GQLChangePasswordSuccessResponseResolvers< export type GQLConditionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Condition'] = GQLResolversParentTypes['Condition'], + ParentType extends GQLResolversParentTypes['Condition'] = + GQLResolversParentTypes['Condition'], > = { __resolveType: TypeResolveFn< 'ConditionSet' | 'LeafCondition', @@ -7429,8 +7432,8 @@ export type GQLConditionResolvers< export type GQLConditionInputFieldResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ConditionInputField'] = GQLResolversParentTypes['ConditionInputField'], + ParentType extends GQLResolversParentTypes['ConditionInputField'] = + GQLResolversParentTypes['ConditionInputField'], > = { contentTypeId?: Resolver< Maybe, @@ -7461,8 +7464,8 @@ export type GQLConditionInputFieldResolvers< export type GQLConditionResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ConditionResult'] = GQLResolversParentTypes['ConditionResult'], + ParentType extends GQLResolversParentTypes['ConditionResult'] = + GQLResolversParentTypes['ConditionResult'], > = { matchedValue?: Resolver< Maybe, @@ -7479,8 +7482,8 @@ export type GQLConditionResultResolvers< export type GQLConditionSetResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ConditionSet'] = GQLResolversParentTypes['ConditionSet'], + ParentType extends GQLResolversParentTypes['ConditionSet'] = + GQLResolversParentTypes['ConditionSet'], > = { conditions?: Resolver< ReadonlyArray, @@ -7497,8 +7500,8 @@ export type GQLConditionSetResolvers< export type GQLConditionSetWithResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ConditionSetWithResult'] = GQLResolversParentTypes['ConditionSetWithResult'], + ParentType extends GQLResolversParentTypes['ConditionSetWithResult'] = + GQLResolversParentTypes['ConditionSetWithResult'], > = { conditions?: Resolver< ReadonlyArray, @@ -7520,8 +7523,8 @@ export type GQLConditionSetWithResultResolvers< export type GQLConditionWithResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ConditionWithResult'] = GQLResolversParentTypes['ConditionWithResult'], + ParentType extends GQLResolversParentTypes['ConditionWithResult'] = + GQLResolversParentTypes['ConditionWithResult'], > = { __resolveType: TypeResolveFn< 'ConditionSetWithResult' | 'LeafConditionWithResult', @@ -7532,8 +7535,8 @@ export type GQLConditionWithResultResolvers< export type GQLContainerResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Container'] = GQLResolversParentTypes['Container'], + ParentType extends GQLResolversParentTypes['Container'] = + GQLResolversParentTypes['Container'], > = { containerType?: Resolver< GQLResolversTypes['ContainerType'], @@ -7555,7 +7558,8 @@ export type GQLContainerResolvers< export type GQLContentAppealManualReviewJobPayloadResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['ContentAppealManualReviewJobPayload'] = GQLResolversParentTypes['ContentAppealManualReviewJobPayload'], + GQLResolversParentTypes['ContentAppealManualReviewJobPayload'] = + GQLResolversParentTypes['ContentAppealManualReviewJobPayload'], > = { actionsTaken?: Resolver< ReadonlyArray, @@ -7594,8 +7598,8 @@ export type GQLContentAppealManualReviewJobPayloadResolvers< export type GQLContentItemResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ContentItem'] = GQLResolversParentTypes['ContentItem'], + ParentType extends GQLResolversParentTypes['ContentItem'] = + GQLResolversParentTypes['ContentItem'], > = { data?: Resolver; id?: Resolver; @@ -7615,8 +7619,8 @@ export type GQLContentItemResolvers< export type GQLContentItemTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ContentItemType'] = GQLResolversParentTypes['ContentItemType'], + ParentType extends GQLResolversParentTypes['ContentItemType'] = + GQLResolversParentTypes['ContentItemType'], > = { baseFields?: Resolver< ReadonlyArray, @@ -7656,8 +7660,8 @@ export type GQLContentItemTypeResolvers< export type GQLContentManualReviewJobPayloadResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ContentManualReviewJobPayload'] = GQLResolversParentTypes['ContentManualReviewJobPayload'], + ParentType extends GQLResolversParentTypes['ContentManualReviewJobPayload'] = + GQLResolversParentTypes['ContentManualReviewJobPayload'], > = { additionalContentItems?: Resolver< ReadonlyArray, @@ -7700,8 +7704,8 @@ export type GQLContentManualReviewJobPayloadResolvers< export type GQLContentRuleResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ContentRule'] = GQLResolversParentTypes['ContentRule'], + ParentType extends GQLResolversParentTypes['ContentRule'] = + GQLResolversParentTypes['ContentRule'], > = { actions?: Resolver< ReadonlyArray, @@ -7766,8 +7770,8 @@ export type GQLContentRuleResolvers< export type GQLContentSchemaFieldRolesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ContentSchemaFieldRoles'] = GQLResolversParentTypes['ContentSchemaFieldRoles'], + ParentType extends GQLResolversParentTypes['ContentSchemaFieldRoles'] = + GQLResolversParentTypes['ContentSchemaFieldRoles'], > = { createdAt?: Resolver< Maybe, @@ -7804,8 +7808,8 @@ export type GQLContentSchemaFieldRolesResolvers< export type GQLContentTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ContentType'] = GQLResolversParentTypes['ContentType'], + ParentType extends GQLResolversParentTypes['ContentType'] = + GQLResolversParentTypes['ContentType'], > = { actions?: Resolver< ReadonlyArray, @@ -7831,15 +7835,17 @@ export type GQLContentTypeResolvers< name?: Resolver; }; -export interface GQLCoopInputOrStringScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLCoopInputOrStringScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['CoopInputOrString'], + any +> { name: 'CoopInputOrString'; } export type GQLCountByActionByDayResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByActionByDay'] = GQLResolversParentTypes['CountByActionByDay'], + ParentType extends GQLResolversParentTypes['CountByActionByDay'] = + GQLResolversParentTypes['CountByActionByDay'], > = { action?: Resolver< GQLResolversTypes['CountByActionByDayAction'], @@ -7852,8 +7858,8 @@ export type GQLCountByActionByDayResolvers< export type GQLCountByActionByDayActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByActionByDayAction'] = GQLResolversParentTypes['CountByActionByDayAction'], + ParentType extends GQLResolversParentTypes['CountByActionByDayAction'] = + GQLResolversParentTypes['CountByActionByDayAction'], > = { id?: Resolver; name?: Resolver; @@ -7861,8 +7867,8 @@ export type GQLCountByActionByDayActionResolvers< export type GQLCountByDayResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByDay'] = GQLResolversParentTypes['CountByDay'], + ParentType extends GQLResolversParentTypes['CountByDay'] = + GQLResolversParentTypes['CountByDay'], > = { count?: Resolver; date?: Resolver; @@ -7870,8 +7876,8 @@ export type GQLCountByDayResolvers< export type GQLCountByDecisionTypeByDayResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByDecisionTypeByDay'] = GQLResolversParentTypes['CountByDecisionTypeByDay'], + ParentType extends GQLResolversParentTypes['CountByDecisionTypeByDay'] = + GQLResolversParentTypes['CountByDecisionTypeByDay'], > = { count?: Resolver; date?: Resolver; @@ -7880,8 +7886,8 @@ export type GQLCountByDecisionTypeByDayResolvers< export type GQLCountByPolicyByDayResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByPolicyByDay'] = GQLResolversParentTypes['CountByPolicyByDay'], + ParentType extends GQLResolversParentTypes['CountByPolicyByDay'] = + GQLResolversParentTypes['CountByPolicyByDay'], > = { count?: Resolver; date?: Resolver; @@ -7894,8 +7900,8 @@ export type GQLCountByPolicyByDayResolvers< export type GQLCountByPolicyByDayPolicyResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByPolicyByDayPolicy'] = GQLResolversParentTypes['CountByPolicyByDayPolicy'], + ParentType extends GQLResolversParentTypes['CountByPolicyByDayPolicy'] = + GQLResolversParentTypes['CountByPolicyByDayPolicy'], > = { id?: Resolver; name?: Resolver; @@ -7903,8 +7909,8 @@ export type GQLCountByPolicyByDayPolicyResolvers< export type GQLCountByTagByDayResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CountByTagByDay'] = GQLResolversParentTypes['CountByTagByDay'], + ParentType extends GQLResolversParentTypes['CountByTagByDay'] = + GQLResolversParentTypes['CountByTagByDay'], > = { count?: Resolver; date?: Resolver; @@ -7913,16 +7919,16 @@ export type GQLCountByTagByDayResolvers< export type GQLCreateBacktestResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateBacktestResponse'] = GQLResolversParentTypes['CreateBacktestResponse'], + ParentType extends GQLResolversParentTypes['CreateBacktestResponse'] = + GQLResolversParentTypes['CreateBacktestResponse'], > = { backtest?: Resolver; }; export type GQLCreateContentRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateContentRuleResponse'] = GQLResolversParentTypes['CreateContentRuleResponse'], + ParentType extends GQLResolversParentTypes['CreateContentRuleResponse'] = + GQLResolversParentTypes['CreateContentRuleResponse'], > = { __resolveType: TypeResolveFn< 'MutateContentRuleSuccessResponse' | 'RuleNameExistsError', @@ -7934,7 +7940,8 @@ export type GQLCreateContentRuleResponseResolvers< export type GQLCreateManualReviewQueueResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['CreateManualReviewQueueResponse'] = GQLResolversParentTypes['CreateManualReviewQueueResponse'], + GQLResolversParentTypes['CreateManualReviewQueueResponse'] = + GQLResolversParentTypes['CreateManualReviewQueueResponse'], > = { __resolveType: TypeResolveFn< | 'ManualReviewQueueNameExistsError' @@ -7946,8 +7953,8 @@ export type GQLCreateManualReviewQueueResponseResolvers< export type GQLCreateOrgResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateOrgResponse'] = GQLResolversParentTypes['CreateOrgResponse'], + ParentType extends GQLResolversParentTypes['CreateOrgResponse'] = + GQLResolversParentTypes['CreateOrgResponse'], > = { __resolveType: TypeResolveFn< | 'CreateOrgSuccessResponse' @@ -7960,8 +7967,8 @@ export type GQLCreateOrgResponseResolvers< export type GQLCreateOrgSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateOrgSuccessResponse'] = GQLResolversParentTypes['CreateOrgSuccessResponse'], + ParentType extends GQLResolversParentTypes['CreateOrgSuccessResponse'] = + GQLResolversParentTypes['CreateOrgSuccessResponse'], > = { id?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -7969,8 +7976,8 @@ export type GQLCreateOrgSuccessResponseResolvers< export type GQLCreateReportingRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateReportingRuleResponse'] = GQLResolversParentTypes['CreateReportingRuleResponse'], + ParentType extends GQLResolversParentTypes['CreateReportingRuleResponse'] = + GQLResolversParentTypes['CreateReportingRuleResponse'], > = { __resolveType: TypeResolveFn< 'MutateReportingRuleSuccessResponse' | 'ReportingRuleNameExistsError', @@ -7981,8 +7988,8 @@ export type GQLCreateReportingRuleResponseResolvers< export type GQLCreateRoutingRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateRoutingRuleResponse'] = GQLResolversParentTypes['CreateRoutingRuleResponse'], + ParentType extends GQLResolversParentTypes['CreateRoutingRuleResponse'] = + GQLResolversParentTypes['CreateRoutingRuleResponse'], > = { __resolveType: TypeResolveFn< | 'MutateRoutingRuleSuccessResponse' @@ -7995,8 +8002,8 @@ export type GQLCreateRoutingRuleResponseResolvers< export type GQLCreateUserRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CreateUserRuleResponse'] = GQLResolversParentTypes['CreateUserRuleResponse'], + ParentType extends GQLResolversParentTypes['CreateUserRuleResponse'] = + GQLResolversParentTypes['CreateUserRuleResponse'], > = { __resolveType: TypeResolveFn< 'MutateUserRuleSuccessResponse' | 'RuleNameExistsError', @@ -8005,15 +8012,17 @@ export type GQLCreateUserRuleResponseResolvers< >; }; -export interface GQLCursorScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLCursorScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['Cursor'], + any +> { name: 'Cursor'; } export type GQLCustomActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CustomAction'] = GQLResolversParentTypes['CustomAction'], + ParentType extends GQLResolversParentTypes['CustomAction'] = + GQLResolversParentTypes['CustomAction'], > = { applyUserStrikes?: Resolver< Maybe, @@ -8059,28 +8068,32 @@ export type GQLCustomActionResolvers< export type GQLCustomMrtApiParamSpecResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['CustomMrtApiParamSpec'] = GQLResolversParentTypes['CustomMrtApiParamSpec'], + ParentType extends GQLResolversParentTypes['CustomMrtApiParamSpec'] = + GQLResolversParentTypes['CustomMrtApiParamSpec'], > = { displayName?: Resolver; name?: Resolver; type?: Resolver; }; -export interface GQLDateScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLDateScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['Date'], + any +> { name: 'Date'; } -export interface GQLDateTimeScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLDateTimeScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['DateTime'], + any +> { name: 'DateTime'; } export type GQLDecisionCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DecisionCount'] = GQLResolversParentTypes['DecisionCount'], + ParentType extends GQLResolversParentTypes['DecisionCount'] = + GQLResolversParentTypes['DecisionCount'], > = { action_id?: Resolver< Maybe, @@ -8113,8 +8126,8 @@ export type GQLDecisionCountResolvers< export type GQLDecisionCountFilterByResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DecisionCountFilterBy'] = GQLResolversParentTypes['DecisionCountFilterBy'], + ParentType extends GQLResolversParentTypes['DecisionCountFilterBy'] = + GQLResolversParentTypes['DecisionCountFilterBy'], > = { actionIds?: Resolver< ReadonlyArray, @@ -8157,8 +8170,8 @@ export type GQLDecisionCountFilterByResolvers< export type GQLDeleteAllJobsFromQueueResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DeleteAllJobsFromQueueResponse'] = GQLResolversParentTypes['DeleteAllJobsFromQueueResponse'], + ParentType extends GQLResolversParentTypes['DeleteAllJobsFromQueueResponse'] = + GQLResolversParentTypes['DeleteAllJobsFromQueueResponse'], > = { __resolveType: TypeResolveFn< 'DeleteAllJobsFromQueueSuccessResponse' | 'DeleteAllJobsUnauthorizedError', @@ -8170,7 +8183,8 @@ export type GQLDeleteAllJobsFromQueueResponseResolvers< export type GQLDeleteAllJobsFromQueueSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['DeleteAllJobsFromQueueSuccessResponse'] = GQLResolversParentTypes['DeleteAllJobsFromQueueSuccessResponse'], + GQLResolversParentTypes['DeleteAllJobsFromQueueSuccessResponse'] = + GQLResolversParentTypes['DeleteAllJobsFromQueueSuccessResponse'], > = { _?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -8178,8 +8192,8 @@ export type GQLDeleteAllJobsFromQueueSuccessResponseResolvers< export type GQLDeleteAllJobsUnauthorizedErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DeleteAllJobsUnauthorizedError'] = GQLResolversParentTypes['DeleteAllJobsUnauthorizedError'], + ParentType extends GQLResolversParentTypes['DeleteAllJobsUnauthorizedError'] = + GQLResolversParentTypes['DeleteAllJobsUnauthorizedError'], > = { detail?: Resolver< Maybe, @@ -8208,8 +8222,8 @@ export type GQLDeleteAllJobsUnauthorizedErrorResolvers< export type GQLDeleteItemTypeResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DeleteItemTypeResponse'] = GQLResolversParentTypes['DeleteItemTypeResponse'], + ParentType extends GQLResolversParentTypes['DeleteItemTypeResponse'] = + GQLResolversParentTypes['DeleteItemTypeResponse'], > = { __resolveType: TypeResolveFn< 'CannotDeleteDefaultUserError' | 'DeleteItemTypeSuccessResponse', @@ -8220,8 +8234,8 @@ export type GQLDeleteItemTypeResponseResolvers< export type GQLDeleteItemTypeSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DeleteItemTypeSuccessResponse'] = GQLResolversParentTypes['DeleteItemTypeSuccessResponse'], + ParentType extends GQLResolversParentTypes['DeleteItemTypeSuccessResponse'] = + GQLResolversParentTypes['DeleteItemTypeSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -8229,8 +8243,8 @@ export type GQLDeleteItemTypeSuccessResponseResolvers< export type GQLDequeueManualReviewJobResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DequeueManualReviewJobResponse'] = GQLResolversParentTypes['DequeueManualReviewJobResponse'], + ParentType extends GQLResolversParentTypes['DequeueManualReviewJobResponse'] = + GQLResolversParentTypes['DequeueManualReviewJobResponse'], > = { __resolveType: TypeResolveFn< 'DequeueManualReviewJobSuccessResponse', @@ -8242,7 +8256,8 @@ export type GQLDequeueManualReviewJobResponseResolvers< export type GQLDequeueManualReviewJobSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['DequeueManualReviewJobSuccessResponse'] = GQLResolversParentTypes['DequeueManualReviewJobSuccessResponse'], + GQLResolversParentTypes['DequeueManualReviewJobSuccessResponse'] = + GQLResolversParentTypes['DequeueManualReviewJobSuccessResponse'], > = { job?: Resolver; lockToken?: Resolver; @@ -8252,8 +8267,8 @@ export type GQLDequeueManualReviewJobSuccessResponseResolvers< export type GQLDerivedFieldResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DerivedField'] = GQLResolversParentTypes['DerivedField'], + ParentType extends GQLResolversParentTypes['DerivedField'] = + GQLResolversParentTypes['DerivedField'], > = { container?: Resolver< Maybe, @@ -8272,8 +8287,8 @@ export type GQLDerivedFieldResolvers< export type GQLDerivedFieldCoopInputSourceResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DerivedFieldCoopInputSource'] = GQLResolversParentTypes['DerivedFieldCoopInputSource'], + ParentType extends GQLResolversParentTypes['DerivedFieldCoopInputSource'] = + GQLResolversParentTypes['DerivedFieldCoopInputSource'], > = { name?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -8281,8 +8296,8 @@ export type GQLDerivedFieldCoopInputSourceResolvers< export type GQLDerivedFieldFieldSourceResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DerivedFieldFieldSource'] = GQLResolversParentTypes['DerivedFieldFieldSource'], + ParentType extends GQLResolversParentTypes['DerivedFieldFieldSource'] = + GQLResolversParentTypes['DerivedFieldFieldSource'], > = { contentTypeId?: Resolver< GQLResolversTypes['String'], @@ -8295,8 +8310,8 @@ export type GQLDerivedFieldFieldSourceResolvers< export type GQLDerivedFieldFullItemSourceResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DerivedFieldFullItemSource'] = GQLResolversParentTypes['DerivedFieldFullItemSource'], + ParentType extends GQLResolversParentTypes['DerivedFieldFullItemSource'] = + GQLResolversParentTypes['DerivedFieldFullItemSource'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -8304,8 +8319,8 @@ export type GQLDerivedFieldFullItemSourceResolvers< export type GQLDerivedFieldSourceResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DerivedFieldSource'] = GQLResolversParentTypes['DerivedFieldSource'], + ParentType extends GQLResolversParentTypes['DerivedFieldSource'] = + GQLResolversParentTypes['DerivedFieldSource'], > = { __resolveType: TypeResolveFn< | 'DerivedFieldCoopInputSource' @@ -8318,8 +8333,8 @@ export type GQLDerivedFieldSourceResolvers< export type GQLDerivedFieldSpecResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DerivedFieldSpec'] = GQLResolversParentTypes['DerivedFieldSpec'], + ParentType extends GQLResolversParentTypes['DerivedFieldSpec'] = + GQLResolversParentTypes['DerivedFieldSpec'], > = { derivationType?: Resolver< GQLResolversTypes['DerivedFieldDerivationType'], @@ -8335,8 +8350,8 @@ export type GQLDerivedFieldSpecResolvers< export type GQLDisabledInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['DisabledInfo'] = GQLResolversParentTypes['DisabledInfo'], + ParentType extends GQLResolversParentTypes['DisabledInfo'] = + GQLResolversParentTypes['DisabledInfo'], > = { disabled?: Resolver; disabledMessage?: Resolver< @@ -8348,8 +8363,8 @@ export type GQLDisabledInfoResolvers< export type GQLEnqueueAuthorToMrtActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['EnqueueAuthorToMrtAction'] = GQLResolversParentTypes['EnqueueAuthorToMrtAction'], + ParentType extends GQLResolversParentTypes['EnqueueAuthorToMrtAction'] = + GQLResolversParentTypes['EnqueueAuthorToMrtAction'], > = { applyUserStrikes?: Resolver< GQLResolversTypes['Boolean'], @@ -8379,8 +8394,8 @@ export type GQLEnqueueAuthorToMrtActionResolvers< export type GQLEnqueueToMrtActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['EnqueueToMrtAction'] = GQLResolversParentTypes['EnqueueToMrtAction'], + ParentType extends GQLResolversParentTypes['EnqueueToMrtAction'] = + GQLResolversParentTypes['EnqueueToMrtAction'], > = { applyUserStrikes?: Resolver< Maybe, @@ -8410,8 +8425,8 @@ export type GQLEnqueueToMrtActionResolvers< export type GQLEnqueueToNcmecActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['EnqueueToNcmecAction'] = GQLResolversParentTypes['EnqueueToNcmecAction'], + ParentType extends GQLResolversParentTypes['EnqueueToNcmecAction'] = + GQLResolversParentTypes['EnqueueToNcmecAction'], > = { applyUserStrikes?: Resolver< Maybe, @@ -8441,8 +8456,8 @@ export type GQLEnqueueToNcmecActionResolvers< export type GQLEnumSignalOutputTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['EnumSignalOutputType'] = GQLResolversParentTypes['EnumSignalOutputType'], + ParentType extends GQLResolversParentTypes['EnumSignalOutputType'] = + GQLResolversParentTypes['EnumSignalOutputType'], > = { enum?: Resolver< ReadonlyArray, @@ -8460,8 +8475,8 @@ export type GQLEnumSignalOutputTypeResolvers< export type GQLErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Error'] = GQLResolversParentTypes['Error'], + ParentType extends GQLResolversParentTypes['Error'] = + GQLResolversParentTypes['Error'], > = { __resolveType: TypeResolveFn< | 'ActionNameExistsError' @@ -8508,8 +8523,8 @@ export type GQLErrorResolvers< export type GQLExchangeApiInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExchangeApiInfo'] = GQLResolversParentTypes['ExchangeApiInfo'], + ParentType extends GQLResolversParentTypes['ExchangeApiInfo'] = + GQLResolversParentTypes['ExchangeApiInfo'], > = { has_auth?: Resolver; name?: Resolver; @@ -8522,8 +8537,8 @@ export type GQLExchangeApiInfoResolvers< export type GQLExchangeApiSchemaResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExchangeApiSchema'] = GQLResolversParentTypes['ExchangeApiSchema'], + ParentType extends GQLResolversParentTypes['ExchangeApiSchema'] = + GQLResolversParentTypes['ExchangeApiSchema'], > = { config_schema?: Resolver< GQLResolversTypes['ExchangeSchemaSection'], @@ -8539,8 +8554,8 @@ export type GQLExchangeApiSchemaResolvers< export type GQLExchangeFieldDescriptorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExchangeFieldDescriptor'] = GQLResolversParentTypes['ExchangeFieldDescriptor'], + ParentType extends GQLResolversParentTypes['ExchangeFieldDescriptor'] = + GQLResolversParentTypes['ExchangeFieldDescriptor'], > = { choices?: Resolver< Maybe>, @@ -8556,8 +8571,8 @@ export type GQLExchangeFieldDescriptorResolvers< export type GQLExchangeInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExchangeInfo'] = GQLResolversParentTypes['ExchangeInfo'], + ParentType extends GQLResolversParentTypes['ExchangeInfo'] = + GQLResolversParentTypes['ExchangeInfo'], > = { api?: Resolver; enabled?: Resolver; @@ -8592,8 +8607,8 @@ export type GQLExchangeInfoResolvers< export type GQLExchangeSchemaSectionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExchangeSchemaSection'] = GQLResolversParentTypes['ExchangeSchemaSection'], + ParentType extends GQLResolversParentTypes['ExchangeSchemaSection'] = + GQLResolversParentTypes['ExchangeSchemaSection'], > = { fields?: Resolver< ReadonlyArray, @@ -8604,8 +8619,8 @@ export type GQLExchangeSchemaSectionResolvers< export type GQLExecuteActionResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExecuteActionResponse'] = GQLResolversParentTypes['ExecuteActionResponse'], + ParentType extends GQLResolversParentTypes['ExecuteActionResponse'] = + GQLResolversParentTypes['ExecuteActionResponse'], > = { actionId?: Resolver; itemId?: Resolver; @@ -8614,8 +8629,8 @@ export type GQLExecuteActionResponseResolvers< export type GQLExecuteBulkActionResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ExecuteBulkActionResponse'] = GQLResolversParentTypes['ExecuteBulkActionResponse'], + ParentType extends GQLResolversParentTypes['ExecuteBulkActionResponse'] = + GQLResolversParentTypes['ExecuteBulkActionResponse'], > = { results?: Resolver< ReadonlyArray, @@ -8626,8 +8641,8 @@ export type GQLExecuteBulkActionResponseResolvers< export type GQLFieldResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Field'] = GQLResolversParentTypes['Field'], + ParentType extends GQLResolversParentTypes['Field'] = + GQLResolversParentTypes['Field'], > = { __resolveType: TypeResolveFn< 'BaseField' | 'DerivedField', @@ -8638,8 +8653,8 @@ export type GQLFieldResolvers< export type GQLGetDecisionCountSettingsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['GetDecisionCountSettings'] = GQLResolversParentTypes['GetDecisionCountSettings'], + ParentType extends GQLResolversParentTypes['GetDecisionCountSettings'] = + GQLResolversParentTypes['GetDecisionCountSettings'], > = { filterBy?: Resolver< GQLResolversTypes['DecisionCountFilterBy'], @@ -8668,7 +8683,8 @@ export type GQLGetDecisionCountSettingsResolvers< export type GQLGetFullReportingRuleResultForItemResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['GetFullReportingRuleResultForItemResponse'] = GQLResolversParentTypes['GetFullReportingRuleResultForItemResponse'], + GQLResolversParentTypes['GetFullReportingRuleResultForItemResponse'] = + GQLResolversParentTypes['GetFullReportingRuleResultForItemResponse'], > = { __resolveType: TypeResolveFn< 'NotFoundError' | 'ReportingRuleExecutionResult', @@ -8679,8 +8695,8 @@ export type GQLGetFullReportingRuleResultForItemResponseResolvers< export type GQLGetFullResultForItemResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['GetFullResultForItemResponse'] = GQLResolversParentTypes['GetFullResultForItemResponse'], + ParentType extends GQLResolversParentTypes['GetFullResultForItemResponse'] = + GQLResolversParentTypes['GetFullResultForItemResponse'], > = { __resolveType: TypeResolveFn< 'NotFoundError' | 'RuleExecutionResult', @@ -8691,8 +8707,8 @@ export type GQLGetFullResultForItemResponseResolvers< export type GQLGetJobCreationCountSettingsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['GetJobCreationCountSettings'] = GQLResolversParentTypes['GetJobCreationCountSettings'], + ParentType extends GQLResolversParentTypes['GetJobCreationCountSettings'] = + GQLResolversParentTypes['GetJobCreationCountSettings'], > = { filterBy?: Resolver< GQLResolversTypes['JobCreationFilterBy'], @@ -8721,7 +8737,8 @@ export type GQLGetJobCreationCountSettingsResolvers< export type GQLGoogleContentSafetyApiIntegrationApiCredentialResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['GoogleContentSafetyApiIntegrationApiCredential'] = GQLResolversParentTypes['GoogleContentSafetyApiIntegrationApiCredential'], + GQLResolversParentTypes['GoogleContentSafetyApiIntegrationApiCredential'] = + GQLResolversParentTypes['GoogleContentSafetyApiIntegrationApiCredential'], > = { apiKey?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -8729,16 +8746,16 @@ export type GQLGoogleContentSafetyApiIntegrationApiCredentialResolvers< export type GQLGooglePlaceLocationInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['GooglePlaceLocationInfo'] = GQLResolversParentTypes['GooglePlaceLocationInfo'], + ParentType extends GQLResolversParentTypes['GooglePlaceLocationInfo'] = + GQLResolversParentTypes['GooglePlaceLocationInfo'], > = { id?: Resolver; }; export type GQLHashBankResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['HashBank'] = GQLResolversParentTypes['HashBank'], + ParentType extends GQLResolversParentTypes['HashBank'] = + GQLResolversParentTypes['HashBank'], > = { description?: Resolver< Maybe, @@ -8759,8 +8776,8 @@ export type GQLHashBankResolvers< export type GQLIgnoreDecisionComponentResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IgnoreDecisionComponent'] = GQLResolversParentTypes['IgnoreDecisionComponent'], + ParentType extends GQLResolversParentTypes['IgnoreDecisionComponent'] = + GQLResolversParentTypes['IgnoreDecisionComponent'], > = { type?: Resolver< GQLResolversTypes['ManualReviewDecisionType'], @@ -8772,8 +8789,8 @@ export type GQLIgnoreDecisionComponentResolvers< export type GQLIntegrationApiCredentialResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IntegrationApiCredential'] = GQLResolversParentTypes['IntegrationApiCredential'], + ParentType extends GQLResolversParentTypes['IntegrationApiCredential'] = + GQLResolversParentTypes['IntegrationApiCredential'], > = { __resolveType: TypeResolveFn< | 'GoogleContentSafetyApiIntegrationApiCredential' @@ -8787,8 +8804,8 @@ export type GQLIntegrationApiCredentialResolvers< export type GQLIntegrationConfigResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IntegrationConfig'] = GQLResolversParentTypes['IntegrationConfig'], + ParentType extends GQLResolversParentTypes['IntegrationConfig'] = + GQLResolversParentTypes['IntegrationConfig'], > = { apiCredential?: Resolver< GQLResolversTypes['IntegrationApiCredential'], @@ -8823,8 +8840,8 @@ export type GQLIntegrationConfigResolvers< export type GQLIntegrationConfigQueryResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IntegrationConfigQueryResponse'] = GQLResolversParentTypes['IntegrationConfigQueryResponse'], + ParentType extends GQLResolversParentTypes['IntegrationConfigQueryResponse'] = + GQLResolversParentTypes['IntegrationConfigQueryResponse'], > = { __resolveType: TypeResolveFn< | 'IntegrationConfigSuccessResult' @@ -8836,8 +8853,8 @@ export type GQLIntegrationConfigQueryResponseResolvers< export type GQLIntegrationConfigSuccessResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IntegrationConfigSuccessResult'] = GQLResolversParentTypes['IntegrationConfigSuccessResult'], + ParentType extends GQLResolversParentTypes['IntegrationConfigSuccessResult'] = + GQLResolversParentTypes['IntegrationConfigSuccessResult'], > = { config?: Resolver< Maybe, @@ -8850,7 +8867,8 @@ export type GQLIntegrationConfigSuccessResultResolvers< export type GQLIntegrationConfigTooManyCredentialsErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['IntegrationConfigTooManyCredentialsError'] = GQLResolversParentTypes['IntegrationConfigTooManyCredentialsError'], + GQLResolversParentTypes['IntegrationConfigTooManyCredentialsError'] = + GQLResolversParentTypes['IntegrationConfigTooManyCredentialsError'], > = { detail?: Resolver< Maybe, @@ -8880,7 +8898,8 @@ export type GQLIntegrationConfigTooManyCredentialsErrorResolvers< export type GQLIntegrationConfigUnsupportedIntegrationErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['IntegrationConfigUnsupportedIntegrationError'] = GQLResolversParentTypes['IntegrationConfigUnsupportedIntegrationError'], + GQLResolversParentTypes['IntegrationConfigUnsupportedIntegrationError'] = + GQLResolversParentTypes['IntegrationConfigUnsupportedIntegrationError'], > = { detail?: Resolver< Maybe, @@ -8910,7 +8929,8 @@ export type GQLIntegrationConfigUnsupportedIntegrationErrorResolvers< export type GQLIntegrationEmptyInputCredentialsErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['IntegrationEmptyInputCredentialsError'] = GQLResolversParentTypes['IntegrationEmptyInputCredentialsError'], + GQLResolversParentTypes['IntegrationEmptyInputCredentialsError'] = + GQLResolversParentTypes['IntegrationEmptyInputCredentialsError'], > = { detail?: Resolver< Maybe, @@ -8939,8 +8959,8 @@ export type GQLIntegrationEmptyInputCredentialsErrorResolvers< export type GQLIntegrationMetadataResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IntegrationMetadata'] = GQLResolversParentTypes['IntegrationMetadata'], + ParentType extends GQLResolversParentTypes['IntegrationMetadata'] = + GQLResolversParentTypes['IntegrationMetadata'], > = { docsUrl?: Resolver; logoUrl?: Resolver< @@ -8965,7 +8985,8 @@ export type GQLIntegrationMetadataResolvers< export type GQLIntegrationNoInputCredentialsErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['IntegrationNoInputCredentialsError'] = GQLResolversParentTypes['IntegrationNoInputCredentialsError'], + GQLResolversParentTypes['IntegrationNoInputCredentialsError'] = + GQLResolversParentTypes['IntegrationNoInputCredentialsError'], > = { detail?: Resolver< Maybe, @@ -8994,8 +9015,8 @@ export type GQLIntegrationNoInputCredentialsErrorResolvers< export type GQLInviteUserTokenResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['InviteUserToken'] = GQLResolversParentTypes['InviteUserToken'], + ParentType extends GQLResolversParentTypes['InviteUserToken'] = + GQLResolversParentTypes['InviteUserToken'], > = { email?: Resolver; orgId?: Resolver; @@ -9006,8 +9027,8 @@ export type GQLInviteUserTokenResolvers< export type GQLInviteUserTokenExpiredErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['InviteUserTokenExpiredError'] = GQLResolversParentTypes['InviteUserTokenExpiredError'], + ParentType extends GQLResolversParentTypes['InviteUserTokenExpiredError'] = + GQLResolversParentTypes['InviteUserTokenExpiredError'], > = { detail?: Resolver< Maybe, @@ -9036,8 +9057,8 @@ export type GQLInviteUserTokenExpiredErrorResolvers< export type GQLInviteUserTokenMissingErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['InviteUserTokenMissingError'] = GQLResolversParentTypes['InviteUserTokenMissingError'], + ParentType extends GQLResolversParentTypes['InviteUserTokenMissingError'] = + GQLResolversParentTypes['InviteUserTokenMissingError'], > = { detail?: Resolver< Maybe, @@ -9066,8 +9087,8 @@ export type GQLInviteUserTokenMissingErrorResolvers< export type GQLInviteUserTokenResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['InviteUserTokenResponse'] = GQLResolversParentTypes['InviteUserTokenResponse'], + ParentType extends GQLResolversParentTypes['InviteUserTokenResponse'] = + GQLResolversParentTypes['InviteUserTokenResponse'], > = { __resolveType: TypeResolveFn< | 'InviteUserTokenExpiredError' @@ -9080,8 +9101,8 @@ export type GQLInviteUserTokenResponseResolvers< export type GQLInviteUserTokenSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['InviteUserTokenSuccessResponse'] = GQLResolversParentTypes['InviteUserTokenSuccessResponse'], + ParentType extends GQLResolversParentTypes['InviteUserTokenSuccessResponse'] = + GQLResolversParentTypes['InviteUserTokenSuccessResponse'], > = { tokenData?: Resolver< GQLResolversTypes['InviteUserToken'], @@ -9093,8 +9114,8 @@ export type GQLInviteUserTokenSuccessResponseResolvers< export type GQLIpAddressResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['IpAddress'] = GQLResolversParentTypes['IpAddress'], + ParentType extends GQLResolversParentTypes['IpAddress'] = + GQLResolversParentTypes['IpAddress'], > = { ip?: Resolver; port?: Resolver, ParentType, ContextType>; @@ -9102,8 +9123,8 @@ export type GQLIpAddressResolvers< export type GQLItemResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Item'] = GQLResolversParentTypes['Item'], + ParentType extends GQLResolversParentTypes['Item'] = + GQLResolversParentTypes['Item'], > = { __resolveType: TypeResolveFn< 'ContentItem' | 'ThreadItem' | 'UserItem', @@ -9114,8 +9135,8 @@ export type GQLItemResolvers< export type GQLItemActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemAction'] = GQLResolversParentTypes['ItemAction'], + ParentType extends GQLResolversParentTypes['ItemAction'] = + GQLResolversParentTypes['ItemAction'], > = { actionId?: Resolver; actorId?: Resolver, ParentType, ContextType>; @@ -9147,8 +9168,8 @@ export type GQLItemActionResolvers< export type GQLItemBaseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemBase'] = GQLResolversParentTypes['ItemBase'], + ParentType extends GQLResolversParentTypes['ItemBase'] = + GQLResolversParentTypes['ItemBase'], > = { __resolveType: TypeResolveFn< 'ContentItem' | 'ThreadItem' | 'UserItem', @@ -9159,8 +9180,8 @@ export type GQLItemBaseResolvers< export type GQLItemHistoryResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemHistoryResponse'] = GQLResolversParentTypes['ItemHistoryResponse'], + ParentType extends GQLResolversParentTypes['ItemHistoryResponse'] = + GQLResolversParentTypes['ItemHistoryResponse'], > = { __resolveType: TypeResolveFn< 'ItemHistoryResult' | 'NotFoundError', @@ -9171,8 +9192,8 @@ export type GQLItemHistoryResponseResolvers< export type GQLItemHistoryResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemHistoryResult'] = GQLResolversParentTypes['ItemHistoryResult'], + ParentType extends GQLResolversParentTypes['ItemHistoryResult'] = + GQLResolversParentTypes['ItemHistoryResult'], > = { executions?: Resolver< ReadonlyArray, @@ -9185,8 +9206,8 @@ export type GQLItemHistoryResultResolvers< export type GQLItemIdentifierResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemIdentifier'] = GQLResolversParentTypes['ItemIdentifier'], + ParentType extends GQLResolversParentTypes['ItemIdentifier'] = + GQLResolversParentTypes['ItemIdentifier'], > = { id?: Resolver; typeId?: Resolver; @@ -9194,8 +9215,8 @@ export type GQLItemIdentifierResolvers< export type GQLItemSubmissionsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemSubmissions'] = GQLResolversParentTypes['ItemSubmissions'], + ParentType extends GQLResolversParentTypes['ItemSubmissions'] = + GQLResolversParentTypes['ItemSubmissions'], > = { latest?: Resolver; prior?: Resolver< @@ -9207,8 +9228,8 @@ export type GQLItemSubmissionsResolvers< export type GQLItemTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemType'] = GQLResolversParentTypes['ItemType'], + ParentType extends GQLResolversParentTypes['ItemType'] = + GQLResolversParentTypes['ItemType'], > = { __resolveType: TypeResolveFn< 'ContentItemType' | 'ThreadItemType' | 'UserItemType', @@ -9219,8 +9240,8 @@ export type GQLItemTypeResolvers< export type GQLItemTypeBaseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemTypeBase'] = GQLResolversParentTypes['ItemTypeBase'], + ParentType extends GQLResolversParentTypes['ItemTypeBase'] = + GQLResolversParentTypes['ItemTypeBase'], > = { __resolveType: TypeResolveFn< 'ContentItemType' | 'ThreadItemType' | 'UserItemType', @@ -9231,8 +9252,8 @@ export type GQLItemTypeBaseResolvers< export type GQLItemTypeIdentifierResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemTypeIdentifier'] = GQLResolversParentTypes['ItemTypeIdentifier'], + ParentType extends GQLResolversParentTypes['ItemTypeIdentifier'] = + GQLResolversParentTypes['ItemTypeIdentifier'], > = { id?: Resolver; schemaVariant?: Resolver< @@ -9249,8 +9270,8 @@ export type GQLItemTypeIdentifierResolvers< export type GQLItemTypeNameAlreadyExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemTypeNameAlreadyExistsError'] = GQLResolversParentTypes['ItemTypeNameAlreadyExistsError'], + ParentType extends GQLResolversParentTypes['ItemTypeNameAlreadyExistsError'] = + GQLResolversParentTypes['ItemTypeNameAlreadyExistsError'], > = { detail?: Resolver< Maybe, @@ -9289,8 +9310,8 @@ export type GQLItemTypeSchemaVariantInputResolvers = EnumResolverSignature< export type GQLItemWithParentsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ItemWithParents'] = GQLResolversParentTypes['ItemWithParents'], + ParentType extends GQLResolversParentTypes['ItemWithParents'] = + GQLResolversParentTypes['ItemWithParents'], > = { item?: Resolver< GQLResolversTypes['ItemSubmissions'], @@ -9304,20 +9325,24 @@ export type GQLItemWithParentsResolvers< >; }; -export interface GQLJsonScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLJsonScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['JSON'], + any +> { name: 'JSON'; } -export interface GQLJsonObjectScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLJsonObjectScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['JSONObject'], + any +> { name: 'JSONObject'; } export type GQLJobCreationCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['JobCreationCount'] = GQLResolversParentTypes['JobCreationCount'], + ParentType extends GQLResolversParentTypes['JobCreationCount'] = + GQLResolversParentTypes['JobCreationCount'], > = { count?: Resolver; itemTypeId?: Resolver< @@ -9350,8 +9375,8 @@ export type GQLJobCreationCountResolvers< export type GQLJobCreationFilterByResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['JobCreationFilterBy'] = GQLResolversParentTypes['JobCreationFilterBy'], + ParentType extends GQLResolversParentTypes['JobCreationFilterBy'] = + GQLResolversParentTypes['JobCreationFilterBy'], > = { endDate?: Resolver; itemTypeIds?: Resolver< @@ -9385,7 +9410,8 @@ export type GQLJobCreationFilterByResolvers< export type GQLJobHasAlreadyBeenSubmittedErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['JobHasAlreadyBeenSubmittedError'] = GQLResolversParentTypes['JobHasAlreadyBeenSubmittedError'], + GQLResolversParentTypes['JobHasAlreadyBeenSubmittedError'] = + GQLResolversParentTypes['JobHasAlreadyBeenSubmittedError'], > = { detail?: Resolver< Maybe, @@ -9414,8 +9440,8 @@ export type GQLJobHasAlreadyBeenSubmittedErrorResolvers< export type GQLLanguagesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Languages'] = GQLResolversParentTypes['Languages'], + ParentType extends GQLResolversParentTypes['Languages'] = + GQLResolversParentTypes['Languages'], > = { languages?: Resolver< ReadonlyArray, @@ -9427,8 +9453,8 @@ export type GQLLanguagesResolvers< export type GQLLatLngResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LatLng'] = GQLResolversParentTypes['LatLng'], + ParentType extends GQLResolversParentTypes['LatLng'] = + GQLResolversParentTypes['LatLng'], > = { lat?: Resolver; lng?: Resolver; @@ -9436,8 +9462,8 @@ export type GQLLatLngResolvers< export type GQLLeafConditionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LeafCondition'] = GQLResolversParentTypes['LeafCondition'], + ParentType extends GQLResolversParentTypes['LeafCondition'] = + GQLResolversParentTypes['LeafCondition'], > = { comparator?: Resolver< Maybe, @@ -9469,8 +9495,8 @@ export type GQLLeafConditionResolvers< export type GQLLeafConditionWithResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LeafConditionWithResult'] = GQLResolversParentTypes['LeafConditionWithResult'], + ParentType extends GQLResolversParentTypes['LeafConditionWithResult'] = + GQLResolversParentTypes['LeafConditionWithResult'], > = { comparator?: Resolver< Maybe, @@ -9507,8 +9533,8 @@ export type GQLLeafConditionWithResultResolvers< export type GQLLocationAreaResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LocationArea'] = GQLResolversParentTypes['LocationArea'], + ParentType extends GQLResolversParentTypes['LocationArea'] = + GQLResolversParentTypes['LocationArea'], > = { bounds?: Resolver< Maybe, @@ -9531,8 +9557,8 @@ export type GQLLocationAreaResolvers< export type GQLLocationBankResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LocationBank'] = GQLResolversParentTypes['LocationBank'], + ParentType extends GQLResolversParentTypes['LocationBank'] = + GQLResolversParentTypes['LocationBank'], > = { description?: Resolver< Maybe, @@ -9550,8 +9576,8 @@ export type GQLLocationBankResolvers< export type GQLLocationBankNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LocationBankNameExistsError'] = GQLResolversParentTypes['LocationBankNameExistsError'], + ParentType extends GQLResolversParentTypes['LocationBankNameExistsError'] = + GQLResolversParentTypes['LocationBankNameExistsError'], > = { detail?: Resolver< Maybe, @@ -9580,8 +9606,8 @@ export type GQLLocationBankNameExistsErrorResolvers< export type GQLLocationGeometryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LocationGeometry'] = GQLResolversParentTypes['LocationGeometry'], + ParentType extends GQLResolversParentTypes['LocationGeometry'] = + GQLResolversParentTypes['LocationGeometry'], > = { center?: Resolver; radius?: Resolver; @@ -9589,8 +9615,8 @@ export type GQLLocationGeometryResolvers< export type GQLLoginIncorrectPasswordErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LoginIncorrectPasswordError'] = GQLResolversParentTypes['LoginIncorrectPasswordError'], + ParentType extends GQLResolversParentTypes['LoginIncorrectPasswordError'] = + GQLResolversParentTypes['LoginIncorrectPasswordError'], > = { detail?: Resolver< Maybe, @@ -9619,8 +9645,8 @@ export type GQLLoginIncorrectPasswordErrorResolvers< export type GQLLoginResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LoginResponse'] = GQLResolversParentTypes['LoginResponse'], + ParentType extends GQLResolversParentTypes['LoginResponse'] = + GQLResolversParentTypes['LoginResponse'], > = { __resolveType: TypeResolveFn< | 'LoginIncorrectPasswordError' @@ -9634,8 +9660,8 @@ export type GQLLoginResponseResolvers< export type GQLLoginSsoRequiredErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LoginSsoRequiredError'] = GQLResolversParentTypes['LoginSsoRequiredError'], + ParentType extends GQLResolversParentTypes['LoginSsoRequiredError'] = + GQLResolversParentTypes['LoginSsoRequiredError'], > = { detail?: Resolver< Maybe, @@ -9664,8 +9690,8 @@ export type GQLLoginSsoRequiredErrorResolvers< export type GQLLoginSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LoginSuccessResponse'] = GQLResolversParentTypes['LoginSuccessResponse'], + ParentType extends GQLResolversParentTypes['LoginSuccessResponse'] = + GQLResolversParentTypes['LoginSuccessResponse'], > = { user?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -9673,8 +9699,8 @@ export type GQLLoginSuccessResponseResolvers< export type GQLLoginUserDoesNotExistErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['LoginUserDoesNotExistError'] = GQLResolversParentTypes['LoginUserDoesNotExistError'], + ParentType extends GQLResolversParentTypes['LoginUserDoesNotExistError'] = + GQLResolversParentTypes['LoginUserDoesNotExistError'], > = { detail?: Resolver< Maybe, @@ -9703,8 +9729,8 @@ export type GQLLoginUserDoesNotExistErrorResolvers< export type GQLManualReviewChartSettingsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewChartSettings'] = GQLResolversParentTypes['ManualReviewChartSettings'], + ParentType extends GQLResolversParentTypes['ManualReviewChartSettings'] = + GQLResolversParentTypes['ManualReviewChartSettings'], > = { __resolveType: TypeResolveFn< 'GetDecisionCountSettings' | 'GetJobCreationCountSettings', @@ -9715,8 +9741,8 @@ export type GQLManualReviewChartSettingsResolvers< export type GQLManualReviewDecisionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewDecision'] = GQLResolversParentTypes['ManualReviewDecision'], + ParentType extends GQLResolversParentTypes['ManualReviewDecision'] = + GQLResolversParentTypes['ManualReviewDecision'], > = { createdAt?: Resolver; decisionReason?: Resolver< @@ -9756,8 +9782,8 @@ export type GQLManualReviewDecisionResolvers< export type GQLManualReviewDecisionComponentResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewDecisionComponent'] = GQLResolversParentTypes['ManualReviewDecisionComponent'], + ParentType extends GQLResolversParentTypes['ManualReviewDecisionComponent'] = + GQLResolversParentTypes['ManualReviewDecisionComponent'], > = { __resolveType: TypeResolveFn< | 'AcceptAppealDecisionComponent' @@ -9775,7 +9801,8 @@ export type GQLManualReviewDecisionComponentResolvers< export type GQLManualReviewDecisionComponentBaseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['ManualReviewDecisionComponentBase'] = GQLResolversParentTypes['ManualReviewDecisionComponentBase'], + GQLResolversParentTypes['ManualReviewDecisionComponentBase'] = + GQLResolversParentTypes['ManualReviewDecisionComponentBase'], > = { __resolveType: TypeResolveFn< | 'AcceptAppealDecisionComponent' @@ -9792,8 +9819,8 @@ export type GQLManualReviewDecisionComponentBaseResolvers< export type GQLManualReviewExistingJobResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewExistingJob'] = GQLResolversParentTypes['ManualReviewExistingJob'], + ParentType extends GQLResolversParentTypes['ManualReviewExistingJob'] = + GQLResolversParentTypes['ManualReviewExistingJob'], > = { job?: Resolver; queueId?: Resolver; @@ -9801,8 +9828,8 @@ export type GQLManualReviewExistingJobResolvers< export type GQLManualReviewJobResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewJob'] = GQLResolversParentTypes['ManualReviewJob'], + ParentType extends GQLResolversParentTypes['ManualReviewJob'] = + GQLResolversParentTypes['ManualReviewJob'], > = { comments?: Resolver< ReadonlyArray, @@ -9830,8 +9857,8 @@ export type GQLManualReviewJobResolvers< export type GQLManualReviewJobCommentResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewJobComment'] = GQLResolversParentTypes['ManualReviewJobComment'], + ParentType extends GQLResolversParentTypes['ManualReviewJobComment'] = + GQLResolversParentTypes['ManualReviewJobComment'], > = { author?: Resolver; commentText?: Resolver; @@ -9842,7 +9869,8 @@ export type GQLManualReviewJobCommentResolvers< export type GQLManualReviewJobEnqueueSourceInfoResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['ManualReviewJobEnqueueSourceInfo'] = GQLResolversParentTypes['ManualReviewJobEnqueueSourceInfo'], + GQLResolversParentTypes['ManualReviewJobEnqueueSourceInfo'] = + GQLResolversParentTypes['ManualReviewJobEnqueueSourceInfo'], > = { __resolveType: TypeResolveFn< | 'AppealEnqueueSourceInfo' @@ -9857,8 +9885,8 @@ export type GQLManualReviewJobEnqueueSourceInfoResolvers< export type GQLManualReviewJobPayloadResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewJobPayload'] = GQLResolversParentTypes['ManualReviewJobPayload'], + ParentType extends GQLResolversParentTypes['ManualReviewJobPayload'] = + GQLResolversParentTypes['ManualReviewJobPayload'], > = { __resolveType: TypeResolveFn< | 'ContentAppealManualReviewJobPayload' @@ -9875,8 +9903,8 @@ export type GQLManualReviewJobPayloadResolvers< export type GQLManualReviewJobWithDecisionsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewJobWithDecisions'] = GQLResolversParentTypes['ManualReviewJobWithDecisions'], + ParentType extends GQLResolversParentTypes['ManualReviewJobWithDecisions'] = + GQLResolversParentTypes['ManualReviewJobWithDecisions'], > = { decision?: Resolver< GQLResolversTypes['ManualReviewDecision'], @@ -9888,8 +9916,8 @@ export type GQLManualReviewJobWithDecisionsResolvers< export type GQLManualReviewQueueResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ManualReviewQueue'] = GQLResolversParentTypes['ManualReviewQueue'], + ParentType extends GQLResolversParentTypes['ManualReviewQueue'] = + GQLResolversParentTypes['ManualReviewQueue'], > = { autoCloseJobs?: Resolver< GQLResolversTypes['Boolean'], @@ -9941,7 +9969,8 @@ export type GQLManualReviewQueueResolvers< export type GQLManualReviewQueueNameExistsErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['ManualReviewQueueNameExistsError'] = GQLResolversParentTypes['ManualReviewQueueNameExistsError'], + GQLResolversParentTypes['ManualReviewQueueNameExistsError'] = + GQLResolversParentTypes['ManualReviewQueueNameExistsError'], > = { detail?: Resolver< Maybe, @@ -9970,8 +9999,8 @@ export type GQLManualReviewQueueNameExistsErrorResolvers< export type GQLMatchingBankNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MatchingBankNameExistsError'] = GQLResolversParentTypes['MatchingBankNameExistsError'], + ParentType extends GQLResolversParentTypes['MatchingBankNameExistsError'] = + GQLResolversParentTypes['MatchingBankNameExistsError'], > = { detail?: Resolver< Maybe, @@ -10000,8 +10029,8 @@ export type GQLMatchingBankNameExistsErrorResolvers< export type GQLMatchingBanksResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MatchingBanks'] = GQLResolversParentTypes['MatchingBanks'], + ParentType extends GQLResolversParentTypes['MatchingBanks'] = + GQLResolversParentTypes['MatchingBanks'], > = { hashBanks?: Resolver< ReadonlyArray, @@ -10022,8 +10051,8 @@ export type GQLMatchingBanksResolvers< export type GQLMatchingValuesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MatchingValues'] = GQLResolversParentTypes['MatchingValues'], + ParentType extends GQLResolversParentTypes['MatchingValues'] = + GQLResolversParentTypes['MatchingValues'], > = { imageBankIds?: Resolver< Maybe>, @@ -10054,8 +10083,8 @@ export type GQLMatchingValuesResolvers< export type GQLMessageWithIpAddressResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MessageWithIpAddress'] = GQLResolversParentTypes['MessageWithIpAddress'], + ParentType extends GQLResolversParentTypes['MessageWithIpAddress'] = + GQLResolversParentTypes['MessageWithIpAddress'], > = { ipAddress?: Resolver; message?: Resolver; @@ -10063,8 +10092,8 @@ export type GQLMessageWithIpAddressResolvers< export type GQLModelCardResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ModelCard'] = GQLResolversParentTypes['ModelCard'], + ParentType extends GQLResolversParentTypes['ModelCard'] = + GQLResolversParentTypes['ModelCard'], > = { modelName?: Resolver; releaseDate?: Resolver< @@ -10082,8 +10111,8 @@ export type GQLModelCardResolvers< export type GQLModelCardFieldResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ModelCardField'] = GQLResolversParentTypes['ModelCardField'], + ParentType extends GQLResolversParentTypes['ModelCardField'] = + GQLResolversParentTypes['ModelCardField'], > = { label?: Resolver; value?: Resolver; @@ -10091,8 +10120,8 @@ export type GQLModelCardFieldResolvers< export type GQLModelCardSectionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ModelCardSection'] = GQLResolversParentTypes['ModelCardSection'], + ParentType extends GQLResolversParentTypes['ModelCardSection'] = + GQLResolversParentTypes['ModelCardSection'], > = { fields?: Resolver< Maybe>, @@ -10110,8 +10139,8 @@ export type GQLModelCardSectionResolvers< export type GQLModelCardSubsectionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ModelCardSubsection'] = GQLResolversParentTypes['ModelCardSubsection'], + ParentType extends GQLResolversParentTypes['ModelCardSubsection'] = + GQLResolversParentTypes['ModelCardSubsection'], > = { fields?: Resolver< ReadonlyArray, @@ -10123,8 +10152,8 @@ export type GQLModelCardSubsectionResolvers< export type GQLMrtJobEnqueueSourceInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MrtJobEnqueueSourceInfo'] = GQLResolversParentTypes['MrtJobEnqueueSourceInfo'], + ParentType extends GQLResolversParentTypes['MrtJobEnqueueSourceInfo'] = + GQLResolversParentTypes['MrtJobEnqueueSourceInfo'], > = { kind?: Resolver< GQLResolversTypes['JobCreationSourceOptions'], @@ -10137,7 +10166,8 @@ export type GQLMrtJobEnqueueSourceInfoResolvers< export type GQLMutateAccessibleQueuesForUserSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateAccessibleQueuesForUserSuccessResponse'] = GQLResolversParentTypes['MutateAccessibleQueuesForUserSuccessResponse'], + GQLResolversParentTypes['MutateAccessibleQueuesForUserSuccessResponse'] = + GQLResolversParentTypes['MutateAccessibleQueuesForUserSuccessResponse'], > = { _?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10145,8 +10175,8 @@ export type GQLMutateAccessibleQueuesForUserSuccessResponseResolvers< export type GQLMutateActionResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateActionResponse'] = GQLResolversParentTypes['MutateActionResponse'], + ParentType extends GQLResolversParentTypes['MutateActionResponse'] = + GQLResolversParentTypes['MutateActionResponse'], > = { __resolveType: TypeResolveFn< 'ActionNameExistsError' | 'MutateActionSuccessResponse', @@ -10157,8 +10187,8 @@ export type GQLMutateActionResponseResolvers< export type GQLMutateActionSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateActionSuccessResponse'] = GQLResolversParentTypes['MutateActionSuccessResponse'], + ParentType extends GQLResolversParentTypes['MutateActionSuccessResponse'] = + GQLResolversParentTypes['MutateActionSuccessResponse'], > = { data?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10166,8 +10196,8 @@ export type GQLMutateActionSuccessResponseResolvers< export type GQLMutateBankResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateBankResponse'] = GQLResolversParentTypes['MutateBankResponse'], + ParentType extends GQLResolversParentTypes['MutateBankResponse'] = + GQLResolversParentTypes['MutateBankResponse'], > = { error?: Resolver, ParentType, ContextType>; success?: Resolver< @@ -10179,8 +10209,8 @@ export type GQLMutateBankResponseResolvers< export type GQLMutateContentItemTypeResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateContentItemTypeResponse'] = GQLResolversParentTypes['MutateContentItemTypeResponse'], + ParentType extends GQLResolversParentTypes['MutateContentItemTypeResponse'] = + GQLResolversParentTypes['MutateContentItemTypeResponse'], > = { __resolveType: TypeResolveFn< 'ItemTypeNameAlreadyExistsError' | 'MutateContentTypeSuccessResponse', @@ -10192,7 +10222,8 @@ export type GQLMutateContentItemTypeResponseResolvers< export type GQLMutateContentRuleSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateContentRuleSuccessResponse'] = GQLResolversParentTypes['MutateContentRuleSuccessResponse'], + GQLResolversParentTypes['MutateContentRuleSuccessResponse'] = + GQLResolversParentTypes['MutateContentRuleSuccessResponse'], > = { data?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10201,7 +10232,8 @@ export type GQLMutateContentRuleSuccessResponseResolvers< export type GQLMutateContentTypeSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateContentTypeSuccessResponse'] = GQLResolversParentTypes['MutateContentTypeSuccessResponse'], + GQLResolversParentTypes['MutateContentTypeSuccessResponse'] = + GQLResolversParentTypes['MutateContentTypeSuccessResponse'], > = { data?: Resolver< Maybe, @@ -10213,8 +10245,8 @@ export type GQLMutateContentTypeSuccessResponseResolvers< export type GQLMutateHashBankResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateHashBankResponse'] = GQLResolversParentTypes['MutateHashBankResponse'], + ParentType extends GQLResolversParentTypes['MutateHashBankResponse'] = + GQLResolversParentTypes['MutateHashBankResponse'], > = { __resolveType: TypeResolveFn< 'MatchingBankNameExistsError' | 'MutateHashBankSuccessResponse', @@ -10225,8 +10257,8 @@ export type GQLMutateHashBankResponseResolvers< export type GQLMutateHashBankSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateHashBankSuccessResponse'] = GQLResolversParentTypes['MutateHashBankSuccessResponse'], + ParentType extends GQLResolversParentTypes['MutateHashBankSuccessResponse'] = + GQLResolversParentTypes['MutateHashBankSuccessResponse'], > = { data?: Resolver; warning?: Resolver< @@ -10239,8 +10271,8 @@ export type GQLMutateHashBankSuccessResponseResolvers< export type GQLMutateLocationBankResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateLocationBankResponse'] = GQLResolversParentTypes['MutateLocationBankResponse'], + ParentType extends GQLResolversParentTypes['MutateLocationBankResponse'] = + GQLResolversParentTypes['MutateLocationBankResponse'], > = { __resolveType: TypeResolveFn< 'LocationBankNameExistsError' | 'MutateLocationBankSuccessResponse', @@ -10252,7 +10284,8 @@ export type GQLMutateLocationBankResponseResolvers< export type GQLMutateLocationBankSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateLocationBankSuccessResponse'] = GQLResolversParentTypes['MutateLocationBankSuccessResponse'], + GQLResolversParentTypes['MutateLocationBankSuccessResponse'] = + GQLResolversParentTypes['MutateLocationBankSuccessResponse'], > = { data?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10261,7 +10294,8 @@ export type GQLMutateLocationBankSuccessResponseResolvers< export type GQLMutateManualReviewQueueSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateManualReviewQueueSuccessResponse'] = GQLResolversParentTypes['MutateManualReviewQueueSuccessResponse'], + GQLResolversParentTypes['MutateManualReviewQueueSuccessResponse'] = + GQLResolversParentTypes['MutateManualReviewQueueSuccessResponse'], > = { data?: Resolver< GQLResolversTypes['ManualReviewQueue'], @@ -10274,7 +10308,8 @@ export type GQLMutateManualReviewQueueSuccessResponseResolvers< export type GQLMutateReportingRuleSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateReportingRuleSuccessResponse'] = GQLResolversParentTypes['MutateReportingRuleSuccessResponse'], + GQLResolversParentTypes['MutateReportingRuleSuccessResponse'] = + GQLResolversParentTypes['MutateReportingRuleSuccessResponse'], > = { data?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10283,7 +10318,8 @@ export type GQLMutateReportingRuleSuccessResponseResolvers< export type GQLMutateRoutingRuleSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateRoutingRuleSuccessResponse'] = GQLResolversParentTypes['MutateRoutingRuleSuccessResponse'], + GQLResolversParentTypes['MutateRoutingRuleSuccessResponse'] = + GQLResolversParentTypes['MutateRoutingRuleSuccessResponse'], > = { data?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10292,7 +10328,8 @@ export type GQLMutateRoutingRuleSuccessResponseResolvers< export type GQLMutateRoutingRulesOrderSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateRoutingRulesOrderSuccessResponse'] = GQLResolversParentTypes['MutateRoutingRulesOrderSuccessResponse'], + GQLResolversParentTypes['MutateRoutingRulesOrderSuccessResponse'] = + GQLResolversParentTypes['MutateRoutingRulesOrderSuccessResponse'], > = { data?: Resolver< ReadonlyArray, @@ -10304,8 +10341,8 @@ export type GQLMutateRoutingRulesOrderSuccessResponseResolvers< export type GQLMutateThreadItemTypeResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateThreadItemTypeResponse'] = GQLResolversParentTypes['MutateThreadItemTypeResponse'], + ParentType extends GQLResolversParentTypes['MutateThreadItemTypeResponse'] = + GQLResolversParentTypes['MutateThreadItemTypeResponse'], > = { __resolveType: TypeResolveFn< 'ItemTypeNameAlreadyExistsError' | 'MutateThreadTypeSuccessResponse', @@ -10317,7 +10354,8 @@ export type GQLMutateThreadItemTypeResponseResolvers< export type GQLMutateThreadTypeSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['MutateThreadTypeSuccessResponse'] = GQLResolversParentTypes['MutateThreadTypeSuccessResponse'], + GQLResolversParentTypes['MutateThreadTypeSuccessResponse'] = + GQLResolversParentTypes['MutateThreadTypeSuccessResponse'], > = { data?: Resolver< Maybe, @@ -10329,8 +10367,8 @@ export type GQLMutateThreadTypeSuccessResponseResolvers< export type GQLMutateUserItemTypeResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateUserItemTypeResponse'] = GQLResolversParentTypes['MutateUserItemTypeResponse'], + ParentType extends GQLResolversParentTypes['MutateUserItemTypeResponse'] = + GQLResolversParentTypes['MutateUserItemTypeResponse'], > = { __resolveType: TypeResolveFn< 'ItemTypeNameAlreadyExistsError' | 'MutateUserTypeSuccessResponse', @@ -10341,8 +10379,8 @@ export type GQLMutateUserItemTypeResponseResolvers< export type GQLMutateUserRuleSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateUserRuleSuccessResponse'] = GQLResolversParentTypes['MutateUserRuleSuccessResponse'], + ParentType extends GQLResolversParentTypes['MutateUserRuleSuccessResponse'] = + GQLResolversParentTypes['MutateUserRuleSuccessResponse'], > = { data?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -10350,8 +10388,8 @@ export type GQLMutateUserRuleSuccessResponseResolvers< export type GQLMutateUserTypeSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['MutateUserTypeSuccessResponse'] = GQLResolversParentTypes['MutateUserTypeSuccessResponse'], + ParentType extends GQLResolversParentTypes['MutateUserTypeSuccessResponse'] = + GQLResolversParentTypes['MutateUserTypeSuccessResponse'], > = { data?: Resolver< Maybe, @@ -10363,8 +10401,8 @@ export type GQLMutateUserTypeSuccessResponseResolvers< export type GQLMutationResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Mutation'] = GQLResolversParentTypes['Mutation'], + ParentType extends GQLResolversParentTypes['Mutation'] = + GQLResolversParentTypes['Mutation'], > = { addAccessibleQueuesToUser?: Resolver< GQLResolversTypes['AddAccessibleQueuesToUserResponse'], @@ -10878,8 +10916,8 @@ export type GQLMutationResolvers< export type GQLNcmecReportResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NCMECReport'] = GQLResolversParentTypes['NCMECReport'], + ParentType extends GQLResolversParentTypes['NCMECReport'] = + GQLResolversParentTypes['NCMECReport'], > = { additionalFiles?: Resolver< ReadonlyArray, @@ -10919,8 +10957,8 @@ export type GQLNcmecReportResolvers< export type GQLNcmecReportedMediaResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NCMECReportedMedia'] = GQLResolversParentTypes['NCMECReportedMedia'], + ParentType extends GQLResolversParentTypes['NCMECReportedMedia'] = + GQLResolversParentTypes['NCMECReportedMedia'], > = { id?: Resolver; xml?: Resolver; @@ -10928,8 +10966,8 @@ export type GQLNcmecReportedMediaResolvers< export type GQLNcmecReportedThreadResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NCMECReportedThread'] = GQLResolversParentTypes['NCMECReportedThread'], + ParentType extends GQLResolversParentTypes['NCMECReportedThread'] = + GQLResolversParentTypes['NCMECReportedThread'], > = { csv?: Resolver; fileName?: Resolver; @@ -10938,8 +10976,8 @@ export type GQLNcmecReportedThreadResolvers< export type GQLNcmecAdditionalFileResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NcmecAdditionalFile'] = GQLResolversParentTypes['NcmecAdditionalFile'], + ParentType extends GQLResolversParentTypes['NcmecAdditionalFile'] = + GQLResolversParentTypes['NcmecAdditionalFile'], > = { ncmecFileId?: Resolver; url?: Resolver; @@ -10948,8 +10986,8 @@ export type GQLNcmecAdditionalFileResolvers< export type GQLNcmecContentItemResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NcmecContentItem'] = GQLResolversParentTypes['NcmecContentItem'], + ParentType extends GQLResolversParentTypes['NcmecContentItem'] = + GQLResolversParentTypes['NcmecContentItem'], > = { contentItem?: Resolver; isConfirmedCSAM?: Resolver< @@ -10962,8 +11000,8 @@ export type GQLNcmecContentItemResolvers< export type GQLNcmecManualReviewJobPayloadResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NcmecManualReviewJobPayload'] = GQLResolversParentTypes['NcmecManualReviewJobPayload'], + ParentType extends GQLResolversParentTypes['NcmecManualReviewJobPayload'] = + GQLResolversParentTypes['NcmecManualReviewJobPayload'], > = { allMediaItems?: Resolver< ReadonlyArray, @@ -10986,8 +11024,8 @@ export type GQLNcmecManualReviewJobPayloadResolvers< export type GQLNcmecOrgSettingsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NcmecOrgSettings'] = GQLResolversParentTypes['NcmecOrgSettings'], + ParentType extends GQLResolversParentTypes['NcmecOrgSettings'] = + GQLResolversParentTypes['NcmecOrgSettings'], > = { companyTemplate?: Resolver< Maybe, @@ -11060,8 +11098,8 @@ export type GQLNcmecOrgSettingsResolvers< export type GQLNcmecReportedMediaDetailsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NcmecReportedMediaDetails'] = GQLResolversParentTypes['NcmecReportedMediaDetails'], + ParentType extends GQLResolversParentTypes['NcmecReportedMediaDetails'] = + GQLResolversParentTypes['NcmecReportedMediaDetails'], > = { fileAnnotations?: Resolver< ReadonlyArray, @@ -11080,8 +11118,8 @@ export type GQLNcmecReportedMediaDetailsResolvers< export type GQLNoJobWithIdInQueueErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NoJobWithIdInQueueError'] = GQLResolversParentTypes['NoJobWithIdInQueueError'], + ParentType extends GQLResolversParentTypes['NoJobWithIdInQueueError'] = + GQLResolversParentTypes['NoJobWithIdInQueueError'], > = { detail?: Resolver< Maybe, @@ -11108,15 +11146,17 @@ export type GQLNoJobWithIdInQueueErrorResolvers< __isTypeOf?: IsTypeOfResolverFn; }; -export interface GQLNonEmptyStringScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLNonEmptyStringScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['NonEmptyString'], + any +> { name: 'NonEmptyString'; } export type GQLNotFoundErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['NotFoundError'] = GQLResolversParentTypes['NotFoundError'], + ParentType extends GQLResolversParentTypes['NotFoundError'] = + GQLResolversParentTypes['NotFoundError'], > = { detail?: Resolver< Maybe, @@ -11145,8 +11185,8 @@ export type GQLNotFoundErrorResolvers< export type GQLNotificationResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Notification'] = GQLResolversParentTypes['Notification'], + ParentType extends GQLResolversParentTypes['Notification'] = + GQLResolversParentTypes['Notification'], > = { createdAt?: Resolver; data?: Resolver< @@ -11170,8 +11210,8 @@ export type GQLNotificationResolvers< export type GQLOpenAiIntegrationApiCredentialResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['OpenAiIntegrationApiCredential'] = GQLResolversParentTypes['OpenAiIntegrationApiCredential'], + ParentType extends GQLResolversParentTypes['OpenAiIntegrationApiCredential'] = + GQLResolversParentTypes['OpenAiIntegrationApiCredential'], > = { apiKey?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -11179,8 +11219,8 @@ export type GQLOpenAiIntegrationApiCredentialResolvers< export type GQLOrgResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Org'] = GQLResolversParentTypes['Org'], + ParentType extends GQLResolversParentTypes['Org'] = + GQLResolversParentTypes['Org'], > = { actions?: Resolver< ReadonlyArray, @@ -11349,8 +11389,8 @@ export type GQLOrgResolvers< export type GQLOrgWithEmailExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['OrgWithEmailExistsError'] = GQLResolversParentTypes['OrgWithEmailExistsError'], + ParentType extends GQLResolversParentTypes['OrgWithEmailExistsError'] = + GQLResolversParentTypes['OrgWithEmailExistsError'], > = { detail?: Resolver< Maybe, @@ -11379,8 +11419,8 @@ export type GQLOrgWithEmailExistsErrorResolvers< export type GQLOrgWithNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['OrgWithNameExistsError'] = GQLResolversParentTypes['OrgWithNameExistsError'], + ParentType extends GQLResolversParentTypes['OrgWithNameExistsError'] = + GQLResolversParentTypes['OrgWithNameExistsError'], > = { detail?: Resolver< Maybe, @@ -11409,8 +11449,8 @@ export type GQLOrgWithNameExistsErrorResolvers< export type GQLPageInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PageInfo'] = GQLResolversParentTypes['PageInfo'], + ParentType extends GQLResolversParentTypes['PageInfo'] = + GQLResolversParentTypes['PageInfo'], > = { endCursor?: Resolver; hasNextPage?: Resolver; @@ -11425,7 +11465,8 @@ export type GQLPageInfoResolvers< export type GQLPartialItemsEndpointResponseErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['PartialItemsEndpointResponseError'] = GQLResolversParentTypes['PartialItemsEndpointResponseError'], + GQLResolversParentTypes['PartialItemsEndpointResponseError'] = + GQLResolversParentTypes['PartialItemsEndpointResponseError'], > = { detail?: Resolver< Maybe, @@ -11455,7 +11496,8 @@ export type GQLPartialItemsEndpointResponseErrorResolvers< export type GQLPartialItemsInvalidResponseErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['PartialItemsInvalidResponseError'] = GQLResolversParentTypes['PartialItemsInvalidResponseError'], + GQLResolversParentTypes['PartialItemsInvalidResponseError'] = + GQLResolversParentTypes['PartialItemsInvalidResponseError'], > = { detail?: Resolver< Maybe, @@ -11485,7 +11527,8 @@ export type GQLPartialItemsInvalidResponseErrorResolvers< export type GQLPartialItemsMissingEndpointErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['PartialItemsMissingEndpointError'] = GQLResolversParentTypes['PartialItemsMissingEndpointError'], + GQLResolversParentTypes['PartialItemsMissingEndpointError'] = + GQLResolversParentTypes['PartialItemsMissingEndpointError'], > = { detail?: Resolver< Maybe, @@ -11514,8 +11557,8 @@ export type GQLPartialItemsMissingEndpointErrorResolvers< export type GQLPartialItemsResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PartialItemsResponse'] = GQLResolversParentTypes['PartialItemsResponse'], + ParentType extends GQLResolversParentTypes['PartialItemsResponse'] = + GQLResolversParentTypes['PartialItemsResponse'], > = { __resolveType: TypeResolveFn< | 'PartialItemsEndpointResponseError' @@ -11529,8 +11572,8 @@ export type GQLPartialItemsResponseResolvers< export type GQLPartialItemsSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PartialItemsSuccessResponse'] = GQLResolversParentTypes['PartialItemsSuccessResponse'], + ParentType extends GQLResolversParentTypes['PartialItemsSuccessResponse'] = + GQLResolversParentTypes['PartialItemsSuccessResponse'], > = { items?: Resolver< ReadonlyArray, @@ -11542,8 +11585,8 @@ export type GQLPartialItemsSuccessResponseResolvers< export type GQLPendingInviteResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PendingInvite'] = GQLResolversParentTypes['PendingInvite'], + ParentType extends GQLResolversParentTypes['PendingInvite'] = + GQLResolversParentTypes['PendingInvite'], > = { createdAt?: Resolver; email?: Resolver; @@ -11553,8 +11596,8 @@ export type GQLPendingInviteResolvers< export type GQLPlaceBoundsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PlaceBounds'] = GQLResolversParentTypes['PlaceBounds'], + ParentType extends GQLResolversParentTypes['PlaceBounds'] = + GQLResolversParentTypes['PlaceBounds'], > = { northeastCorner?: Resolver< GQLResolversTypes['LatLng'], @@ -11570,8 +11613,8 @@ export type GQLPlaceBoundsResolvers< export type GQLPluginIntegrationApiCredentialResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PluginIntegrationApiCredential'] = GQLResolversParentTypes['PluginIntegrationApiCredential'], + ParentType extends GQLResolversParentTypes['PluginIntegrationApiCredential'] = + GQLResolversParentTypes['PluginIntegrationApiCredential'], > = { credential?: Resolver< GQLResolversTypes['JSONObject'], @@ -11583,8 +11626,8 @@ export type GQLPluginIntegrationApiCredentialResolvers< export type GQLPolicyResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Policy'] = GQLResolversParentTypes['Policy'], + ParentType extends GQLResolversParentTypes['Policy'] = + GQLResolversParentTypes['Policy'], > = { applyUserStrikeCountConfigToChildren?: Resolver< Maybe, @@ -11619,8 +11662,8 @@ export type GQLPolicyResolvers< export type GQLPolicyActionCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PolicyActionCount'] = GQLResolversParentTypes['PolicyActionCount'], + ParentType extends GQLResolversParentTypes['PolicyActionCount'] = + GQLResolversParentTypes['PolicyActionCount'], > = { actionId?: Resolver; actorId?: Resolver< @@ -11643,8 +11686,8 @@ export type GQLPolicyActionCountResolvers< export type GQLPolicyNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PolicyNameExistsError'] = GQLResolversParentTypes['PolicyNameExistsError'], + ParentType extends GQLResolversParentTypes['PolicyNameExistsError'] = + GQLResolversParentTypes['PolicyNameExistsError'], > = { detail?: Resolver< Maybe, @@ -11673,8 +11716,8 @@ export type GQLPolicyNameExistsErrorResolvers< export type GQLPolicyViolationsCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PolicyViolationsCount'] = GQLResolversParentTypes['PolicyViolationsCount'], + ParentType extends GQLResolversParentTypes['PolicyViolationsCount'] = + GQLResolversParentTypes['PolicyViolationsCount'], > = { count?: Resolver; policyId?: Resolver; @@ -11682,8 +11725,8 @@ export type GQLPolicyViolationsCountResolvers< export type GQLPostActionsEnqueueSourceInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['PostActionsEnqueueSourceInfo'] = GQLResolversParentTypes['PostActionsEnqueueSourceInfo'], + ParentType extends GQLResolversParentTypes['PostActionsEnqueueSourceInfo'] = + GQLResolversParentTypes['PostActionsEnqueueSourceInfo'], > = { kind?: Resolver< GQLResolversTypes['JobCreationSourceOptions'], @@ -11695,8 +11738,8 @@ export type GQLPostActionsEnqueueSourceInfoResolvers< export type GQLQueryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Query'] = GQLResolversParentTypes['Query'], + ParentType extends GQLResolversParentTypes['Query'] = + GQLResolversParentTypes['Query'], > = { action?: Resolver< Maybe, @@ -12060,8 +12103,8 @@ export type GQLQueryResolvers< export type GQLQueueDoesNotExistErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['QueueDoesNotExistError'] = GQLResolversParentTypes['QueueDoesNotExistError'], + ParentType extends GQLResolversParentTypes['QueueDoesNotExistError'] = + GQLResolversParentTypes['QueueDoesNotExistError'], > = { detail?: Resolver< Maybe, @@ -12090,8 +12133,8 @@ export type GQLQueueDoesNotExistErrorResolvers< export type GQLRecentDecisionsForUserResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RecentDecisionsForUser'] = GQLResolversParentTypes['RecentDecisionsForUser'], + ParentType extends GQLResolversParentTypes['RecentDecisionsForUser'] = + GQLResolversParentTypes['RecentDecisionsForUser'], > = { recentDecisions?: Resolver< ReadonlyArray, @@ -12107,8 +12150,8 @@ export type GQLRecentDecisionsForUserResolvers< export type GQLRecentUserStrikeActionsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RecentUserStrikeActions'] = GQLResolversParentTypes['RecentUserStrikeActions'], + ParentType extends GQLResolversParentTypes['RecentUserStrikeActions'] = + GQLResolversParentTypes['RecentUserStrikeActions'], > = { actionId?: Resolver; itemId?: Resolver; @@ -12119,8 +12162,8 @@ export type GQLRecentUserStrikeActionsResolvers< export type GQLRecommendedThresholdsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RecommendedThresholds'] = GQLResolversParentTypes['RecommendedThresholds'], + ParentType extends GQLResolversParentTypes['RecommendedThresholds'] = + GQLResolversParentTypes['RecommendedThresholds'], > = { highPrecisionThreshold?: Resolver< GQLResolversTypes['StringOrFloat'], @@ -12137,7 +12180,8 @@ export type GQLRecommendedThresholdsResolvers< export type GQLRecordingJobDecisionFailedErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['RecordingJobDecisionFailedError'] = GQLResolversParentTypes['RecordingJobDecisionFailedError'], + GQLResolversParentTypes['RecordingJobDecisionFailedError'] = + GQLResolversParentTypes['RecordingJobDecisionFailedError'], > = { detail?: Resolver< Maybe, @@ -12166,8 +12210,8 @@ export type GQLRecordingJobDecisionFailedErrorResolvers< export type GQLRejectAppealDecisionComponentResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RejectAppealDecisionComponent'] = GQLResolversParentTypes['RejectAppealDecisionComponent'], + ParentType extends GQLResolversParentTypes['RejectAppealDecisionComponent'] = + GQLResolversParentTypes['RejectAppealDecisionComponent'], > = { actionIds?: Resolver< ReadonlyArray, @@ -12186,7 +12230,8 @@ export type GQLRejectAppealDecisionComponentResolvers< export type GQLRemoveAccessibleQueuesToUserResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['RemoveAccessibleQueuesToUserResponse'] = GQLResolversParentTypes['RemoveAccessibleQueuesToUserResponse'], + GQLResolversParentTypes['RemoveAccessibleQueuesToUserResponse'] = + GQLResolversParentTypes['RemoveAccessibleQueuesToUserResponse'], > = { __resolveType: TypeResolveFn< 'MutateAccessibleQueuesForUserSuccessResponse' | 'NotFoundError', @@ -12198,15 +12243,16 @@ export type GQLRemoveAccessibleQueuesToUserResponseResolvers< export type GQLRemoveFavoriteMrtQueueSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['RemoveFavoriteMRTQueueSuccessResponse'] = GQLResolversParentTypes['RemoveFavoriteMRTQueueSuccessResponse'], + GQLResolversParentTypes['RemoveFavoriteMRTQueueSuccessResponse'] = + GQLResolversParentTypes['RemoveFavoriteMRTQueueSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; export type GQLRemoveFavoriteRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RemoveFavoriteRuleResponse'] = GQLResolversParentTypes['RemoveFavoriteRuleResponse'], + ParentType extends GQLResolversParentTypes['RemoveFavoriteRuleResponse'] = + GQLResolversParentTypes['RemoveFavoriteRuleResponse'], > = { __resolveType: TypeResolveFn< 'RemoveFavoriteRuleSuccessResponse', @@ -12218,7 +12264,8 @@ export type GQLRemoveFavoriteRuleResponseResolvers< export type GQLRemoveFavoriteRuleSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['RemoveFavoriteRuleSuccessResponse'] = GQLResolversParentTypes['RemoveFavoriteRuleSuccessResponse'], + GQLResolversParentTypes['RemoveFavoriteRuleSuccessResponse'] = + GQLResolversParentTypes['RemoveFavoriteRuleSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -12226,8 +12273,8 @@ export type GQLRemoveFavoriteRuleSuccessResponseResolvers< export type GQLReorderRoutingRulesResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReorderRoutingRulesResponse'] = GQLResolversParentTypes['ReorderRoutingRulesResponse'], + ParentType extends GQLResolversParentTypes['ReorderRoutingRulesResponse'] = + GQLResolversParentTypes['ReorderRoutingRulesResponse'], > = { __resolveType: TypeResolveFn< 'MutateRoutingRulesOrderSuccessResponse', @@ -12238,8 +12285,8 @@ export type GQLReorderRoutingRulesResponseResolvers< export type GQLReportEnqueueSourceInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportEnqueueSourceInfo'] = GQLResolversParentTypes['ReportEnqueueSourceInfo'], + ParentType extends GQLResolversParentTypes['ReportEnqueueSourceInfo'] = + GQLResolversParentTypes['ReportEnqueueSourceInfo'], > = { kind?: Resolver< GQLResolversTypes['JobCreationSourceOptions'], @@ -12251,8 +12298,8 @@ export type GQLReportEnqueueSourceInfoResolvers< export type GQLReportHistoryEntryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportHistoryEntry'] = GQLResolversParentTypes['ReportHistoryEntry'], + ParentType extends GQLResolversParentTypes['ReportHistoryEntry'] = + GQLResolversParentTypes['ReportHistoryEntry'], > = { policyId?: Resolver, ParentType, ContextType>; reason?: Resolver< @@ -12271,8 +12318,8 @@ export type GQLReportHistoryEntryResolvers< export type GQLReportedForReasonResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportedForReason'] = GQLResolversParentTypes['ReportedForReason'], + ParentType extends GQLResolversParentTypes['ReportedForReason'] = + GQLResolversParentTypes['ReportedForReason'], > = { reason?: Resolver< Maybe, @@ -12288,8 +12335,8 @@ export type GQLReportedForReasonResolvers< export type GQLReportingInsightsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportingInsights'] = GQLResolversParentTypes['ReportingInsights'], + ParentType extends GQLResolversParentTypes['ReportingInsights'] = + GQLResolversParentTypes['ReportingInsights'], > = { totalIngestedReportsByDay?: Resolver< ReadonlyArray, @@ -12300,8 +12347,8 @@ export type GQLReportingInsightsResolvers< export type GQLReportingRuleResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportingRule'] = GQLResolversParentTypes['ReportingRule'], + ParentType extends GQLResolversParentTypes['ReportingRule'] = + GQLResolversParentTypes['ReportingRule'], > = { actions?: Resolver< ReadonlyArray, @@ -12346,8 +12393,8 @@ export type GQLReportingRuleResolvers< export type GQLReportingRuleExecutionResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportingRuleExecutionResult'] = GQLResolversParentTypes['ReportingRuleExecutionResult'], + ParentType extends GQLResolversParentTypes['ReportingRuleExecutionResult'] = + GQLResolversParentTypes['ReportingRuleExecutionResult'], > = { creatorId?: Resolver< Maybe, @@ -12393,8 +12440,8 @@ export type GQLReportingRuleExecutionResultResolvers< export type GQLReportingRuleInsightsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportingRuleInsights'] = GQLResolversParentTypes['ReportingRuleInsights'], + ParentType extends GQLResolversParentTypes['ReportingRuleInsights'] = + GQLResolversParentTypes['ReportingRuleInsights'], > = { latestVersionSamples?: Resolver< ReadonlyArray, @@ -12416,8 +12463,8 @@ export type GQLReportingRuleInsightsResolvers< export type GQLReportingRuleNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportingRuleNameExistsError'] = GQLResolversParentTypes['ReportingRuleNameExistsError'], + ParentType extends GQLResolversParentTypes['ReportingRuleNameExistsError'] = + GQLResolversParentTypes['ReportingRuleNameExistsError'], > = { detail?: Resolver< Maybe, @@ -12446,8 +12493,8 @@ export type GQLReportingRuleNameExistsErrorResolvers< export type GQLReportingRulePassRateDataResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ReportingRulePassRateData'] = GQLResolversParentTypes['ReportingRulePassRateData'], + ParentType extends GQLResolversParentTypes['ReportingRulePassRateData'] = + GQLResolversParentTypes['ReportingRulePassRateData'], > = { date?: Resolver; totalMatches?: Resolver; @@ -12456,8 +12503,8 @@ export type GQLReportingRulePassRateDataResolvers< export type GQLResolvedJobCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ResolvedJobCount'] = GQLResolversParentTypes['ResolvedJobCount'], + ParentType extends GQLResolversParentTypes['ResolvedJobCount'] = + GQLResolversParentTypes['ResolvedJobCount'], > = { count?: Resolver; queueId?: Resolver< @@ -12475,8 +12522,8 @@ export type GQLResolvedJobCountResolvers< export type GQLRotateApiKeyErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RotateApiKeyError'] = GQLResolversParentTypes['RotateApiKeyError'], + ParentType extends GQLResolversParentTypes['RotateApiKeyError'] = + GQLResolversParentTypes['RotateApiKeyError'], > = { detail?: Resolver< Maybe, @@ -12505,8 +12552,8 @@ export type GQLRotateApiKeyErrorResolvers< export type GQLRotateApiKeyResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RotateApiKeyResponse'] = GQLResolversParentTypes['RotateApiKeyResponse'], + ParentType extends GQLResolversParentTypes['RotateApiKeyResponse'] = + GQLResolversParentTypes['RotateApiKeyResponse'], > = { __resolveType: TypeResolveFn< 'RotateApiKeyError' | 'RotateApiKeySuccessResponse', @@ -12517,8 +12564,8 @@ export type GQLRotateApiKeyResponseResolvers< export type GQLRotateApiKeySuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RotateApiKeySuccessResponse'] = GQLResolversParentTypes['RotateApiKeySuccessResponse'], + ParentType extends GQLResolversParentTypes['RotateApiKeySuccessResponse'] = + GQLResolversParentTypes['RotateApiKeySuccessResponse'], > = { apiKey?: Resolver; record?: Resolver; @@ -12527,8 +12574,8 @@ export type GQLRotateApiKeySuccessResponseResolvers< export type GQLRotateWebhookSigningKeyErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RotateWebhookSigningKeyError'] = GQLResolversParentTypes['RotateWebhookSigningKeyError'], + ParentType extends GQLResolversParentTypes['RotateWebhookSigningKeyError'] = + GQLResolversParentTypes['RotateWebhookSigningKeyError'], > = { detail?: Resolver< Maybe, @@ -12558,7 +12605,8 @@ export type GQLRotateWebhookSigningKeyErrorResolvers< export type GQLRotateWebhookSigningKeyResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['RotateWebhookSigningKeyResponse'] = GQLResolversParentTypes['RotateWebhookSigningKeyResponse'], + GQLResolversParentTypes['RotateWebhookSigningKeyResponse'] = + GQLResolversParentTypes['RotateWebhookSigningKeyResponse'], > = { __resolveType: TypeResolveFn< 'RotateWebhookSigningKeyError' | 'RotateWebhookSigningKeySuccessResponse', @@ -12570,7 +12618,8 @@ export type GQLRotateWebhookSigningKeyResponseResolvers< export type GQLRotateWebhookSigningKeySuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['RotateWebhookSigningKeySuccessResponse'] = GQLResolversParentTypes['RotateWebhookSigningKeySuccessResponse'], + GQLResolversParentTypes['RotateWebhookSigningKeySuccessResponse'] = + GQLResolversParentTypes['RotateWebhookSigningKeySuccessResponse'], > = { publicSigningKey?: Resolver< GQLResolversTypes['String'], @@ -12582,8 +12631,8 @@ export type GQLRotateWebhookSigningKeySuccessResponseResolvers< export type GQLRoutingRuleResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RoutingRule'] = GQLResolversParentTypes['RoutingRule'], + ParentType extends GQLResolversParentTypes['RoutingRule'] = + GQLResolversParentTypes['RoutingRule'], > = { conditionSet?: Resolver< GQLResolversTypes['ConditionSet'], @@ -12617,8 +12666,8 @@ export type GQLRoutingRuleResolvers< export type GQLRoutingRuleNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RoutingRuleNameExistsError'] = GQLResolversParentTypes['RoutingRuleNameExistsError'], + ParentType extends GQLResolversParentTypes['RoutingRuleNameExistsError'] = + GQLResolversParentTypes['RoutingRuleNameExistsError'], > = { detail?: Resolver< Maybe, @@ -12647,8 +12696,8 @@ export type GQLRoutingRuleNameExistsErrorResolvers< export type GQLRuleResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Rule'] = GQLResolversParentTypes['Rule'], + ParentType extends GQLResolversParentTypes['Rule'] = + GQLResolversParentTypes['Rule'], > = { __resolveType: TypeResolveFn< 'ContentRule' | 'UserRule', @@ -12659,8 +12708,8 @@ export type GQLRuleResolvers< export type GQLRuleExecutionEnqueueSourceInfoResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleExecutionEnqueueSourceInfo'] = GQLResolversParentTypes['RuleExecutionEnqueueSourceInfo'], + ParentType extends GQLResolversParentTypes['RuleExecutionEnqueueSourceInfo'] = + GQLResolversParentTypes['RuleExecutionEnqueueSourceInfo'], > = { kind?: Resolver< GQLResolversTypes['JobCreationSourceOptions'], @@ -12677,8 +12726,8 @@ export type GQLRuleExecutionEnqueueSourceInfoResolvers< export type GQLRuleExecutionResultResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleExecutionResult'] = GQLResolversParentTypes['RuleExecutionResult'], + ParentType extends GQLResolversParentTypes['RuleExecutionResult'] = + GQLResolversParentTypes['RuleExecutionResult'], > = { content?: Resolver; contentId?: Resolver; @@ -12729,8 +12778,8 @@ export type GQLRuleExecutionResultResolvers< export type GQLRuleExecutionResultEdgeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleExecutionResultEdge'] = GQLResolversParentTypes['RuleExecutionResultEdge'], + ParentType extends GQLResolversParentTypes['RuleExecutionResultEdge'] = + GQLResolversParentTypes['RuleExecutionResultEdge'], > = { cursor?: Resolver; node?: Resolver< @@ -12742,8 +12791,8 @@ export type GQLRuleExecutionResultEdgeResolvers< export type GQLRuleExecutionResultsConnectionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleExecutionResultsConnection'] = GQLResolversParentTypes['RuleExecutionResultsConnection'], + ParentType extends GQLResolversParentTypes['RuleExecutionResultsConnection'] = + GQLResolversParentTypes['RuleExecutionResultsConnection'], > = { edges?: Resolver< ReadonlyArray, @@ -12755,8 +12804,8 @@ export type GQLRuleExecutionResultsConnectionResolvers< export type GQLRuleHasRunningBacktestsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleHasRunningBacktestsError'] = GQLResolversParentTypes['RuleHasRunningBacktestsError'], + ParentType extends GQLResolversParentTypes['RuleHasRunningBacktestsError'] = + GQLResolversParentTypes['RuleHasRunningBacktestsError'], > = { detail?: Resolver< Maybe, @@ -12785,8 +12834,8 @@ export type GQLRuleHasRunningBacktestsErrorResolvers< export type GQLRuleInsightsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleInsights'] = GQLResolversParentTypes['RuleInsights'], + ParentType extends GQLResolversParentTypes['RuleInsights'] = + GQLResolversParentTypes['RuleInsights'], > = { latestVersionSamples?: Resolver< ReadonlyArray, @@ -12808,8 +12857,8 @@ export type GQLRuleInsightsResolvers< export type GQLRuleNameExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RuleNameExistsError'] = GQLResolversParentTypes['RuleNameExistsError'], + ParentType extends GQLResolversParentTypes['RuleNameExistsError'] = + GQLResolversParentTypes['RuleNameExistsError'], > = { detail?: Resolver< Maybe, @@ -12838,8 +12887,8 @@ export type GQLRuleNameExistsErrorResolvers< export type GQLRulePassRateDataResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RulePassRateData'] = GQLResolversParentTypes['RulePassRateData'], + ParentType extends GQLResolversParentTypes['RulePassRateData'] = + GQLResolversParentTypes['RulePassRateData'], > = { date?: Resolver; totalMatches?: Resolver; @@ -12848,8 +12897,8 @@ export type GQLRulePassRateDataResolvers< export type GQLRunRetroactionResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RunRetroactionResponse'] = GQLResolversParentTypes['RunRetroactionResponse'], + ParentType extends GQLResolversParentTypes['RunRetroactionResponse'] = + GQLResolversParentTypes['RunRetroactionResponse'], > = { __resolveType: TypeResolveFn< 'RunRetroactionSuccessResponse', @@ -12860,8 +12909,8 @@ export type GQLRunRetroactionResponseResolvers< export type GQLRunRetroactionSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['RunRetroactionSuccessResponse'] = GQLResolversParentTypes['RunRetroactionSuccessResponse'], + ParentType extends GQLResolversParentTypes['RunRetroactionSuccessResponse'] = + GQLResolversParentTypes['RunRetroactionSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -12869,8 +12918,8 @@ export type GQLRunRetroactionSuccessResponseResolvers< export type GQLScalarSignalOutputTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ScalarSignalOutputType'] = GQLResolversParentTypes['ScalarSignalOutputType'], + ParentType extends GQLResolversParentTypes['ScalarSignalOutputType'] = + GQLResolversParentTypes['ScalarSignalOutputType'], > = { scalarType?: Resolver< GQLResolversTypes['ScalarType'], @@ -12882,8 +12931,8 @@ export type GQLScalarSignalOutputTypeResolvers< export type GQLSchemaFieldRolesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SchemaFieldRoles'] = GQLResolversParentTypes['SchemaFieldRoles'], + ParentType extends GQLResolversParentTypes['SchemaFieldRoles'] = + GQLResolversParentTypes['SchemaFieldRoles'], > = { __resolveType: TypeResolveFn< | 'ContentSchemaFieldRoles' @@ -12897,15 +12946,16 @@ export type GQLSchemaFieldRolesResolvers< export type GQLSetAllUserStrikeThresholdsSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['SetAllUserStrikeThresholdsSuccessResponse'] = GQLResolversParentTypes['SetAllUserStrikeThresholdsSuccessResponse'], + GQLResolversParentTypes['SetAllUserStrikeThresholdsSuccessResponse'] = + GQLResolversParentTypes['SetAllUserStrikeThresholdsSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; export type GQLSetIntegrationConfigResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SetIntegrationConfigResponse'] = GQLResolversParentTypes['SetIntegrationConfigResponse'], + ParentType extends GQLResolversParentTypes['SetIntegrationConfigResponse'] = + GQLResolversParentTypes['SetIntegrationConfigResponse'], > = { __resolveType: TypeResolveFn< | 'IntegrationConfigTooManyCredentialsError' @@ -12920,7 +12970,8 @@ export type GQLSetIntegrationConfigResponseResolvers< export type GQLSetIntegrationConfigSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['SetIntegrationConfigSuccessResponse'] = GQLResolversParentTypes['SetIntegrationConfigSuccessResponse'], + GQLResolversParentTypes['SetIntegrationConfigSuccessResponse'] = + GQLResolversParentTypes['SetIntegrationConfigSuccessResponse'], > = { config?: Resolver< GQLResolversTypes['IntegrationConfig'], @@ -12933,7 +12984,8 @@ export type GQLSetIntegrationConfigSuccessResponseResolvers< export type GQLSetModeratorSafetySettingsSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['SetModeratorSafetySettingsSuccessResponse'] = GQLResolversParentTypes['SetModeratorSafetySettingsSuccessResponse'], + GQLResolversParentTypes['SetModeratorSafetySettingsSuccessResponse'] = + GQLResolversParentTypes['SetModeratorSafetySettingsSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; @@ -12941,15 +12993,16 @@ export type GQLSetModeratorSafetySettingsSuccessResponseResolvers< export type GQLSetMrtChartConfigurationSettingsSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['SetMrtChartConfigurationSettingsSuccessResponse'] = GQLResolversParentTypes['SetMrtChartConfigurationSettingsSuccessResponse'], + GQLResolversParentTypes['SetMrtChartConfigurationSettingsSuccessResponse'] = + GQLResolversParentTypes['SetMrtChartConfigurationSettingsSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; export type GQLSignUpResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignUpResponse'] = GQLResolversParentTypes['SignUpResponse'], + ParentType extends GQLResolversParentTypes['SignUpResponse'] = + GQLResolversParentTypes['SignUpResponse'], > = { __resolveType: TypeResolveFn< 'SignUpSuccessResponse' | 'SignUpUserExistsError', @@ -12960,8 +13013,8 @@ export type GQLSignUpResponseResolvers< export type GQLSignUpSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignUpSuccessResponse'] = GQLResolversParentTypes['SignUpSuccessResponse'], + ParentType extends GQLResolversParentTypes['SignUpSuccessResponse'] = + GQLResolversParentTypes['SignUpSuccessResponse'], > = { data?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -12969,8 +13022,8 @@ export type GQLSignUpSuccessResponseResolvers< export type GQLSignUpUserExistsErrorResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignUpUserExistsError'] = GQLResolversParentTypes['SignUpUserExistsError'], + ParentType extends GQLResolversParentTypes['SignUpUserExistsError'] = + GQLResolversParentTypes['SignUpUserExistsError'], > = { detail?: Resolver< Maybe, @@ -12999,8 +13052,8 @@ export type GQLSignUpUserExistsErrorResolvers< export type GQLSignalResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['Signal'] = GQLResolversParentTypes['Signal'], + ParentType extends GQLResolversParentTypes['Signal'] = + GQLResolversParentTypes['Signal'], > = { allowedInAutomatedRules?: Resolver< GQLResolversTypes['Boolean'], @@ -13105,8 +13158,8 @@ export type GQLSignalResolvers< export type GQLSignalArgsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignalArgs'] = GQLResolversParentTypes['SignalArgs'], + ParentType extends GQLResolversParentTypes['SignalArgs'] = + GQLResolversParentTypes['SignalArgs'], > = { __resolveType: TypeResolveFn< 'AggregationSignalArgs', @@ -13117,8 +13170,8 @@ export type GQLSignalArgsResolvers< export type GQLSignalOutputTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignalOutputType'] = GQLResolversParentTypes['SignalOutputType'], + ParentType extends GQLResolversParentTypes['SignalOutputType'] = + GQLResolversParentTypes['SignalOutputType'], > = { __resolveType: TypeResolveFn< 'EnumSignalOutputType' | 'ScalarSignalOutputType', @@ -13129,8 +13182,8 @@ export type GQLSignalOutputTypeResolvers< export type GQLSignalPricingStructureResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignalPricingStructure'] = GQLResolversParentTypes['SignalPricingStructure'], + ParentType extends GQLResolversParentTypes['SignalPricingStructure'] = + GQLResolversParentTypes['SignalPricingStructure'], > = { type?: Resolver< GQLResolversTypes['SignalPricingStructureType'], @@ -13141,8 +13194,8 @@ export type GQLSignalPricingStructureResolvers< export type GQLSignalSubcategoryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignalSubcategory'] = GQLResolversParentTypes['SignalSubcategory'], + ParentType extends GQLResolversParentTypes['SignalSubcategory'] = + GQLResolversParentTypes['SignalSubcategory'], > = { childrenIds?: Resolver< ReadonlyArray, @@ -13160,8 +13213,8 @@ export type GQLSignalSubcategoryResolvers< export type GQLSignalWithScoreResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SignalWithScore'] = GQLResolversParentTypes['SignalWithScore'], + ParentType extends GQLResolversParentTypes['SignalWithScore'] = + GQLResolversParentTypes['SignalWithScore'], > = { integration?: Resolver< Maybe, @@ -13179,8 +13232,8 @@ export type GQLSignalWithScoreResolvers< export type GQLSkippedJobResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SkippedJob'] = GQLResolversParentTypes['SkippedJob'], + ParentType extends GQLResolversParentTypes['SkippedJob'] = + GQLResolversParentTypes['SkippedJob'], > = { jobId?: Resolver; queueId?: Resolver; @@ -13190,8 +13243,8 @@ export type GQLSkippedJobResolvers< export type GQLSkippedJobCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SkippedJobCount'] = GQLResolversParentTypes['SkippedJobCount'], + ParentType extends GQLResolversParentTypes['SkippedJobCount'] = + GQLResolversParentTypes['SkippedJobCount'], > = { count?: Resolver; queueId?: Resolver< @@ -13207,15 +13260,17 @@ export type GQLSkippedJobCountResolvers< time?: Resolver; }; -export interface GQLStringOrFloatScalarConfig - extends GraphQLScalarTypeConfig { +export interface GQLStringOrFloatScalarConfig extends GraphQLScalarTypeConfig< + GQLResolversTypes['StringOrFloat'], + any +> { name: 'StringOrFloat'; } export type GQLSubmitDecisionResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SubmitDecisionResponse'] = GQLResolversParentTypes['SubmitDecisionResponse'], + ParentType extends GQLResolversParentTypes['SubmitDecisionResponse'] = + GQLResolversParentTypes['SubmitDecisionResponse'], > = { __resolveType: TypeResolveFn< | 'JobHasAlreadyBeenSubmittedError' @@ -13230,8 +13285,8 @@ export type GQLSubmitDecisionResponseResolvers< export type GQLSubmitDecisionSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SubmitDecisionSuccessResponse'] = GQLResolversParentTypes['SubmitDecisionSuccessResponse'], + ParentType extends GQLResolversParentTypes['SubmitDecisionSuccessResponse'] = + GQLResolversParentTypes['SubmitDecisionSuccessResponse'], > = { success?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -13240,7 +13295,8 @@ export type GQLSubmitDecisionSuccessResponseResolvers< export type GQLSubmitNcmecReportDecisionComponentResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['SubmitNCMECReportDecisionComponent'] = GQLResolversParentTypes['SubmitNCMECReportDecisionComponent'], + GQLResolversParentTypes['SubmitNCMECReportDecisionComponent'] = + GQLResolversParentTypes['SubmitNCMECReportDecisionComponent'], > = { reportedMedia?: Resolver< ReadonlyArray, @@ -13258,7 +13314,8 @@ export type GQLSubmitNcmecReportDecisionComponentResolvers< export type GQLSubmittedJobActionNotFoundErrorResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['SubmittedJobActionNotFoundError'] = GQLResolversParentTypes['SubmittedJobActionNotFoundError'], + GQLResolversParentTypes['SubmittedJobActionNotFoundError'] = + GQLResolversParentTypes['SubmittedJobActionNotFoundError'], > = { detail?: Resolver< Maybe, @@ -13287,8 +13344,8 @@ export type GQLSubmittedJobActionNotFoundErrorResolvers< export type GQLSupportedLanguagesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['SupportedLanguages'] = GQLResolversParentTypes['SupportedLanguages'], + ParentType extends GQLResolversParentTypes['SupportedLanguages'] = + GQLResolversParentTypes['SupportedLanguages'], > = { __resolveType: TypeResolveFn< 'AllLanguages' | 'Languages', @@ -13299,8 +13356,8 @@ export type GQLSupportedLanguagesResolvers< export type GQLTableDecisionCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['TableDecisionCount'] = GQLResolversParentTypes['TableDecisionCount'], + ParentType extends GQLResolversParentTypes['TableDecisionCount'] = + GQLResolversParentTypes['TableDecisionCount'], > = { action_id?: Resolver< Maybe, @@ -13327,8 +13384,8 @@ export type GQLTableDecisionCountResolvers< export type GQLTextBankResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['TextBank'] = GQLResolversParentTypes['TextBank'], + ParentType extends GQLResolversParentTypes['TextBank'] = + GQLResolversParentTypes['TextBank'], > = { description?: Resolver< Maybe, @@ -13348,7 +13405,8 @@ export type GQLTextBankResolvers< export type GQLThreadAppealManualReviewJobPayloadResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['ThreadAppealManualReviewJobPayload'] = GQLResolversParentTypes['ThreadAppealManualReviewJobPayload'], + GQLResolversParentTypes['ThreadAppealManualReviewJobPayload'] = + GQLResolversParentTypes['ThreadAppealManualReviewJobPayload'], > = { actionsTaken?: Resolver< ReadonlyArray, @@ -13377,8 +13435,8 @@ export type GQLThreadAppealManualReviewJobPayloadResolvers< export type GQLThreadItemResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ThreadItem'] = GQLResolversParentTypes['ThreadItem'], + ParentType extends GQLResolversParentTypes['ThreadItem'] = + GQLResolversParentTypes['ThreadItem'], > = { data?: Resolver; id?: Resolver; @@ -13394,8 +13452,8 @@ export type GQLThreadItemResolvers< export type GQLThreadItemTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ThreadItemType'] = GQLResolversParentTypes['ThreadItemType'], + ParentType extends GQLResolversParentTypes['ThreadItemType'] = + GQLResolversParentTypes['ThreadItemType'], > = { baseFields?: Resolver< ReadonlyArray, @@ -13435,8 +13493,8 @@ export type GQLThreadItemTypeResolvers< export type GQLThreadManualReviewJobPayloadResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ThreadManualReviewJobPayload'] = GQLResolversParentTypes['ThreadManualReviewJobPayload'], + ParentType extends GQLResolversParentTypes['ThreadManualReviewJobPayload'] = + GQLResolversParentTypes['ThreadManualReviewJobPayload'], > = { enqueueSourceInfo?: Resolver< Maybe, @@ -13469,8 +13527,8 @@ export type GQLThreadManualReviewJobPayloadResolvers< export type GQLThreadSchemaFieldRolesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ThreadSchemaFieldRoles'] = GQLResolversParentTypes['ThreadSchemaFieldRoles'], + ParentType extends GQLResolversParentTypes['ThreadSchemaFieldRoles'] = + GQLResolversParentTypes['ThreadSchemaFieldRoles'], > = { createdAt?: Resolver< Maybe, @@ -13497,8 +13555,8 @@ export type GQLThreadSchemaFieldRolesResolvers< export type GQLThreadWithMessagesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ThreadWithMessages'] = GQLResolversParentTypes['ThreadWithMessages'], + ParentType extends GQLResolversParentTypes['ThreadWithMessages'] = + GQLResolversParentTypes['ThreadWithMessages'], > = { messages?: Resolver< ReadonlyArray, @@ -13511,8 +13569,8 @@ export type GQLThreadWithMessagesResolvers< export type GQLThreadWithMessagesAndIpAddressResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ThreadWithMessagesAndIpAddress'] = GQLResolversParentTypes['ThreadWithMessagesAndIpAddress'], + ParentType extends GQLResolversParentTypes['ThreadWithMessagesAndIpAddress'] = + GQLResolversParentTypes['ThreadWithMessagesAndIpAddress'], > = { messages?: Resolver< ReadonlyArray, @@ -13525,8 +13583,8 @@ export type GQLThreadWithMessagesAndIpAddressResolvers< export type GQLTimeToActionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['TimeToAction'] = GQLResolversParentTypes['TimeToAction'], + ParentType extends GQLResolversParentTypes['TimeToAction'] = + GQLResolversParentTypes['TimeToAction'], > = { itemTypeId?: Resolver< Maybe, @@ -13548,7 +13606,8 @@ export type GQLTimeToActionResolvers< export type GQLTransformJobAndRecreateInQueueDecisionComponentResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['TransformJobAndRecreateInQueueDecisionComponent'] = GQLResolversParentTypes['TransformJobAndRecreateInQueueDecisionComponent'], + GQLResolversParentTypes['TransformJobAndRecreateInQueueDecisionComponent'] = + GQLResolversParentTypes['TransformJobAndRecreateInQueueDecisionComponent'], > = { newJobKind?: Resolver< GQLResolversTypes['ManualReviewJobKind'], @@ -13580,8 +13639,8 @@ export type GQLTransformJobAndRecreateInQueueDecisionComponentResolvers< export type GQLUpdateContentRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdateContentRuleResponse'] = GQLResolversParentTypes['UpdateContentRuleResponse'], + ParentType extends GQLResolversParentTypes['UpdateContentRuleResponse'] = + GQLResolversParentTypes['UpdateContentRuleResponse'], > = { __resolveType: TypeResolveFn< | 'MutateContentRuleSuccessResponse' @@ -13596,7 +13655,8 @@ export type GQLUpdateContentRuleResponseResolvers< export type GQLUpdateManualReviewQueueQueueResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['UpdateManualReviewQueueQueueResponse'] = GQLResolversParentTypes['UpdateManualReviewQueueQueueResponse'], + GQLResolversParentTypes['UpdateManualReviewQueueQueueResponse'] = + GQLResolversParentTypes['UpdateManualReviewQueueQueueResponse'], > = { __resolveType: TypeResolveFn< | 'ManualReviewQueueNameExistsError' @@ -13609,24 +13669,24 @@ export type GQLUpdateManualReviewQueueQueueResponseResolvers< export type GQLUpdateNcmecOrgSettingsResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdateNcmecOrgSettingsResponse'] = GQLResolversParentTypes['UpdateNcmecOrgSettingsResponse'], + ParentType extends GQLResolversParentTypes['UpdateNcmecOrgSettingsResponse'] = + GQLResolversParentTypes['UpdateNcmecOrgSettingsResponse'], > = { success?: Resolver; }; export type GQLUpdateOrgInfoSuccessResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdateOrgInfoSuccessResponse'] = GQLResolversParentTypes['UpdateOrgInfoSuccessResponse'], + ParentType extends GQLResolversParentTypes['UpdateOrgInfoSuccessResponse'] = + GQLResolversParentTypes['UpdateOrgInfoSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; export type GQLUpdatePolicyResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdatePolicyResponse'] = GQLResolversParentTypes['UpdatePolicyResponse'], + ParentType extends GQLResolversParentTypes['UpdatePolicyResponse'] = + GQLResolversParentTypes['UpdatePolicyResponse'], > = { __resolveType: TypeResolveFn< 'NotFoundError' | 'Policy', @@ -13637,8 +13697,8 @@ export type GQLUpdatePolicyResponseResolvers< export type GQLUpdateReportingRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdateReportingRuleResponse'] = GQLResolversParentTypes['UpdateReportingRuleResponse'], + ParentType extends GQLResolversParentTypes['UpdateReportingRuleResponse'] = + GQLResolversParentTypes['UpdateReportingRuleResponse'], > = { __resolveType: TypeResolveFn< | 'MutateReportingRuleSuccessResponse' @@ -13651,8 +13711,8 @@ export type GQLUpdateReportingRuleResponseResolvers< export type GQLUpdateRoutingRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdateRoutingRuleResponse'] = GQLResolversParentTypes['UpdateRoutingRuleResponse'], + ParentType extends GQLResolversParentTypes['UpdateRoutingRuleResponse'] = + GQLResolversParentTypes['UpdateRoutingRuleResponse'], > = { __resolveType: TypeResolveFn< | 'MutateRoutingRuleSuccessResponse' @@ -13666,8 +13726,8 @@ export type GQLUpdateRoutingRuleResponseResolvers< export type GQLUpdateUserRuleResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UpdateUserRuleResponse'] = GQLResolversParentTypes['UpdateUserRuleResponse'], + ParentType extends GQLResolversParentTypes['UpdateUserRuleResponse'] = + GQLResolversParentTypes['UpdateUserRuleResponse'], > = { __resolveType: TypeResolveFn< | 'MutateUserRuleSuccessResponse' @@ -13682,15 +13742,16 @@ export type GQLUpdateUserRuleResponseResolvers< export type GQLUpdateUserStrikeTtlSuccessResponseResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['UpdateUserStrikeTTLSuccessResponse'] = GQLResolversParentTypes['UpdateUserStrikeTTLSuccessResponse'], + GQLResolversParentTypes['UpdateUserStrikeTTLSuccessResponse'] = + GQLResolversParentTypes['UpdateUserStrikeTTLSuccessResponse'], > = { _?: Resolver, ParentType, ContextType>; }; export type GQLUserResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['User'] = GQLResolversParentTypes['User'], + ParentType extends GQLResolversParentTypes['User'] = + GQLResolversParentTypes['User'], > = { approvedByAdmin?: Resolver< Maybe, @@ -13758,8 +13819,8 @@ export type GQLUserResolvers< export type GQLUserActionsHistoryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserActionsHistory'] = GQLResolversParentTypes['UserActionsHistory'], + ParentType extends GQLResolversParentTypes['UserActionsHistory'] = + GQLResolversParentTypes['UserActionsHistory'], > = { countsByPolicy?: Resolver< ReadonlyArray, @@ -13771,7 +13832,8 @@ export type GQLUserActionsHistoryResolvers< export type GQLUserAppealManualReviewJobPayloadResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['UserAppealManualReviewJobPayload'] = GQLResolversParentTypes['UserAppealManualReviewJobPayload'], + GQLResolversParentTypes['UserAppealManualReviewJobPayload'] = + GQLResolversParentTypes['UserAppealManualReviewJobPayload'], > = { actionsTaken?: Resolver< ReadonlyArray, @@ -13815,8 +13877,8 @@ export type GQLUserAppealManualReviewJobPayloadResolvers< export type GQLUserHistoryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserHistory'] = GQLResolversParentTypes['UserHistory'], + ParentType extends GQLResolversParentTypes['UserHistory'] = + GQLResolversParentTypes['UserHistory'], > = { actions?: Resolver< GQLResolversTypes['UserActionsHistory'], @@ -13844,8 +13906,8 @@ export type GQLUserHistoryResolvers< export type GQLUserHistoryResponseResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserHistoryResponse'] = GQLResolversParentTypes['UserHistoryResponse'], + ParentType extends GQLResolversParentTypes['UserHistoryResponse'] = + GQLResolversParentTypes['UserHistoryResponse'], > = { __resolveType: TypeResolveFn< 'NotFoundError' | 'UserHistory', @@ -13856,8 +13918,8 @@ export type GQLUserHistoryResponseResolvers< export type GQLUserInterfacePreferencesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserInterfacePreferences'] = GQLResolversParentTypes['UserInterfacePreferences'], + ParentType extends GQLResolversParentTypes['UserInterfacePreferences'] = + GQLResolversParentTypes['UserInterfacePreferences'], > = { moderatorSafetyBlurLevel?: Resolver< GQLResolversTypes['Int'], @@ -13883,8 +13945,8 @@ export type GQLUserInterfacePreferencesResolvers< export type GQLUserItemResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserItem'] = GQLResolversParentTypes['UserItem'], + ParentType extends GQLResolversParentTypes['UserItem'] = + GQLResolversParentTypes['UserItem'], > = { data?: Resolver; id?: Resolver; @@ -13901,8 +13963,8 @@ export type GQLUserItemResolvers< export type GQLUserItemTypeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserItemType'] = GQLResolversParentTypes['UserItemType'], + ParentType extends GQLResolversParentTypes['UserItemType'] = + GQLResolversParentTypes['UserItemType'], > = { baseFields?: Resolver< ReadonlyArray, @@ -13947,8 +14009,8 @@ export type GQLUserItemTypeResolvers< export type GQLUserManualReviewJobPayloadResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserManualReviewJobPayload'] = GQLResolversParentTypes['UserManualReviewJobPayload'], + ParentType extends GQLResolversParentTypes['UserManualReviewJobPayload'] = + GQLResolversParentTypes['UserManualReviewJobPayload'], > = { additionalContentItems?: Resolver< ReadonlyArray, @@ -13996,16 +14058,16 @@ export type GQLUserManualReviewJobPayloadResolvers< export type GQLUserNotificationEdgeResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserNotificationEdge'] = GQLResolversParentTypes['UserNotificationEdge'], + ParentType extends GQLResolversParentTypes['UserNotificationEdge'] = + GQLResolversParentTypes['UserNotificationEdge'], > = { node?: Resolver; }; export type GQLUserNotificationsResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserNotifications'] = GQLResolversParentTypes['UserNotifications'], + ParentType extends GQLResolversParentTypes['UserNotifications'] = + GQLResolversParentTypes['UserNotifications'], > = { edges?: Resolver< ReadonlyArray, @@ -14017,7 +14079,8 @@ export type GQLUserNotificationsResolvers< export type GQLUserOrRelatedActionDecisionComponentResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['UserOrRelatedActionDecisionComponent'] = GQLResolversParentTypes['UserOrRelatedActionDecisionComponent'], + GQLResolversParentTypes['UserOrRelatedActionDecisionComponent'] = + GQLResolversParentTypes['UserOrRelatedActionDecisionComponent'], > = { actionIds?: Resolver< ReadonlyArray, @@ -14050,8 +14113,8 @@ export type GQLUserOrRelatedActionDecisionComponentResolvers< export type GQLUserRuleResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserRule'] = GQLResolversParentTypes['UserRule'], + ParentType extends GQLResolversParentTypes['UserRule'] = + GQLResolversParentTypes['UserRule'], > = { actions?: Resolver< ReadonlyArray, @@ -14111,8 +14174,8 @@ export type GQLUserRuleResolvers< export type GQLUserSchemaFieldRolesResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserSchemaFieldRoles'] = GQLResolversParentTypes['UserSchemaFieldRoles'], + ParentType extends GQLResolversParentTypes['UserSchemaFieldRoles'] = + GQLResolversParentTypes['UserSchemaFieldRoles'], > = { backgroundImage?: Resolver< Maybe, @@ -14144,8 +14207,8 @@ export type GQLUserSchemaFieldRolesResolvers< export type GQLUserStrikeBucketResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserStrikeBucket'] = GQLResolversParentTypes['UserStrikeBucket'], + ParentType extends GQLResolversParentTypes['UserStrikeBucket'] = + GQLResolversParentTypes['UserStrikeBucket'], > = { numStrikes?: Resolver; numUsers?: Resolver; @@ -14153,8 +14216,8 @@ export type GQLUserStrikeBucketResolvers< export type GQLUserStrikeThresholdResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserStrikeThreshold'] = GQLResolversParentTypes['UserStrikeThreshold'], + ParentType extends GQLResolversParentTypes['UserStrikeThreshold'] = + GQLResolversParentTypes['UserStrikeThreshold'], > = { actions?: Resolver< ReadonlyArray, @@ -14167,8 +14230,8 @@ export type GQLUserStrikeThresholdResolvers< export type GQLUserSubmissionCountResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserSubmissionCount'] = GQLResolversParentTypes['UserSubmissionCount'], + ParentType extends GQLResolversParentTypes['UserSubmissionCount'] = + GQLResolversParentTypes['UserSubmissionCount'], > = { count?: Resolver; itemTypeId?: Resolver; @@ -14176,8 +14239,8 @@ export type GQLUserSubmissionCountResolvers< export type GQLUserSubmissionsHistoryResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['UserSubmissionsHistory'] = GQLResolversParentTypes['UserSubmissionsHistory'], + ParentType extends GQLResolversParentTypes['UserSubmissionsHistory'] = + GQLResolversParentTypes['UserSubmissionsHistory'], > = { countsByItemType?: Resolver< ReadonlyArray, @@ -14188,8 +14251,8 @@ export type GQLUserSubmissionsHistoryResolvers< export type GQLWindowConfigurationResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['WindowConfiguration'] = GQLResolversParentTypes['WindowConfiguration'], + ParentType extends GQLResolversParentTypes['WindowConfiguration'] = + GQLResolversParentTypes['WindowConfiguration'], > = { hopMs?: Resolver; sizeMs?: Resolver; @@ -14198,7 +14261,8 @@ export type GQLWindowConfigurationResolvers< export type GQLZentropiIntegrationApiCredentialResolvers< ContextType = Context, ParentType extends - GQLResolversParentTypes['ZentropiIntegrationApiCredential'] = GQLResolversParentTypes['ZentropiIntegrationApiCredential'], + GQLResolversParentTypes['ZentropiIntegrationApiCredential'] = + GQLResolversParentTypes['ZentropiIntegrationApiCredential'], > = { apiKey?: Resolver; labelerVersions?: Resolver< @@ -14211,8 +14275,8 @@ export type GQLZentropiIntegrationApiCredentialResolvers< export type GQLZentropiLabelerVersionResolvers< ContextType = Context, - ParentType extends - GQLResolversParentTypes['ZentropiLabelerVersion'] = GQLResolversParentTypes['ZentropiLabelerVersion'], + ParentType extends GQLResolversParentTypes['ZentropiLabelerVersion'] = + GQLResolversParentTypes['ZentropiLabelerVersion'], > = { id?: Resolver; label?: Resolver; diff --git a/server/graphql/resolvers.ts b/server/graphql/resolvers.ts index 4ce59e2..656e5a2 100644 --- a/server/graphql/resolvers.ts +++ b/server/graphql/resolvers.ts @@ -4,7 +4,7 @@ import { type PassportContext } from 'graphql-passport'; import { type GQLServices } from '../api.js'; import { type DataSources } from '../iocContainer/index.js'; -import { type User } from '../models/UserModel.js'; +import { type GraphQLUserParent } from './datasources/userKyselyPersistence.js'; import { CoopError, isCoopErrorOfType } from '../utils/errors.js'; import { type GQLInviteUserToken, @@ -41,7 +41,7 @@ import { gqlErrorResult, gqlSuccessResult } from './utils/gqlResult.js'; import { forbiddenError, unauthenticatedError } from './utils/errors.js'; // eslint-disable-next-line @typescript-eslint/no-restricted-types -export type Context = PassportContext & { +export type Context = PassportContext & { dataSources: DataSources; services: GQLServices; }; @@ -124,7 +124,7 @@ const Query: GQLQueryResolvers = { }, }; -type TSignUpResponse = { data: User } | CoopError; +type TSignUpResponse = { data: GraphQLUserParent } | CoopError; const SignUpResponse: ResolverMap = { __resolveType(response) { if (response instanceof CoopError) { diff --git a/server/models/rules/ruleTypes.ts b/server/models/rules/ruleTypes.ts index 9315ec5..53a4475 100644 --- a/server/models/rules/ruleTypes.ts +++ b/server/models/rules/ruleTypes.ts @@ -6,7 +6,7 @@ import { type Action, type Policy, } from '../../services/moderationConfigService/index.js'; -import { type User } from '../UserModel.js'; +import { type GraphQLUserParent } from '../../graphql/datasources/userKyselyPersistence.js'; export type RuleLatestVersionRow = { ruleId: string; @@ -50,7 +50,7 @@ export function computeRuleStatusFromRow( } export type RuleGraphqlMethods = { - getCreator(): Promise; + getCreator(): Promise; getActions(): Promise; getPolicies(): Promise; }; diff --git a/server/services/coreAppTables.ts b/server/services/coreAppTables.ts index 80e0ab1..a36294f 100644 --- a/server/services/coreAppTables.ts +++ b/server/services/coreAppTables.ts @@ -1,8 +1,13 @@ import { type Generated, type GeneratedAlways } from 'kysely'; +import { type UserRole } from '../models/types/permissioning.js'; + /** Postgres enum for backtests.status (generated column — read-only in app). */ export type BacktestStatusDb = 'RUNNING' | 'COMPLETE' | 'CANCELED'; +/** Postgres enum for users.login_methods. */ +export type LoginMethod = 'password' | 'saml'; + export type CoreAppTablesPg = { 'public.orgs': { id: string; @@ -14,6 +19,25 @@ export type CoreAppTablesPg = { updated_at: Date; on_call_alert_email: string | null; }; + // `id`, `created_at`, `updated_at` are all NOT NULL with no server-side + // default — the app supplies them on INSERT, just like the Sequelize model + // did. The DB enforces a CHECK constraint (`password_null_when_not_present`) + // tying `password IS NOT NULL` to `'password' ∈ login_methods`; that + // invariant is enforced at the app layer too (see `userValidation.ts`). + 'public.users': { + id: string; + email: string; + password: string | null; + first_name: string; + last_name: string; + role: UserRole; + approved_by_admin: boolean; + rejected_by_admin: boolean; + created_at: Date; + updated_at: Date; + org_id: string; + login_methods: LoginMethod[]; + }; 'public.location_banks': { id: string; name: string; diff --git a/server/services/userManagementService/dbTypes.ts b/server/services/userManagementService/dbTypes.ts index 90f0abc..ce93844 100644 --- a/server/services/userManagementService/dbTypes.ts +++ b/server/services/userManagementService/dbTypes.ts @@ -1,6 +1,7 @@ import type { ColumnType, GeneratedAlways } from 'kysely'; import type { UserRole } from '../../models/types/permissioning.js'; +import { type CoreAppTablesPg } from '../coreAppTables.js'; import type { DecisionCountsInput, JobCreationsInput, @@ -56,20 +57,9 @@ export type UserManagementPg = { org_id: string; created_at: Date; }; - 'public.users': { - id: GeneratedAlways; - email: string; - password: string | null; - first_name: string; - last_name: string; - role: UserRole; - approved_by_admin: boolean; - rejected_by_admin: boolean; - created_at: GeneratedAlways; - updated_at: GeneratedAlways; - org_id: string; - login_methods: ('password' | 'saml')[]; - }; + // Shared definition lives in `services/coreAppTables.ts` so Kysely instances + // typed on either `UserManagementPg` or `CombinedPg` see the same columns. + 'public.users': CoreAppTablesPg['public.users']; 'public.invite_user_tokens': { id: GeneratedAlways; token: string; diff --git a/server/services/userManagementService/index.ts b/server/services/userManagementService/index.ts index 40c214f..a37c59f 100644 --- a/server/services/userManagementService/index.ts +++ b/server/services/userManagementService/index.ts @@ -3,4 +3,4 @@ export { default as makeUserManagementService, type UserManagementService, } from './userManagementService.js'; -export { hashPassword } from './utils.js'; +export { hashPassword, passwordMatchesHash } from './utils.js'; diff --git a/server/services/userManagementService/utils.ts b/server/services/userManagementService/utils.ts index dd5cd34..4ca807d 100644 --- a/server/services/userManagementService/utils.ts +++ b/server/services/userManagementService/utils.ts @@ -1,5 +1,18 @@ +import { promisify } from 'util'; import bcrypt from 'bcryptjs'; export async function hashPassword(rawPassword: string) { return bcrypt.hash(rawPassword, 5); } + +// Matches the bcrypt.compare semantics used by the now-removed Sequelize +// `User.passwordMatchesHash` static; kept here so `UserApi.changePassword` and +// the Passport local strategy share a single implementation. +const bcryptCompare = promisify(bcrypt.compare); + +export async function passwordMatchesHash( + givenPassword: string, + hash: string, +): Promise { + return bcryptCompare(givenPassword, hash); +} -- 2.51.2