diff --git a/modules/authentication/src/Authentication.ts b/modules/authentication/src/Authentication.ts index 1fd96dc1c..3eecf4408 100644 --- a/modules/authentication/src/Authentication.ts +++ b/modules/authentication/src/Authentication.ts @@ -6,6 +6,7 @@ import { GrpcRequest, HealthCheckStatus, Indexable, + Query, } from '@conduitplatform/grpc-sdk'; import path from 'path'; import { isEmpty, isNil } from 'lodash-es'; @@ -788,10 +789,9 @@ export default class Authentication extends ManagedModule { try { const deletedToken = await Token.getInstance().deleteOne({ - // @ts-expect-error Unsafe nested property access 'data.teamId': teamId, 'data.email': email, - }); + } as Query); if (deletedToken.deletedCount === 0) { return callback({ diff --git a/modules/authentication/src/handlers/metamask.ts b/modules/authentication/src/handlers/metamask.ts index 68aa672b8..735211e60 100644 --- a/modules/authentication/src/handlers/metamask.ts +++ b/modules/authentication/src/handlers/metamask.ts @@ -6,6 +6,7 @@ import { ConduitRouteReturnDefinition, GrpcError, ParsedRouterRequest, + Query, UnparsedRouterResponse, } from '@conduitplatform/grpc-sdk'; import { User } from '../models/index.js'; @@ -80,9 +81,8 @@ export class MetamaskHandlers implements IAuthenticationStrategy { const normalizedEthPublicAddress = ethPublicAddress.toLowerCase(); const existingUser: User | null = await User.getInstance().findOne({ - // @ts-expect-error Unsafe nested property access 'metamask.ethPublicAddress': normalizedEthPublicAddress, - }); + } as Query); if (existingUser) { return { nonce: existingUser.metamask!.nonce }; @@ -110,9 +110,8 @@ export class MetamaskHandlers implements IAuthenticationStrategy { } const user = await User.getInstance().findOne({ - // @ts-expect-error Unsafe nested property access 'metamask.ethPublicAddress': normalizedEthPublicAddress, - }); + } as Query); if (isNil(user)) { throw new GrpcError( @@ -155,9 +154,8 @@ export class MetamaskHandlers implements IAuthenticationStrategy { } await User.getInstance().findByIdAndUpdate(user._id, { - // @ts-expect-error Unsafe nested property access 'metamask.nonce': uuid(), - }); + } as Query); const config = ConfigController.getInstance().config; return TokenProvider.getInstance().provideUserTokens({ diff --git a/modules/authentication/src/handlers/team.ts b/modules/authentication/src/handlers/team.ts index f45cf9892..ee2a24c5c 100644 --- a/modules/authentication/src/handlers/team.ts +++ b/modules/authentication/src/handlers/team.ts @@ -147,9 +147,8 @@ export class TeamsHandler implements IAuthenticationStrategy { async getUserInvites(call: ParsedRouterRequest): Promise { const invites = await Token.getInstance().findMany({ tokenType: TokenType.TEAM_INVITE_TOKEN, - // @ts-ignore 'data.email': call.request.context.user.email, - }); + } as Query); return { invites: invites.map(invite => ({ teamId: invite.data.teamId, @@ -597,10 +596,9 @@ export class TeamsHandler implements IAuthenticationStrategy { // Delete any existing invite for the same email and team await Token.getInstance().deleteOne({ tokenType: TokenType.TEAM_INVITE_TOKEN, - // @ts-expect-error Unsafe nested property access 'data.teamId': teamId, 'data.email': email, - }); + } as Query); const invitation = await this.createUserInvitation({ teamId, @@ -663,10 +661,9 @@ export class TeamsHandler implements IAuthenticationStrategy { // Delete any existing invite for the same email and team await Token.getInstance().deleteOne({ tokenType: TokenType.TEAM_INVITE_TOKEN, - // @ts-expect-error Unsafe nested property access 'data.teamId': teamId, 'data.email': email, - }); + } as Query); return 'OK'; } @@ -698,17 +695,14 @@ export class TeamsHandler implements IAuthenticationStrategy { ); } - const invites = await Token.getInstance().findMany({ + const teamInvitesQuery = { tokenType: TokenType.TEAM_INVITE_TOKEN, - // @ts-expect-error Unsafe nested property access 'data.teamId': teamId, - }); + } as Query; - const count = await Token.getInstance().countDocuments({ - tokenType: TokenType.TEAM_INVITE_TOKEN, - // @ts-expect-error Unsafe nested property access - 'data.teamId': teamId, - }); + const invites = await Token.getInstance().findMany(teamInvitesQuery); + + const count = await Token.getInstance().countDocuments(teamInvitesQuery); return { invites, diff --git a/modules/communications/src/providers/email/mandrill/MandrilProvider.ts b/modules/communications/src/providers/email/mandrill/MandrilProvider.ts index 3be1fe3ad..7f37be2ae 100644 --- a/modules/communications/src/providers/email/mandrill/MandrilProvider.ts +++ b/modules/communications/src/providers/email/mandrill/MandrilProvider.ts @@ -7,11 +7,7 @@ import { MandrillBuilder } from './mandrillBuilder.js'; import { getHandleBarsValues } from '../utils/index.js'; import { MandrillTemplate } from '../interfaces/mandrill/MandrillTemplate.js'; -// @ts-expect-error — CJS package without bundled types import mailchimpFactory from '@mailchimp/mailchimp_transactional'; - -// @ts-expect-error -// missing typings for nodemailer-mandrill-transport import mandrillTransport from 'nodemailer-mandrill-transport'; import { Indexable } from '@conduitplatform/grpc-sdk'; diff --git a/modules/communications/src/types/mailchimp-transactional.d.ts b/modules/communications/src/types/mailchimp-transactional.d.ts new file mode 100644 index 000000000..ff52683e5 --- /dev/null +++ b/modules/communications/src/types/mailchimp-transactional.d.ts @@ -0,0 +1,23 @@ +declare module '@mailchimp/mailchimp_transactional' { + interface MailchimpTransactional { + templates: { + list(body?: Record): Promise; + info(body: { name: string }): Promise; + add(body: { + name: string; + subject?: string; + code?: string; + publish?: boolean; + }): Promise; + update(body: { name: string; code?: string; subject?: string }): Promise; + delete(body: { name: string }): Promise; + }; + messages: { + info(body: { id: string }): Promise; + }; + } + + function mailchimpFactory(apiKey: string): MailchimpTransactional; + + export default mailchimpFactory; +} diff --git a/modules/communications/src/types/nodemailer-mandrill-transport.d.ts b/modules/communications/src/types/nodemailer-mandrill-transport.d.ts new file mode 100644 index 000000000..68e9c366c --- /dev/null +++ b/modules/communications/src/types/nodemailer-mandrill-transport.d.ts @@ -0,0 +1,5 @@ +declare module 'nodemailer-mandrill-transport' { + function mandrillTransport(options: { auth: { apiKey: string } }): any; + + export default mandrillTransport; +} diff --git a/modules/database/src/adapters/DatabaseAdapter.ts b/modules/database/src/adapters/DatabaseAdapter.ts index 7e5f898c9..6345c6413 100644 --- a/modules/database/src/adapters/DatabaseAdapter.ts +++ b/modules/database/src/adapters/DatabaseAdapter.ts @@ -582,24 +582,21 @@ export abstract class DatabaseAdapter { } protected addSchemaPermissions(schema: ConduitSchema) { - const defaultPermissions = { + const defaultPermissions: NonNullable< + NonNullable['permissions'] + > = { extendable: true, canCreate: true, canModify: 'Everything', canDelete: true, - } as const; + }; + if (isNil(schema.modelOptions.conduit)) schema.modelOptions.conduit = {}; - if (isNil(schema.modelOptions.conduit.permissions)) { - schema.modelOptions.conduit!.permissions = defaultPermissions; - } else { - Object.keys(defaultPermissions).forEach(perm => { - if (!schema.modelOptions.conduit!.permissions!.hasOwnProperty(perm)) { - // @ts-ignore - schema.modelOptions.conduit!.permissions![perm] = - defaultPermissions[perm as keyof typeof defaultPermissions]; - } - }); - } + + schema.modelOptions.conduit.permissions = { + ...defaultPermissions, + ...schema.modelOptions.conduit.permissions, + }; return schema; } diff --git a/modules/database/src/adapters/utils/database-transform-utils.ts b/modules/database/src/adapters/utils/database-transform-utils.ts index 6ec5768d0..72956f938 100644 --- a/modules/database/src/adapters/utils/database-transform-utils.ts +++ b/modules/database/src/adapters/utils/database-transform-utils.ts @@ -121,8 +121,7 @@ export function extractFieldProperties( res.unique = objectField.unique ?? false; res.allowNull = false; } else if (objectField.hasOwnProperty('required') && objectField.required) { - // @ts-expect-error - res.allowNull = !objectField.required ?? true; + res.allowNull = !objectField.required; } return res; diff --git a/modules/database/src/utils/utilities.ts b/modules/database/src/utils/utilities.ts index ce6cd7328..15f6e4d4f 100644 --- a/modules/database/src/utils/utilities.ts +++ b/modules/database/src/utils/utilities.ts @@ -18,11 +18,13 @@ import { import * as deepdash from 'deepdash-es/standalone'; +type CrudOperationConfig = { enabled?: boolean; authenticated?: boolean }; + type CrudOperations = { - create?: { enabled?: boolean; authenticated?: boolean }; - read?: { enabled?: boolean; authenticated?: boolean }; - update?: { enabled?: boolean; authenticated?: boolean }; - delete?: { enabled?: boolean; authenticated?: boolean }; + create?: CrudOperationConfig; + read?: CrudOperationConfig; + update?: CrudOperationConfig; + delete?: CrudOperationConfig; }; interface Permissions { @@ -221,23 +223,27 @@ function validateCrudOperations(crudOperations: CrudOperations) { if (!isObject(crudOperations)) throw new Error(`CMS field 'crudOperations' must be of type Object`); - Object.keys(crudOperations).forEach(op => { - if (!allowedCrudOperations.includes(op as keyof CrudOperations)) { + (Object.keys(crudOperations) as Array).forEach(op => { + if (!allowedCrudOperations.includes(op)) { throw new Error(`Unrecognized CRUD operation '${op}' provided`); } - // @ts-ignore - if (!isObject(crudOperations[op])) { + + const operationConfig = crudOperations[op]; + + if (!isObject(operationConfig)) { throw new Error(`Crud operation field '${op}' must be of type Object`); } - // @ts-ignore - Object.keys(crudOperations[op]).forEach(opField => { - if (!['enabled', 'authenticated'].includes(opField)) { + + const config = operationConfig as CrudOperationConfig; + + Object.keys(config).forEach(opField => { + if (opField !== 'enabled' && opField !== 'authenticated') { throw new Error( `Unrecognized crud operation field '${opField}' for operation '${op}' provided`, ); } - // @ts-ignore - if (!isBoolean(crudOperations[op][opField])) { + + if (!isBoolean(config[opField])) { throw new Error( `Crud operation field '${opField}' for operation '${op}' must be of type Boolean`, );