From 98cf16544386c79a635ee6c4b6ceb2013a4652a2 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 16 Apr 2024 09:27:51 -0700 Subject: [PATCH] refactor(permission-controller): Refactor "any" typecasts Either replaces `any` with `@ts-expect-error` directives or leaves them in place without a TODO to replace them. All remaining instances of `any` are defensible. --- .../permission-controller/src/Caveat.test.ts | 4 - packages/permission-controller/src/Caveat.ts | 8 - .../permission-controller/src/Permission.ts | 21 +- .../src/PermissionController.test.ts | 221 ++++++------------ .../src/PermissionController.ts | 32 +-- .../src/SubjectMetadataController.ts | 11 +- .../src/rpc-methods/getPermissions.test.ts | 20 +- .../rpc-methods/requestPermissions.test.ts | 48 ++-- .../src/rpc-methods/revokePermissions.test.ts | 58 +++-- 9 files changed, 145 insertions(+), 278 deletions(-) diff --git a/packages/permission-controller/src/Caveat.test.ts b/packages/permission-controller/src/Caveat.test.ts index adfcfbd742c..6a9dc6ccd9f 100644 --- a/packages/permission-controller/src/Caveat.test.ts +++ b/packages/permission-controller/src/Caveat.test.ts @@ -9,7 +9,6 @@ describe('decorateWithCaveats', () => { const caveatSpecifications = { reverse: { type: 'reverse', - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any decorator: (method: any, _caveat: any) => async () => { return (await method()).reverse(); @@ -46,7 +45,6 @@ describe('decorateWithCaveats', () => { const caveatSpecifications = { reverse: { type: 'reverse', - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any decorator: (method: any, _caveat: any) => async () => { return (await method()).reverse(); @@ -54,7 +52,6 @@ describe('decorateWithCaveats', () => { }, slice: { type: 'slice', - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any decorator: (method: any, caveat: any) => async () => { return (await method()).slice(0, caveat.value); @@ -114,7 +111,6 @@ describe('decorateWithCaveats', () => { const caveatSpecifications = { reverse: { type: 'reverse', - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any decorator: (method: any, _caveat: any) => async () => { return (await method()).reverse(); diff --git a/packages/permission-controller/src/Caveat.ts b/packages/permission-controller/src/Caveat.ts index cf4c9c6376a..41203fa240f 100644 --- a/packages/permission-controller/src/Caveat.ts +++ b/packages/permission-controller/src/Caveat.ts @@ -82,15 +82,12 @@ export type CaveatDecorator = ( * @template Decorator - The {@link CaveatDecorator} to extract a caveat value * type from. */ -// TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any type ExtractCaveatValueFromDecorator> = Decorator extends ( - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any decorated: any, caveat: infer ParentCaveat, - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => AsyncRestrictedMethod ? ParentCaveat extends CaveatConstraint @@ -129,7 +126,6 @@ export type CaveatSpecificationBase = { * performed. Although caveats can also be validated by permission validators, * validating caveat values separately is strongly recommended. */ - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any validator?: CaveatValidator; }; @@ -140,7 +136,6 @@ export type RestrictedMethodCaveatSpecificationConstraint = * The decorator function used to apply the caveat to restricted method * requests. */ - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any decorator: CaveatDecorator; }; @@ -180,7 +175,6 @@ type CaveatSpecificationBuilderOptions< * tailored to their requirements. */ export type CaveatSpecificationBuilder< - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any Options extends CaveatSpecificationBuilderOptions, Specification extends CaveatSpecificationConstraint, @@ -192,7 +186,6 @@ export type CaveatSpecificationBuilder< */ export type CaveatSpecificationBuilderExportConstraint = { specificationBuilder: CaveatSpecificationBuilder< - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any CaveatSpecificationBuilderOptions, CaveatSpecificationConstraint @@ -220,7 +213,6 @@ export type CaveatSpecificationMap< */ export type ExtractCaveats< CaveatSpecification extends CaveatSpecificationConstraint, - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any > = CaveatSpecification extends any ? CaveatSpecification extends RestrictedMethodCaveatSpecificationConstraint diff --git a/packages/permission-controller/src/Permission.ts b/packages/permission-controller/src/Permission.ts index d0800c37564..df902722777 100644 --- a/packages/permission-controller/src/Permission.ts +++ b/packages/permission-controller/src/Permission.ts @@ -118,9 +118,7 @@ export type ValidPermission< */ type ExtractArrayMembers = ArrayType extends [] ? never - : // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ArrayType extends any[] | readonly any[] + : ArrayType extends unknown[] | readonly unknown[] ? ArrayType[number] : never; @@ -209,9 +207,7 @@ export type RequestedPermissions = Record; */ type RestrictedMethodContext = Readonly<{ origin: OriginString; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + [key: string]: unknown; }>; export type RestrictedMethodParameters = Json[] | Record; @@ -265,9 +261,10 @@ export type RestrictedMethod< | AsyncRestrictedMethod; export type ValidRestrictedMethod< - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - MethodImplementation extends RestrictedMethod, + MethodImplementation extends RestrictedMethod< + RestrictedMethodParameters, + Json + >, > = MethodImplementation extends (args: infer Options) => Json | Promise ? Options extends RestrictedMethodOptions ? MethodImplementation @@ -404,7 +401,6 @@ type PermissionSpecificationBase = { * used, and the validator function (if specified) will be called on newly * constructed permissions. */ - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any factory?: PermissionFactory>; @@ -423,7 +419,6 @@ type PermissionSpecificationBase = { * * If the side-effect action fails, the permission that triggered it is revoked. */ - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any sideEffect?: PermissionSideEffect; @@ -449,7 +444,6 @@ export type RestrictedMethodSpecificationConstraint = * The implementation of the restricted method that the permission * corresponds to. */ - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any methodImplementation: RestrictedMethod; }; @@ -469,7 +463,6 @@ export type EndowmentSpecificationConstraint = * permission is invoked, after which the host can apply the endowments to * the requesting subject in the intended manner. */ - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any endowmentGetter: EndowmentGetter; }; @@ -511,7 +504,6 @@ type PermissionSpecificationBuilderOptions< */ export type PermissionSpecificationBuilder< Type extends PermissionType, - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any Options extends PermissionSpecificationBuilderOptions, Specification extends PermissionSpecificationConstraint & { @@ -527,7 +519,6 @@ export type PermissionSpecificationBuilderExportConstraint = { targetName: string; specificationBuilder: PermissionSpecificationBuilder< PermissionType, - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any PermissionSpecificationBuilderOptions, PermissionSpecificationConstraint diff --git a/packages/permission-controller/src/PermissionController.test.ts b/packages/permission-controller/src/PermissionController.test.ts index 42038cc73b4..3456c116175 100644 --- a/packages/permission-controller/src/PermissionController.test.ts +++ b/packages/permission-controller/src/PermissionController.test.ts @@ -692,10 +692,8 @@ describe('PermissionController', () => { }); it('throws if a permission specification lists unrecognized caveats', () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const permissionSpecifications: any = - getDefaultPermissionSpecifications(); + const permissionSpecifications = getDefaultPermissionSpecifications(); + // @ts-expect-error Abusing types for testing purposes permissionSpecifications.wallet_getSecretArray.allowedCaveats.push('foo'); expect( @@ -1652,9 +1650,7 @@ describe('PermissionController', () => { origin, PermissionNames.wallet_getSecretObject, CaveatTypes.noopCaveat, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - 'bar' as any, + 'bar', ), ).toThrow(new Error('NoopCaveat value must be null')); }); @@ -1852,7 +1848,7 @@ describe('PermissionController', () => { expect(() => controller.removeCaveat( origin, - // @ts-expect-error - Testing invalid permission name. + // @ts-expect-error Abusing types for testing purposes PermissionNames.wallet_noopWithRequiredCaveat, CaveatTypes.noopCaveat, ), @@ -2082,9 +2078,7 @@ describe('PermissionController', () => { const controller = getMultiCaveatController(); let counter = 0; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mutator: any = () => { + const mutator = () => { counter += 1; return counter === 1 ? { operation: CaveatMutatorOperation.noop } @@ -2096,6 +2090,7 @@ describe('PermissionController', () => { controller.updatePermissionsByCaveat( CaveatTypes.filterArrayResponse, + // @ts-expect-error Abusing types for testing purposes mutator, ); @@ -2173,9 +2168,7 @@ describe('PermissionController', () => { const controller = getMultiCaveatController(); let counter = 0; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mutator: any = () => { + const mutator = () => { counter += 1; return { operation: @@ -2187,13 +2180,13 @@ describe('PermissionController', () => { controller.updatePermissionsByCaveat( CaveatTypes.filterArrayResponse, + // @ts-expect-error Abusing types for testing purposes mutator, ); const matcher = getMultiCaveatStateMatcher(); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - delete (matcher.subjects as any)[MultiCaveatOrigins.a]; + // @ts-expect-error Abusing types for testing purposes + delete matcher.subjects[MultiCaveatOrigins.a]; expect(controller.state).toStrictEqual(matcher); }); @@ -2230,10 +2223,9 @@ describe('PermissionController', () => { expect(() => controller.updatePermissionsByCaveat( CaveatTypes.filterArrayResponse, + // @ts-expect-error Abusing types for testing purposes () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { operation: 'foobar' } as any; + return { operation: 'foobar' }; }, ), ).toThrow(`Unrecognized mutation result: "foobar"`); @@ -2503,9 +2495,8 @@ describe('PermissionController', () => { expect(() => controller.grantPermissions({ - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - subject: { origin: 2 as any }, + // @ts-expect-error Abusing types for testing purposes + subject: { origin: 2 }, approvedPermissions: { wallet_getSecretArray: {}, }, @@ -2605,9 +2596,8 @@ describe('PermissionController', () => { subject: { origin }, approvedPermissions: { wallet_getSecretArray: { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - caveats: [[]] as any, + // @ts-expect-error Abusing types for testing purposes + caveats: [[]], }, }, }), @@ -2624,9 +2614,8 @@ describe('PermissionController', () => { subject: { origin }, approvedPermissions: { wallet_getSecretArray: { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - caveats: ['foo'] as any, + // @ts-expect-error Abusing types for testing purposes + caveats: ['foo'], }, }, }), @@ -2651,11 +2640,10 @@ describe('PermissionController', () => { caveats: [ { ...{ type: CaveatTypes.filterArrayResponse, value: ['foo'] }, + // @ts-expect-error Abusing types for testing purposes bar: 'bar', }, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ] as any, + ], }, }, }), @@ -2682,12 +2670,11 @@ describe('PermissionController', () => { wallet_getSecretArray: { caveats: [ { + // @ts-expect-error Abusing types for testing purposes type: 2, value: ['foo'], }, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ] as any, + ], }, }, }), @@ -2737,11 +2724,10 @@ describe('PermissionController', () => { caveats: [ { type: CaveatTypes.filterArrayResponse, + // @ts-expect-error Abusing types for testing purposes foo: 'bar', }, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ] as any, + ], }, }, }), @@ -2761,7 +2747,6 @@ describe('PermissionController', () => { const controller = getDefaultPermissionController(); const origin = 'metamask.io'; - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any const circular: any = { foo: 'bar' }; circular.circular = circular; @@ -2898,7 +2883,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -2950,7 +2934,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3012,7 +2995,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3078,7 +3060,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3153,7 +3134,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3210,7 +3190,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3264,7 +3243,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3311,7 +3289,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3368,7 +3345,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3439,7 +3415,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3519,7 +3494,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3595,7 +3569,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3691,9 +3664,8 @@ describe('PermissionController', () => { async () => await controller.requestPermissions( { origin }, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - invalidInput as any, + // @ts-expect-error Abusing types for testing purposes + invalidInput, ), ).rejects.toThrow( errors.invalidParams({ @@ -3856,7 +3828,6 @@ describe('PermissionController', () => { extensionId: null, }; }) - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -3950,9 +3921,8 @@ describe('PermissionController', () => { { origin }, { [PermissionNames.wallet_getSecretArray]: { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - caveats: invalidCaveatsValue as any, + // @ts-expect-error Abusing types for testing purposes + caveats: invalidCaveatsValue, }, }, ), @@ -4050,7 +4020,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -4102,7 +4071,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -4154,7 +4122,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -4208,7 +4175,6 @@ describe('PermissionController', () => { const callActionSpy = jest.spyOn(messenger, 'call'); // The metadata is valid, but the permissions are invalid - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any const getInvalidRequestObject = (invalidPermissions: any) => { return { @@ -4268,7 +4234,6 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementationOnce(async (...args: any) => { const [, { requestData }] = args; @@ -4345,12 +4310,8 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => true) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => undefined); + .mockImplementationOnce(() => true) + .mockImplementationOnce(() => undefined); const controller = getDefaultPermissionController(options); @@ -4391,12 +4352,8 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => true) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => undefined); + .mockImplementationOnce(() => true) + .mockImplementationOnce(() => undefined); const controller = getDefaultPermissionController(options); @@ -4432,9 +4389,7 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => false); + .mockImplementationOnce(() => false); const controller = getDefaultPermissionController(options); @@ -4466,17 +4421,11 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => true) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => { + .mockImplementationOnce(() => true) + .mockImplementationOnce(() => { throw new Error('unexpected failure'); }) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => undefined); + .mockImplementationOnce(() => undefined); const controller = getDefaultPermissionController(options); @@ -4528,12 +4477,8 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce(async (..._args: any) => true) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce(async (..._args: any) => undefined); + .mockImplementationOnce(async () => true) + .mockImplementationOnce(async () => undefined); const controller = getDefaultPermissionController(options); @@ -4563,9 +4508,7 @@ describe('PermissionController', () => { const callActionSpy = jest .spyOn(messenger, 'call') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementationOnce((..._args: any) => false); + .mockImplementationOnce(() => false); const controller = getDefaultPermissionController(options); @@ -4618,9 +4561,8 @@ describe('PermissionController', () => { await expect( controller.getEndowments( origin, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - PermissionNames.wallet_getSecretArray as any, + // @ts-expect-error Abusing types for testing purposes + PermissionNames.wallet_getSecretArray, ), ).rejects.toThrow( new errors.EndowmentPermissionDoesNotExistError( @@ -4750,17 +4692,14 @@ describe('PermissionController', () => { const origin = 'metamask.io'; await expect( - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - controller.executeRestrictedMethod(origin, 'wallet_getMeTacos' as any), + // @ts-expect-error Abusing types for testing purposes + controller.executeRestrictedMethod(origin, 'wallet_getMeTacos'), ).rejects.toThrow(errors.methodNotFound('wallet_getMeTacos', { origin })); }); it('throws if the restricted method returns undefined', async () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const permissionSpecifications: any = - getDefaultPermissionSpecifications(); + const permissionSpecifications = getDefaultPermissionSpecifications(); + // @ts-expect-error Abusing types for testing purposes permissionSpecifications.wallet_doubleNumber.methodImplementation = () => undefined; @@ -5246,14 +5185,13 @@ describe('PermissionController', () => { const engine = new JsonRpcEngine(); engine.push(controller.createPermissionMiddleware({ origin })); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: PermissionNames.wallet_getSecretArray, }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toStrictEqual(['a', 'b', 'c']); }); @@ -5273,14 +5211,13 @@ describe('PermissionController', () => { const engine = new JsonRpcEngine(); engine.push(controller.createPermissionMiddleware({ origin })); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: PermissionNames.wallet_getSecretArray, }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toStrictEqual(['b']); }); @@ -5303,14 +5240,13 @@ describe('PermissionController', () => { const engine = new JsonRpcEngine(); engine.push(controller.createPermissionMiddleware({ origin })); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: PermissionNames.wallet_getSecretArray, }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toStrictEqual(['c', 'a']); }); @@ -5322,30 +5258,23 @@ describe('PermissionController', () => { engine.push(controller.createPermissionMiddleware({ origin })); engine.push( ( - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _req: any, + _req: unknown, res: PendingJsonRpcResponse<'success'>, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _next: any, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - end: () => any, + _next: unknown, + end: () => unknown, ) => { res.result = 'success'; end(); }, ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: 'wallet_unrestrictedMethod', }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toBe('success'); }); @@ -5355,9 +5284,8 @@ describe('PermissionController', () => { ['', null, undefined, 2].forEach((invalidOrigin) => { expect(() => controller.createPermissionMiddleware({ - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - origin: invalidOrigin as any, + // @ts-expect-error Abusing types for testing purposes + origin: invalidOrigin, }), ).toThrow( new Error('The subject "origin" must be a non-empty string.'), @@ -5372,9 +5300,7 @@ describe('PermissionController', () => { const engine = new JsonRpcEngine(); engine.push(controller.createPermissionMiddleware({ origin })); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const request: any = { + const request = { jsonrpc: '2.0', id: 1, method: PermissionNames.wallet_getSecretArray, @@ -5390,9 +5316,8 @@ describe('PermissionController', () => { 'Unauthorized to perform action. Try requesting the required permission(s) first. For more information, see: https://docs.metamask.io/guide/rpc-api.html#permissions', }); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { error }: any = await engine.handle(request); + // @ts-expect-error Abusing types for testing purposes + const { error } = await engine.handle(request); expect(error).toMatchObject(expect.objectContaining(expectedError)); }); @@ -5403,9 +5328,7 @@ describe('PermissionController', () => { const engine = new JsonRpcEngine(); engine.push(controller.createPermissionMiddleware({ origin })); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const request: any = { + const request = { jsonrpc: '2.0', id: 1, method: 'wallet_foo', @@ -5413,9 +5336,8 @@ describe('PermissionController', () => { const expectedError = errors.methodNotFound('wallet_foo', { origin }); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { error }: any = await engine.handle(request); + // @ts-expect-error Abusing types for testing purposes + const { error } = await engine.handle(request); expect(error.message).toStrictEqual(expectedError.message); expect(error.data.cause).toBeNull(); @@ -5425,10 +5347,8 @@ describe('PermissionController', () => { }); it('returns an error if the restricted method returns undefined', async () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const permissionSpecifications: any = - getDefaultPermissionSpecifications(); + const permissionSpecifications = getDefaultPermissionSpecifications(); + // @ts-expect-error Abusing types for testing purposes permissionSpecifications.wallet_doubleNumber.methodImplementation = () => undefined; @@ -5452,9 +5372,7 @@ describe('PermissionController', () => { const engine = new JsonRpcEngine(); engine.push(controller.createPermissionMiddleware({ origin })); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const request: any = { + const request = { jsonrpc: '2.0', id: 1, method: PermissionNames.wallet_doubleNumber, @@ -5465,9 +5383,8 @@ describe('PermissionController', () => { { request: { ...request } }, ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { error }: any = await engine.handle(request); + // @ts-expect-error Abusing types for testing purposes + const { error } = await engine.handle(request); expect(error.message).toStrictEqual(expectedError.message); expect(error.data.cause).toBeNull(); delete error.message; diff --git a/packages/permission-controller/src/PermissionController.ts b/packages/permission-controller/src/PermissionController.ts index 06d740a1fce..d45d517fd43 100644 --- a/packages/permission-controller/src/PermissionController.ts +++ b/packages/permission-controller/src/PermissionController.ts @@ -119,10 +119,8 @@ export type PermissionsRequest = { }; export type SideEffects = { - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any permittedHandlers: Record>; - // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any failureHandlers: Record>; }; @@ -1292,13 +1290,12 @@ export class PermissionController< permission.caveats.splice(caveatIndex, 1, caveat); } } else { - // Typecast: At this point, we don't know if the specific permission - // is allowed to have caveats, but it should be impossible to call - // this method for a permission that may not have any caveats. - // If all else fails, the permission validator is also called. - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - permission.caveats = [caveat] as any; + // At this point, we don't know if the specific permission is allowed + // to have caveats, but it should be impossible to call this method + // for a permission that may not have any caveats. If all else fails, + // the permission validator is also called. + // @ts-expect-error See above comment + permission.caveats = [caveat]; } this.validateModifiedPermission(permission, origin); @@ -1388,12 +1385,11 @@ export class PermissionController< default: { // This type check ensures that the switch statement is // exhaustive. - const _exhaustiveCheck: never = mutatorResult; + const exhaustiveCheck: never = mutatorResult; throw new Error( `Unrecognized mutation result: "${ - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (_exhaustiveCheck as any).operation + // @ts-expect-error We need to override the "never" + exhaustiveCheck.operation }"`, ); } @@ -2233,15 +2229,7 @@ export class PermissionController< * @returns Whether the specified request exists. */ private hasApprovalRequest(options: { id: string }): boolean { - return this.messagingSystem.call( - 'ApprovalController:hasRequest', - // Typecast: For some reason, the type here expects all of the possible - // HasApprovalRequest options to be specified, when they're actually all - // optional. Passing just the id is definitely valid, so we just cast it. - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - options as any, - ); + return this.messagingSystem.call('ApprovalController:hasRequest', options); } /** diff --git a/packages/permission-controller/src/SubjectMetadataController.ts b/packages/permission-controller/src/SubjectMetadataController.ts index ab363e53279..70f6b68e26f 100644 --- a/packages/permission-controller/src/SubjectMetadataController.ts +++ b/packages/permission-controller/src/SubjectMetadataController.ts @@ -210,10 +210,7 @@ export class SubjectMetadataController extends BaseController< this.subjectsWithoutPermissionsEncounteredSinceStartup.add(origin); this.update((draftState) => { - // Typecast: ts(2589) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - draftState.subjectMetadata[origin] = newMetadata as any; + draftState.subjectMetadata[origin] = newMetadata; if (typeof originToForget === 'string') { delete draftState.subjectMetadata[originToForget]; } @@ -235,11 +232,9 @@ export class SubjectMetadataController extends BaseController< */ trimMetadataState(): void { this.update((draftState) => { + // @ts-expect-error ts(2589) return SubjectMetadataController.getTrimmedState( - // Typecast: ts(2589) - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - draftState as any, + draftState, this.subjectHasPermissions, ); }); diff --git a/packages/permission-controller/src/rpc-methods/getPermissions.test.ts b/packages/permission-controller/src/rpc-methods/getPermissions.test.ts index 1493a839913..4418a2b1df2 100644 --- a/packages/permission-controller/src/rpc-methods/getPermissions.test.ts +++ b/packages/permission-controller/src/rpc-methods/getPermissions.test.ts @@ -11,20 +11,18 @@ describe('getPermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { getPermissionsForOrigin: mockGetPermissionsForOrigin, }), ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: 'arbitraryName', }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toStrictEqual(['a', 'b', 'c']); expect(mockGetPermissionsForOrigin).toHaveBeenCalledTimes(1); }); @@ -37,20 +35,18 @@ describe('getPermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { getPermissionsForOrigin: mockGetPermissionsForOrigin, }), ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: 'arbitraryName', }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toStrictEqual([]); expect(mockGetPermissionsForOrigin).toHaveBeenCalledTimes(1); }); diff --git a/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts b/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts index e935e021a74..097f244efb9 100644 --- a/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts +++ b/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts @@ -23,22 +23,20 @@ describe('requestPermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { requestPermissionsForOrigin: mockRequestPermissionsForOrigin, }), ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: 'arbitraryName', params: [{}], }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toStrictEqual(['a', 'b', 'c']); expect(mockRequestPermissionsForOrigin).toHaveBeenCalledTimes(1); expect(mockRequestPermissionsForOrigin).toHaveBeenCalledWith({}); @@ -53,39 +51,35 @@ describe('requestPermissions RPC method', () => { }); const engine = new JsonRpcEngine(); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const end: any = () => undefined; // this won't be called + const end = () => undefined; // this won't be called // Pass the middleware function to createAsyncMiddleware so the error // is catched. engine.push( - createAsyncMiddleware( - (req, res, next) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { - requestPermissionsForOrigin: mockRequestPermissionsForOrigin, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - }) as any, + createAsyncMiddleware((req, res, next) => + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { + requestPermissionsForOrigin: mockRequestPermissionsForOrigin, + }), ), ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: 'arbitraryName', params: [{}], }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toBeUndefined(); + // @ts-expect-error Abusing types for testing purposes delete response.error.stack; + // @ts-expect-error Abusing types for testing purposes delete response.error.data.cause.stack; const expectedError = new Error('foo'); delete expectedError.stack; + // @ts-expect-error Abusing types for testing purposes expect(response.error).toStrictEqual( serializeError(expectedError, { shouldIncludeStack: false }), ); @@ -99,9 +93,8 @@ describe('requestPermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { requestPermissionsForOrigin: mockRequestPermissionsForOrigin, }), ); @@ -121,10 +114,11 @@ describe('requestPermissions RPC method', () => { .serialize(); delete expectedError.stack; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle(req as any); + // @ts-expect-error Abusing types for testing purposes + const response = await engine.handle(req); + // @ts-expect-error Abusing types for testing purposes delete response.error.stack; + // @ts-expect-error Abusing types for testing purposes expect(response.error).toStrictEqual(expectedError); expect(mockRequestPermissionsForOrigin).not.toHaveBeenCalled(); } diff --git a/packages/permission-controller/src/rpc-methods/revokePermissions.test.ts b/packages/permission-controller/src/rpc-methods/revokePermissions.test.ts index b45cb0f3bf3..ccad0eeba45 100644 --- a/packages/permission-controller/src/rpc-methods/revokePermissions.test.ts +++ b/packages/permission-controller/src/rpc-methods/revokePermissions.test.ts @@ -22,16 +22,13 @@ describe('revokePermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { revokePermissionsForOrigin: mockRevokePermissionsForOrigin, }), ); - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle({ + const response = await engine.handle({ jsonrpc: '2.0', id: 1, method: 'wallet_revokePermissions', @@ -42,6 +39,7 @@ describe('revokePermissions RPC method', () => { ], }); + // @ts-expect-error Abusing types for testing purposes expect(response.result).toBeNull(); expect(mockRevokePermissionsForOrigin).toHaveBeenCalledTimes(1); expect(mockRevokePermissionsForOrigin).toHaveBeenCalledWith([ @@ -55,9 +53,8 @@ describe('revokePermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { revokePermissionsForOrigin: mockRevokePermissionsForOrigin, }), ); @@ -76,10 +73,11 @@ describe('revokePermissions RPC method', () => { .serialize(); delete expectedError.stack; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle(req as any); + // @ts-expect-error Abusing types for testing purposes + const response = await engine.handle(req); + // @ts-expect-error Abusing types for testing purposes delete response.error.stack; + // @ts-expect-error Abusing types for testing purposes expect(response.error).toStrictEqual(expectedError); expect(mockRevokePermissionsForOrigin).not.toHaveBeenCalled(); }); @@ -90,9 +88,8 @@ describe('revokePermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { revokePermissionsForOrigin: mockRevokePermissionsForOrigin, }), ); @@ -111,10 +108,11 @@ describe('revokePermissions RPC method', () => { .serialize(); delete expectedError.stack; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle(req as any); + // @ts-expect-error Abusing types for testing purposes + const response = await engine.handle(req); + // @ts-expect-error Abusing types for testing purposes delete response.error.stack; + // @ts-expect-error Abusing types for testing purposes expect(response.error).toStrictEqual(expectedError); expect(mockRevokePermissionsForOrigin).not.toHaveBeenCalled(); }); @@ -125,9 +123,8 @@ describe('revokePermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { revokePermissionsForOrigin: mockRevokePermissionsForOrigin, }), ); @@ -145,10 +142,11 @@ describe('revokePermissions RPC method', () => { .serialize(); delete expectedError.stack; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle(req as any); + // @ts-expect-error Abusing types for testing purposes + const response = await engine.handle(req); + // @ts-expect-error Abusing types for testing purposes delete response.error.stack; + // @ts-expect-error Abusing types for testing purposes expect(response.error).toStrictEqual(expectedError); expect(mockRevokePermissionsForOrigin).not.toHaveBeenCalled(); }); @@ -159,9 +157,8 @@ describe('revokePermissions RPC method', () => { const engine = new JsonRpcEngine(); engine.push((req, res, next, end) => - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - implementation(req as any, res as any, next, end, { + // @ts-expect-error Abusing types for testing purposes + implementation(req, res, next, end, { revokePermissionsForOrigin: mockRevokePermissionsForOrigin, }), ); @@ -180,10 +177,11 @@ describe('revokePermissions RPC method', () => { .serialize(); delete expectedError.stack; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response: any = await engine.handle(req as any); + // @ts-expect-error Abusing types for testing purposes + const response = await engine.handle(req); + // @ts-expect-error Abusing types for testing purposes delete response.error.stack; + // @ts-expect-error Abusing types for testing purposes expect(response.error).toStrictEqual(expectedError); expect(mockRevokePermissionsForOrigin).not.toHaveBeenCalled(); });