diff --git a/eslint.config.mjs b/eslint.config.mjs index 76bbdf4f3d4..f210b8bc438 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -162,6 +162,12 @@ const config = createConfig([ 'n/no-deprecated-api': 'off', }, }, + { + files: ['packages/messenger/src/generate-action-types/**/*.{js,ts}'], + rules: { + 'import-x/no-nodejs-modules': 'off', + }, + }, { files: [ 'packages/notification-services-controller/src/NotificationServicesPushController/services/push/*-web.ts', diff --git a/packages/account-tree-controller/package.json b/packages/account-tree-controller/package.json index 7e056885f8e..f3096c65cf9 100644 --- a/packages/account-tree-controller/package.json +++ b/packages/account-tree-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/account-tree-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/account-tree-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/account-tree-controller/src/AccountTreeController-method-action-types.ts b/packages/account-tree-controller/src/AccountTreeController-method-action-types.ts index 365dbe342c9..0006c6d7a85 100644 --- a/packages/account-tree-controller/src/AccountTreeController-method-action-types.ts +++ b/packages/account-tree-controller/src/AccountTreeController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/accounts-controller/package.json b/packages/accounts-controller/package.json index 2616ea38a8d..d415ca198d3 100644 --- a/packages/accounts-controller/package.json +++ b/packages/accounts-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/accounts-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/accounts-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/accounts-controller/src/AccountsController-method-action-types.ts b/packages/accounts-controller/src/AccountsController-method-action-types.ts index fc8a6706d6e..8007f656ef8 100644 --- a/packages/accounts-controller/src/AccountsController-method-action-types.ts +++ b/packages/accounts-controller/src/AccountsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/address-book-controller/package.json b/packages/address-book-controller/package.json index 8fc382d32c0..7534103e548 100644 --- a/packages/address-book-controller/package.json +++ b/packages/address-book-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/address-book-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/address-book-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/address-book-controller/src/AddressBookController-method-action-types.ts b/packages/address-book-controller/src/AddressBookController-method-action-types.ts index 6074a35dd07..b902cbc2bf3 100644 --- a/packages/address-book-controller/src/AddressBookController-method-action-types.ts +++ b/packages/address-book-controller/src/AddressBookController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/analytics-controller/package.json b/packages/analytics-controller/package.json index 25dce1f4a86..2d09cd0be35 100644 --- a/packages/analytics-controller/package.json +++ b/packages/analytics-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/analytics-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/analytics-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/analytics-controller/src/AnalyticsController-method-action-types.ts b/packages/analytics-controller/src/AnalyticsController-method-action-types.ts index cd4f15c4995..eb3a4d719ac 100644 --- a/packages/analytics-controller/src/AnalyticsController-method-action-types.ts +++ b/packages/analytics-controller/src/AnalyticsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/analytics-data-regulation-controller/package.json b/packages/analytics-data-regulation-controller/package.json index 04d7f79797c..bde2be42ea8 100644 --- a/packages/analytics-data-regulation-controller/package.json +++ b/packages/analytics-data-regulation-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/analytics-data-regulation-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/analytics-data-regulation-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationController-method-action-types.ts b/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationController-method-action-types.ts index 4490946862b..1bffd87f769 100644 --- a/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationController-method-action-types.ts +++ b/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationService-method-action-types.ts b/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationService-method-action-types.ts index cae15ca9d71..da4bbd64e25 100644 --- a/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationService-method-action-types.ts +++ b/packages/analytics-data-regulation-controller/src/AnalyticsDataRegulationService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/announcement-controller/package.json b/packages/announcement-controller/package.json index c51f7285c6f..202d982c07f 100644 --- a/packages/announcement-controller/package.json +++ b/packages/announcement-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/announcement-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/announcement-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/announcement-controller/src/AnnouncementController-method-action-types.ts b/packages/announcement-controller/src/AnnouncementController-method-action-types.ts index 2868e3c9d94..0d8159394c0 100644 --- a/packages/announcement-controller/src/AnnouncementController-method-action-types.ts +++ b/packages/announcement-controller/src/AnnouncementController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/approval-controller/package.json b/packages/approval-controller/package.json index 47dc9b1e3f4..d70a79e86fd 100644 --- a/packages/approval-controller/package.json +++ b/packages/approval-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/approval-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/approval-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/approval-controller/src/ApprovalController-method-action-types.ts b/packages/approval-controller/src/ApprovalController-method-action-types.ts index 3dc6f6630fc..6afadb02314 100644 --- a/packages/approval-controller/src/ApprovalController-method-action-types.ts +++ b/packages/approval-controller/src/ApprovalController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controller/package.json b/packages/assets-controller/package.json index b868e5c4239..e7566dfab06 100644 --- a/packages/assets-controller/package.json +++ b/packages/assets-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/assets-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/assets-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/assets-controller/src/AssetsController-method-action-types.ts b/packages/assets-controller/src/AssetsController-method-action-types.ts index fb600425209..a4e5352a25a 100644 --- a/packages/assets-controller/src/AssetsController-method-action-types.ts +++ b/packages/assets-controller/src/AssetsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index e4be651de88..531ce049060 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -40,9 +40,9 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/assets-controllers", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/assets-controllers", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts \"$@\" && yarn generate-method-action-types:multichain-assets-controller \"$@\" && yarn generate-method-action-types:multichain-assets-rates-controller \"$@\"", - "generate-method-action-types:multichain-assets-controller": "tsx ../../scripts/generate-method-action-types.ts src/MultichainAssetsController", - "generate-method-action-types:multichain-assets-rates-controller": "tsx ../../scripts/generate-method-action-types.ts src/MultichainAssetsRatesController", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts \"$@\" && yarn generate-method-action-types:multichain-assets-controller \"$@\" && yarn generate-method-action-types:multichain-assets-rates-controller \"$@\"", + "generate-method-action-types:multichain-assets-controller": "tsx ../../packages/messenger/src/generate-action-types/cli.ts src/MultichainAssetsController", + "generate-method-action-types:multichain-assets-rates-controller": "tsx ../../packages/messenger/src/generate-action-types/cli.ts src/MultichainAssetsRatesController", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/assets-controllers/src/AccountTrackerController-method-action-types.ts b/packages/assets-controllers/src/AccountTrackerController-method-action-types.ts index 1b8eca12469..6077429cd2e 100644 --- a/packages/assets-controllers/src/AccountTrackerController-method-action-types.ts +++ b/packages/assets-controllers/src/AccountTrackerController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/src/AssetsContractController-method-action-types.ts b/packages/assets-controllers/src/AssetsContractController-method-action-types.ts index 7f240733734..596f27396ce 100644 --- a/packages/assets-controllers/src/AssetsContractController-method-action-types.ts +++ b/packages/assets-controllers/src/AssetsContractController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController-method-action-types.ts b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController-method-action-types.ts index 1d1163ea8ad..1eb1966f49e 100644 --- a/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController-method-action-types.ts +++ b/packages/assets-controllers/src/MultichainAssetsController/MultichainAssetsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController-method-action-types.ts b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController-method-action-types.ts index 8e8c59b03ad..65732ba8170 100644 --- a/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController-method-action-types.ts +++ b/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/src/TokenBalancesController-method-action-types.ts b/packages/assets-controllers/src/TokenBalancesController-method-action-types.ts index 39ad0d2e8f5..b5bff3a8915 100644 --- a/packages/assets-controllers/src/TokenBalancesController-method-action-types.ts +++ b/packages/assets-controllers/src/TokenBalancesController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/src/TokenDetectionController-method-action-types.ts b/packages/assets-controllers/src/TokenDetectionController-method-action-types.ts index 76d99847bc8..b752ec31183 100644 --- a/packages/assets-controllers/src/TokenDetectionController-method-action-types.ts +++ b/packages/assets-controllers/src/TokenDetectionController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/assets-controllers/src/TokensController-method-action-types.ts b/packages/assets-controllers/src/TokensController-method-action-types.ts index 5981e66b27c..d7dc0575e03 100644 --- a/packages/assets-controllers/src/TokensController-method-action-types.ts +++ b/packages/assets-controllers/src/TokensController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/claims-controller/package.json b/packages/claims-controller/package.json index d5b59fe8bf9..8cfb42e00b0 100644 --- a/packages/claims-controller/package.json +++ b/packages/claims-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/claims-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/claims-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/claims-controller/src/ClaimsController-method-action-types.ts b/packages/claims-controller/src/ClaimsController-method-action-types.ts index 5a33bd54cb3..a65e5ab3f1d 100644 --- a/packages/claims-controller/src/ClaimsController-method-action-types.ts +++ b/packages/claims-controller/src/ClaimsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/client-controller/package.json b/packages/client-controller/package.json index 1eda46f84e5..b6fb9b1f369 100644 --- a/packages/client-controller/package.json +++ b/packages/client-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/client-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/client-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/client-controller/src/ClientController-method-action-types.ts b/packages/client-controller/src/ClientController-method-action-types.ts index 395b224ee67..1256f5bb8d9 100644 --- a/packages/client-controller/src/ClientController-method-action-types.ts +++ b/packages/client-controller/src/ClientController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/compliance-controller/package.json b/packages/compliance-controller/package.json index 5650d6468e1..fd23e898f8a 100644 --- a/packages/compliance-controller/package.json +++ b/packages/compliance-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/compliance-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/compliance-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/compliance-controller/src/ComplianceController-method-action-types.ts b/packages/compliance-controller/src/ComplianceController-method-action-types.ts index 8a0a84d94b8..91cc7f2b5e0 100644 --- a/packages/compliance-controller/src/ComplianceController-method-action-types.ts +++ b/packages/compliance-controller/src/ComplianceController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/compliance-controller/src/ComplianceService-method-action-types.ts b/packages/compliance-controller/src/ComplianceService-method-action-types.ts index f13fc5bfbdf..edfabcd87af 100644 --- a/packages/compliance-controller/src/ComplianceService-method-action-types.ts +++ b/packages/compliance-controller/src/ComplianceService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index dc0ff62268f..dd42a8cf09d 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/config-registry-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/config-registry-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "publish:preview": "yarn npm publish --tag preview", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", diff --git a/packages/config-registry-controller/src/ConfigRegistryController-method-action-types.ts b/packages/config-registry-controller/src/ConfigRegistryController-method-action-types.ts index b435af055a7..0edf347717c 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController-method-action-types.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/connectivity-controller/package.json b/packages/connectivity-controller/package.json index 92587f273d7..8cf15a309e2 100644 --- a/packages/connectivity-controller/package.json +++ b/packages/connectivity-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/connectivity-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/connectivity-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/connectivity-controller/src/ConnectivityController-method-action-types.ts b/packages/connectivity-controller/src/ConnectivityController-method-action-types.ts index 49c39a37d1b..17f1034e58f 100644 --- a/packages/connectivity-controller/src/ConnectivityController-method-action-types.ts +++ b/packages/connectivity-controller/src/ConnectivityController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/core-backend/package.json b/packages/core-backend/package.json index 702887206fd..a7677157d41 100644 --- a/packages/core-backend/package.json +++ b/packages/core-backend/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/core-backend", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/core-backend", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/core-backend/src/AccountActivityService-method-action-types.ts b/packages/core-backend/src/AccountActivityService-method-action-types.ts index 29dd40a2441..ae1b151ad88 100644 --- a/packages/core-backend/src/AccountActivityService-method-action-types.ts +++ b/packages/core-backend/src/AccountActivityService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/core-backend/src/ApiPlatformClientService-method-action-types.ts b/packages/core-backend/src/ApiPlatformClientService-method-action-types.ts index 09096daa1a9..c7b76bda40c 100644 --- a/packages/core-backend/src/ApiPlatformClientService-method-action-types.ts +++ b/packages/core-backend/src/ApiPlatformClientService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/core-backend/src/BackendWebSocketService-method-action-types.ts b/packages/core-backend/src/BackendWebSocketService-method-action-types.ts index beb7fb36959..78f0478fe79 100644 --- a/packages/core-backend/src/BackendWebSocketService-method-action-types.ts +++ b/packages/core-backend/src/BackendWebSocketService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/delegation-controller/package.json b/packages/delegation-controller/package.json index 6d981f9047f..168d19f61a0 100644 --- a/packages/delegation-controller/package.json +++ b/packages/delegation-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/delegation-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/delegation-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/delegation-controller/src/DelegationController-method-action-types.ts b/packages/delegation-controller/src/DelegationController-method-action-types.ts index f773c95f731..fed7b85145f 100644 --- a/packages/delegation-controller/src/DelegationController-method-action-types.ts +++ b/packages/delegation-controller/src/DelegationController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/earn-controller/package.json b/packages/earn-controller/package.json index cccdfb1a6d1..cda60371cab 100644 --- a/packages/earn-controller/package.json +++ b/packages/earn-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/earn-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/earn-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/earn-controller/src/EarnController-method-action-types.ts b/packages/earn-controller/src/EarnController-method-action-types.ts index eb8b4402586..782792022dc 100644 --- a/packages/earn-controller/src/EarnController-method-action-types.ts +++ b/packages/earn-controller/src/EarnController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/ens-controller/package.json b/packages/ens-controller/package.json index 0d291cd91fc..9377b0fdd81 100644 --- a/packages/ens-controller/package.json +++ b/packages/ens-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/ens-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ens-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/ens-controller/src/EnsController-method-action-types.ts b/packages/ens-controller/src/EnsController-method-action-types.ts index f516dd91109..7df36788337 100644 --- a/packages/ens-controller/src/EnsController-method-action-types.ts +++ b/packages/ens-controller/src/EnsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/error-reporting-service/package.json b/packages/error-reporting-service/package.json index 5967e89cab4..9a75bf1330b 100644 --- a/packages/error-reporting-service/package.json +++ b/packages/error-reporting-service/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/error-reporting-service", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/error-reporting-service", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/error-reporting-service/src/error-reporting-service-method-action-types.ts b/packages/error-reporting-service/src/error-reporting-service-method-action-types.ts index ca1b854f383..ed636977359 100644 --- a/packages/error-reporting-service/src/error-reporting-service-method-action-types.ts +++ b/packages/error-reporting-service/src/error-reporting-service-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/gas-fee-controller/package.json b/packages/gas-fee-controller/package.json index 2e9d9cca167..b958cddedec 100644 --- a/packages/gas-fee-controller/package.json +++ b/packages/gas-fee-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/gas-fee-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/gas-fee-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/gas-fee-controller/src/GasFeeController-method-action-types.ts b/packages/gas-fee-controller/src/GasFeeController-method-action-types.ts index d00beb19b45..83a101b6456 100644 --- a/packages/gas-fee-controller/src/GasFeeController-method-action-types.ts +++ b/packages/gas-fee-controller/src/GasFeeController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/gator-permissions-controller/package.json b/packages/gator-permissions-controller/package.json index 972b325f67a..6ee34bfadc2 100644 --- a/packages/gator-permissions-controller/package.json +++ b/packages/gator-permissions-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/gator-permissions-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/gator-permissions-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/gator-permissions-controller/src/GatorPermissionsController-method-action-types.ts b/packages/gator-permissions-controller/src/GatorPermissionsController-method-action-types.ts index ed9b6e4e561..88d07117806 100644 --- a/packages/gator-permissions-controller/src/GatorPermissionsController-method-action-types.ts +++ b/packages/gator-permissions-controller/src/GatorPermissionsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/geolocation-controller/package.json b/packages/geolocation-controller/package.json index 7410c13fa0e..ba63816a5e4 100644 --- a/packages/geolocation-controller/package.json +++ b/packages/geolocation-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/geolocation-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/geolocation-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/geolocation-controller/src/GeolocationController-method-action-types.ts b/packages/geolocation-controller/src/GeolocationController-method-action-types.ts index 5c6bc77aa61..6b74d340ed4 100644 --- a/packages/geolocation-controller/src/GeolocationController-method-action-types.ts +++ b/packages/geolocation-controller/src/GeolocationController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/logging-controller/package.json b/packages/logging-controller/package.json index a1fae26e914..68bcf23d699 100644 --- a/packages/logging-controller/package.json +++ b/packages/logging-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/logging-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/logging-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/logging-controller/src/LoggingController-method-action-types.ts b/packages/logging-controller/src/LoggingController-method-action-types.ts index 8e4da336747..bafebfab780 100644 --- a/packages/logging-controller/src/LoggingController-method-action-types.ts +++ b/packages/logging-controller/src/LoggingController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/messenger/CHANGELOG.md b/packages/messenger/CHANGELOG.md index 00371d21c6d..0c95ad18e7c 100644 --- a/packages/messenger/CHANGELOG.md +++ b/packages/messenger/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `generate-action-types` CLI tool and subpath export ([#8264](https://github.com/MetaMask/core/pull/8264)) + - Generates TypeScript action type files for controllers and services that define `MESSENGER_EXPOSED_METHODS`. + - Available as a CLI binary (`messenger-generate-action-types`) and as a programmatic API via `@metamask/messenger/generate-action-types`. + - `typescript`, `yargs`, and `eslint` are optional peer dependencies, only required when using the codegen tool. + ## [0.3.0] ### Added diff --git a/packages/messenger/jest.config.js b/packages/messenger/jest.config.js index ca084133399..4f4c55b563c 100644 --- a/packages/messenger/jest.config.js +++ b/packages/messenger/jest.config.js @@ -14,6 +14,8 @@ module.exports = merge(baseConfig, { // The display name when running multiple projects displayName, + coveragePathIgnorePatterns: ['./src/generate-action-types/cli.ts'], + // An object that configures minimum threshold enforcement for coverage results coverageThreshold: { global: { diff --git a/packages/messenger/package.json b/packages/messenger/package.json index e52c99da962..30ffc4b8a76 100644 --- a/packages/messenger/package.json +++ b/packages/messenger/package.json @@ -27,10 +27,23 @@ "default": "./dist/index.cjs" } }, + "./generate-action-types": { + "import": { + "types": "./dist/generate-action-types/index.d.mts", + "default": "./dist/generate-action-types/index.mjs" + }, + "require": { + "types": "./dist/generate-action-types/index.d.cts", + "default": "./dist/generate-action-types/index.cjs" + } + }, "./package.json": "./package.json" }, "main": "./dist/index.cjs", "types": "./dist/index.d.cts", + "bin": { + "messenger-generate-action-types": "./dist/generate-action-types/cli.mjs" + }, "files": [ "dist/" ], @@ -46,17 +59,39 @@ "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose", "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch" }, + "dependencies": { + "@metamask/utils": "^11.9.0" + }, "devDependencies": { "@metamask/auto-changelog": "^3.4.4", "@ts-bridge/cli": "^0.6.4", "@types/jest": "^29.5.14", + "@types/yargs": "^17.0.32", "deepmerge": "^4.2.2", + "eslint": "^9.39.1", "immer": "^9.0.6", "jest": "^29.7.0", "ts-jest": "^29.2.5", "typedoc": "^0.25.13", "typedoc-plugin-missing-exports": "^2.0.0", - "typescript": "~5.3.3" + "typescript": "~5.3.3", + "yargs": "^17.7.2" + }, + "peerDependencies": { + "eslint": ">=8", + "typescript": "~5.3.3", + "yargs": "^17.7.2" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "yargs": { + "optional": true + } }, "engines": { "node": "^18.18 || >=20" diff --git a/packages/messenger/src/generate-action-types/check.test.ts b/packages/messenger/src/generate-action-types/check.test.ts new file mode 100644 index 00000000000..53a87d5dbe1 --- /dev/null +++ b/packages/messenger/src/generate-action-types/check.test.ts @@ -0,0 +1,146 @@ +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; + +import { checkActionTypesFiles } from './check'; +import { generateActionTypesContent } from './generate-content'; +import type { ControllerInfo } from './parse-controller'; + +describe('checkActionTypesFiles', () => { + let tmpDir: string; + const originalExitCode = globalThis.process.exitCode; + + beforeEach(async () => { + tmpDir = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'check-action-types-'), + ); + globalThis.process.exitCode = undefined; + }); + + afterEach(async () => { + await fs.promises.rm(tmpDir, { recursive: true, force: true }); + globalThis.process.exitCode = originalExitCode; + }); + + it('reports up to date when files match (no ESLint)', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + const content = generateActionTypesContent(controller); + await fs.promises.writeFile( + path.join(tmpDir, 'TestController-method-action-types.ts'), + content, + 'utf8', + ); + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + await checkActionTypesFiles([controller], null); + consoleSpy.mockRestore(); + + expect(globalThis.process.exitCode).toBeUndefined(); + }); + + it('reports out of date when files differ', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + await fs.promises.writeFile( + path.join(tmpDir, 'TestController-method-action-types.ts'), + '// outdated content\n', + 'utf8', + ); + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + await checkActionTypesFiles([controller], null); + consoleSpy.mockRestore(); + consoleErrorSpy.mockRestore(); + + expect(globalThis.process.exitCode).toBe(1); + }); + + it('reports missing files', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + await checkActionTypesFiles([controller], null); + consoleSpy.mockRestore(); + consoleErrorSpy.mockRestore(); + + expect(globalThis.process.exitCode).toBe(1); + }); + + it('reports non-ENOENT errors when accessing files', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + // Mock fs.promises.access to throw a non-ENOENT error + const accessSpy = jest + .spyOn(fs.promises, 'access') + .mockRejectedValue(Object.assign(new Error('EPERM'), { code: 'EPERM' })); + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + await checkActionTypesFiles([controller], null); + + expect(consoleErrorSpy).toHaveBeenCalledWith( + expect.stringContaining('Error reading'), + expect.anything(), + ); + expect(globalThis.process.exitCode).toBe(1); + + accessSpy.mockRestore(); + consoleSpy.mockRestore(); + consoleErrorSpy.mockRestore(); + }); + + it('uses ESLint when provided', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + const content = generateActionTypesContent(controller); + await fs.promises.writeFile( + path.join(tmpDir, 'TestController-method-action-types.ts'), + content, + 'utf8', + ); + + const mockEslint = { + instance: { lintFiles: jest.fn().mockResolvedValue([]) }, + static: { + outputFixes: jest.fn().mockResolvedValue(undefined), + getErrorResults: jest.fn().mockReturnValue([]), + }, + }; + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + await checkActionTypesFiles([controller], mockEslint); + consoleSpy.mockRestore(); + + expect(mockEslint.instance.lintFiles).toHaveBeenCalled(); + expect(mockEslint.static.outputFixes).toHaveBeenCalled(); + expect(globalThis.process.exitCode).toBeUndefined(); + }); +}); diff --git a/packages/messenger/src/generate-action-types/check.ts b/packages/messenger/src/generate-action-types/check.ts new file mode 100644 index 00000000000..661f0664dcb --- /dev/null +++ b/packages/messenger/src/generate-action-types/check.ts @@ -0,0 +1,115 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { generateActionTypesContent } from './generate-content'; +import type { ControllerInfo } from './parse-controller'; +import type { ESLint } from './types'; + +/** + * Checks if generated action types files are up to date. + * + * @param controllers - Array of controller information objects. + * @param eslint - Optional ESLint instance and static methods for formatting. + */ +export async function checkActionTypesFiles( + controllers: ControllerInfo[], + eslint: ESLint | null, +): Promise { + let hasErrors = false; + + const fileComparisonJobs: { + expectedTempFile: string; + actualFile: string; + baseFileName: string; + }[] = []; + + try { + for (const controller of controllers) { + console.log(`\nšŸ”§ Checking ${controller.name}...`); + const outputDir = path.dirname(controller.filePath); + const baseFileName = path.basename(controller.filePath, '.ts'); + const actualFile = path.join( + outputDir, + `${baseFileName}-method-action-types.ts`, + ); + + const expectedContent = generateActionTypesContent(controller); + const expectedTempFile = actualFile.replace('.ts', '.tmp.ts'); + + try { + await fs.promises.access(actualFile); + + await fs.promises.writeFile(expectedTempFile, expectedContent, 'utf8'); + + fileComparisonJobs.push({ + expectedTempFile, + actualFile, + baseFileName, + }); + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') { + console.error( + `āŒ ${baseFileName}-method-action-types.ts does not exist`, + ); + } else { + console.error( + `āŒ Error reading ${baseFileName}-method-action-types.ts:`, + error, + ); + } + hasErrors = true; + } + } + + if (fileComparisonJobs.length > 0) { + if (eslint) { + console.log('\nšŸ“ Running ESLint to compare files...'); + + const results = await eslint.instance.lintFiles( + fileComparisonJobs.map((job) => job.expectedTempFile), + ); + await eslint.static.outputFixes(results); + } + + for (const job of fileComparisonJobs) { + const expectedContent = await fs.promises.readFile( + job.expectedTempFile, + 'utf8', + ); + const actualContent = await fs.promises.readFile( + job.actualFile, + 'utf8', + ); + + if (expectedContent === actualContent) { + console.log( + `āœ… ${job.baseFileName}-method-action-types.ts is up to date`, + ); + } else { + console.error( + `āŒ ${job.baseFileName}-method-action-types.ts is out of date`, + ); + hasErrors = true; + } + } + } + } finally { + for (const job of fileComparisonJobs) { + try { + await fs.promises.unlink(job.expectedTempFile); + } catch { + // Ignore cleanup errors + } + } + } + + if (hasErrors) { + console.error('\nšŸ’„ Some action type files are out of date or missing.'); + console.error( + 'Run `yarn generate-method-action-types --fix` to update them.', + ); + globalThis.process.exitCode = 1; + } else { + console.log('\nšŸŽ‰ All action type files are up to date!'); + } +} diff --git a/packages/messenger/src/generate-action-types/cli.ts b/packages/messenger/src/generate-action-types/cli.ts new file mode 100644 index 00000000000..561cd2965b8 --- /dev/null +++ b/packages/messenger/src/generate-action-types/cli.ts @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +import yargs from 'yargs'; + +import { checkActionTypesFiles } from './check'; +import { generateAllActionTypesFiles } from './fix'; +import { findControllersWithExposedMethods } from './parse-controller'; +import type { ESLint } from './types'; + +type CommandLineArguments = { + check: boolean; + fix: boolean; + controllerPath: string; +}; + +/** + * Uses `yargs` to parse the arguments given to the script. + * + * @returns The command line arguments. + */ +async function parseCommandLineArguments(): Promise { + const { + check, + fix, + path: controllerPath, + } = await yargs(globalThis.process.argv.slice(2)) + .command( + '$0 [path]', + 'Generate method action types for a controller messenger', + (yargsInstance) => { + yargsInstance.positional('path', { + type: 'string', + description: 'Path to the folder where controllers are located', + default: 'src', + }); + }, + ) + .option('check', { + type: 'boolean', + description: 'Check if generated action type files are up to date', + default: false, + }) + .option('fix', { + type: 'boolean', + description: 'Generate/update action type files', + default: false, + }) + .help() + .check((argv) => { + if (!argv.check && !argv.fix) { + throw new Error('Either --check or --fix must be provided.\n'); + } + return true; + }).argv; + + return { + check, + fix, + controllerPath: controllerPath as string, + }; +} + +/** + * Attempt to load ESLint from the current project. Returns null if unavailable. + * + * @returns An ESLint object with instance and static methods, or null if unavailable. + */ +async function loadESLint(): Promise { + try { + const { ESLint: ESLintClass } = await import('eslint'); + const instance = new ESLintClass({ + fix: true, + errorOnUnmatchedPattern: false, + }); + return { instance, static: ESLintClass }; + } catch { + return null; + } +} + +/** + * Main entry point for the CLI. + */ +async function main(): Promise { + const { fix, controllerPath } = await parseCommandLineArguments(); + + console.log('šŸ” Searching for controllers with MESSENGER_EXPOSED_METHODS...'); + + const controllers = await findControllersWithExposedMethods(controllerPath); + + if (controllers.length === 0) { + console.log('āš ļø No controllers found with MESSENGER_EXPOSED_METHODS'); + return; + } + + console.log( + `šŸ“¦ Found ${controllers.length} controller(s) with exposed methods`, + ); + + const eslint = await loadESLint(); + + if (fix) { + await generateAllActionTypesFiles(controllers, eslint); + console.log('\nšŸŽ‰ All action types generated successfully!'); + } else { + await checkActionTypesFiles(controllers, eslint); + } +} + +main().catch((error) => { + console.error('āŒ Script failed:', error); + globalThis.process.exitCode = 1; +}); diff --git a/packages/messenger/src/generate-action-types/fix.test.ts b/packages/messenger/src/generate-action-types/fix.test.ts new file mode 100644 index 00000000000..110a1cf9358 --- /dev/null +++ b/packages/messenger/src/generate-action-types/fix.test.ts @@ -0,0 +1,134 @@ +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; + +import { generateAllActionTypesFiles } from './fix'; +import { generateActionTypesContent } from './generate-content'; +import type { ControllerInfo } from './parse-controller'; + +describe('generateAllActionTypesFiles', () => { + let tmpDir: string; + const originalExitCode = globalThis.process.exitCode; + + beforeEach(async () => { + tmpDir = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'fix-action-types-'), + ); + globalThis.process.exitCode = undefined; + }); + + afterEach(async () => { + await fs.promises.rm(tmpDir, { recursive: true, force: true }); + globalThis.process.exitCode = originalExitCode; + }); + + it('generates files for controllers (no ESLint)', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + await generateAllActionTypesFiles([controller], null); + consoleSpy.mockRestore(); + + const outputFile = path.join( + tmpDir, + 'TestController-method-action-types.ts', + ); + const content = await fs.promises.readFile(outputFile, 'utf8'); + const expected = generateActionTypesContent(controller); + + expect(content).toBe(expected); + }); + + it('generates files for multiple controllers', async () => { + const controllers: ControllerInfo[] = [ + { + name: 'FooController', + filePath: path.join(tmpDir, 'FooController.ts'), + methods: [{ name: 'doFoo', jsDoc: '' }], + }, + { + name: 'BarService', + filePath: path.join(tmpDir, 'BarService.ts'), + methods: [{ name: 'doBar', jsDoc: '' }], + }, + ]; + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + await generateAllActionTypesFiles(controllers, null); + consoleSpy.mockRestore(); + + const fooFile = path.join(tmpDir, 'FooController-method-action-types.ts'); + const barFile = path.join(tmpDir, 'BarService-method-action-types.ts'); + + const fooContent = await fs.promises.readFile(fooFile, 'utf8'); + const barContent = await fs.promises.readFile(barFile, 'utf8'); + + expect(fooContent).toContain('FooController'); + expect(barContent).toContain('BarService'); + }); + + it('invokes ESLint when provided', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + const mockEslint = { + instance: { lintFiles: jest.fn().mockResolvedValue([]) }, + static: { + outputFixes: jest.fn().mockResolvedValue(undefined), + getErrorResults: jest.fn().mockReturnValue([]), + }, + }; + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + await generateAllActionTypesFiles([controller], mockEslint); + consoleSpy.mockRestore(); + + expect(mockEslint.instance.lintFiles).toHaveBeenCalledWith([ + path.join(tmpDir, 'TestController-method-action-types.ts'), + ]); + expect(mockEslint.static.outputFixes).toHaveBeenCalled(); + expect(mockEslint.static.getErrorResults).toHaveBeenCalled(); + }); + + it('sets exitCode when ESLint reports errors', async () => { + const controller: ControllerInfo = { + name: 'TestController', + filePath: path.join(tmpDir, 'TestController.ts'), + methods: [{ name: 'doStuff', jsDoc: '' }], + }; + + const mockEslint = { + instance: { + lintFiles: jest.fn().mockResolvedValue([{ filePath: 'test.ts' }]), + }, + static: { + outputFixes: jest.fn().mockResolvedValue(undefined), + getErrorResults: jest + .fn() + .mockReturnValue([{ filePath: 'test.ts', messages: ['err'] }]), + }, + }; + + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + await generateAllActionTypesFiles([controller], mockEslint); + + expect(globalThis.process.exitCode).toBe(1); + expect(consoleErrorSpy).toHaveBeenCalledWith( + 'āŒ ESLint errors:', + expect.anything(), + ); + + consoleSpy.mockRestore(); + consoleErrorSpy.mockRestore(); + }); +}); diff --git a/packages/messenger/src/generate-action-types/fix.ts b/packages/messenger/src/generate-action-types/fix.ts new file mode 100644 index 00000000000..8ca8d95305c --- /dev/null +++ b/packages/messenger/src/generate-action-types/fix.ts @@ -0,0 +1,48 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { generateActionTypesContent } from './generate-content'; +import type { ControllerInfo } from './parse-controller'; +import type { ESLint } from './types'; + +/** + * Generates action types files for all controllers. + * + * @param controllers - Array of controller information objects. + * @param eslint - Optional ESLint instance and static methods for formatting. + */ +export async function generateAllActionTypesFiles( + controllers: ControllerInfo[], + eslint: ESLint | null, +): Promise { + const outputFiles: string[] = []; + + for (const controller of controllers) { + console.log(`\nšŸ”§ Processing ${controller.name}...`); + const outputDir = path.dirname(controller.filePath); + const baseFileName = path.basename(controller.filePath, '.ts'); + const outputFile = path.join( + outputDir, + `${baseFileName}-method-action-types.ts`, + ); + + const generatedContent = generateActionTypesContent(controller); + await fs.promises.writeFile(outputFile, generatedContent, 'utf8'); + outputFiles.push(outputFile); + console.log(`āœ… Generated action types for ${controller.name}`); + } + + if (outputFiles.length > 0 && eslint) { + console.log('\nšŸ“ Running ESLint on generated files...'); + + const results = await eslint.instance.lintFiles(outputFiles); + await eslint.static.outputFixes(results); + const errors = eslint.static.getErrorResults(results); + if (errors.length > 0) { + console.error('āŒ ESLint errors:', errors); + globalThis.process.exitCode = 1; + } else { + console.log('āœ… ESLint formatting applied'); + } + } +} diff --git a/packages/messenger/src/generate-action-types/generate-content.test.ts b/packages/messenger/src/generate-action-types/generate-content.test.ts new file mode 100644 index 00000000000..acf3a6763cd --- /dev/null +++ b/packages/messenger/src/generate-action-types/generate-content.test.ts @@ -0,0 +1,86 @@ +import { generateActionTypesContent } from './generate-content'; +import type { ControllerInfo } from './parse-controller'; + +describe('generateActionTypesContent', () => { + it('generates action types for a controller with one method', () => { + const controller: ControllerInfo = { + name: 'FooController', + filePath: '/some/path/FooController.ts', + + methods: [ + { + name: 'doSomething', + jsDoc: '', + signature: 'doSomething', + }, + ], + }; + + const result = generateActionTypesContent(controller); + + expect(result).toContain( + 'This file is auto generated by `@metamask/messenger/generate-action-types`.', + ); + expect(result).toContain( + "import type { FooController } from './FooController';", + ); + expect(result).toContain('export type FooControllerDoSomethingAction = {'); + expect(result).toContain('type: `FooController:doSomething`;'); + expect(result).toContain("handler: FooController['doSomething'];"); + expect(result).toContain( + 'export type FooControllerMethodActions = FooControllerDoSomethingAction;', + ); + }); + + it('generates action types for a controller with multiple methods', () => { + const controller: ControllerInfo = { + name: 'BarController', + filePath: '/some/path/BarController.ts', + + methods: [ + { name: 'methodA', jsDoc: '' }, + { name: 'methodB', jsDoc: '' }, + ], + }; + + const result = generateActionTypesContent(controller); + + expect(result).toContain('export type BarControllerMethodAAction = {'); + expect(result).toContain('export type BarControllerMethodBAction = {'); + expect(result).toContain( + 'export type BarControllerMethodActions = BarControllerMethodAAction | BarControllerMethodBAction;', + ); + }); + + it('includes JSDoc comments when present', () => { + const controller: ControllerInfo = { + name: 'FooController', + filePath: '/some/path/FooController.ts', + + methods: [ + { + name: 'doSomething', + jsDoc: '/**\n * Does something.\n */', + signature: 'doSomething', + }, + ], + }; + + const result = generateActionTypesContent(controller); + + expect(result).toContain('/**\n * Does something.\n */'); + }); + + it('generates no union type for controllers with no methods', () => { + const controller: ControllerInfo = { + name: 'EmptyController', + filePath: '/some/path/EmptyController.ts', + + methods: [], + }; + + const result = generateActionTypesContent(controller); + + expect(result).not.toContain('EmptyControllerMethodActions'); + }); +}); diff --git a/packages/messenger/src/generate-action-types/generate-content.ts b/packages/messenger/src/generate-action-types/generate-content.ts new file mode 100644 index 00000000000..0a8804b0a51 --- /dev/null +++ b/packages/messenger/src/generate-action-types/generate-content.ts @@ -0,0 +1,53 @@ +import * as path from 'node:path'; + +import type { ControllerInfo } from './parse-controller'; + +/** + * Generates the content for the action types file. + * + * @param controller - The controller information object. + * @returns The content for the action types file. + */ +export function generateActionTypesContent(controller: ControllerInfo): string { + const baseFileName = path.basename(controller.filePath, '.ts'); + const controllerImportPath = `./${baseFileName}`; + + let content = `/** + * This file is auto generated by \`@metamask/messenger/generate-action-types\`. + * Do not edit manually. + */ + +import type { ${controller.name} } from '${controllerImportPath}'; + +`; + + const actionTypeNames: string[] = []; + + for (const method of controller.methods) { + const capitalizedName = + method.name.charAt(0).toUpperCase() + method.name.slice(1); + const actionTypeName = `${controller.name}${capitalizedName}Action`; + const actionString = `${controller.name}:${method.name}`; + + actionTypeNames.push(actionTypeName); + + if (method.jsDoc) { + content += `${method.jsDoc}\n`; + } + + content += `export type ${actionTypeName} = { + type: \`${actionString}\`; + handler: ${controller.name}['${method.name}']; +};\n\n`; + } + + if (actionTypeNames.length > 0) { + const unionTypeName = `${controller.name}MethodActions`; + content += `/** + * Union of all ${controller.name} action types. + */ +export type ${unionTypeName} = ${actionTypeNames.join(' | ')};\n`; + } + + return `${content.trimEnd()}\n`; +} diff --git a/packages/messenger/src/generate-action-types/index.ts b/packages/messenger/src/generate-action-types/index.ts new file mode 100644 index 00000000000..f04a1b902b0 --- /dev/null +++ b/packages/messenger/src/generate-action-types/index.ts @@ -0,0 +1,9 @@ +export { checkActionTypesFiles } from './check'; +export { generateAllActionTypesFiles } from './fix'; +export { generateActionTypesContent } from './generate-content'; +export type { ControllerInfo, MethodInfo } from './parse-controller'; +export { + findControllersWithExposedMethods, + parseControllerFile, +} from './parse-controller'; +export type { ESLint } from './types'; diff --git a/packages/messenger/src/generate-action-types/parse-controller.test.ts b/packages/messenger/src/generate-action-types/parse-controller.test.ts new file mode 100644 index 00000000000..c5f3d6e48a4 --- /dev/null +++ b/packages/messenger/src/generate-action-types/parse-controller.test.ts @@ -0,0 +1,507 @@ +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; + +import { + findControllersWithExposedMethods, + parseControllerFile, +} from './parse-controller'; + +describe('parseControllerFile', () => { + let tmpDir: string; + + beforeEach(async () => { + tmpDir = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'parse-controller-'), + ); + }); + + afterEach(async () => { + await fs.promises.rm(tmpDir, { recursive: true, force: true }); + }); + + it('extracts controller info from a file with MESSENGER_EXPOSED_METHODS', async () => { + const controllerFile = path.join(tmpDir, 'TestController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff'] as const; + +class TestController { + /** + * Does stuff. + */ + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).toStrictEqual({ + name: 'TestController', + filePath: controllerFile, + methods: [ + { + name: 'doStuff', + jsDoc: '/**\n * Does stuff.\n */', + }, + ], + }); + }); + + it('returns null for a file without MESSENGER_EXPOSED_METHODS', async () => { + const controllerFile = path.join(tmpDir, 'NoExposed.ts'); + await fs.promises.writeFile( + controllerFile, + ` +class NoExposedController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).toBeNull(); + }); + + it('returns null for a file with empty MESSENGER_EXPOSED_METHODS', async () => { + const controllerFile = path.join(tmpDir, 'EmptyController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = [] as const; + +class EmptyController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).toBeNull(); + }); + + it('handles array literals without as const', async () => { + const controllerFile = path.join(tmpDir, 'PlainArrayController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff']; + +class PlainArrayController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods.map((method) => method.name)).toStrictEqual([ + 'doStuff', + ]); + }); + + it('works with Service class names', async () => { + const serviceFile = path.join(tmpDir, 'TestService.ts'); + await fs.promises.writeFile( + serviceFile, + ` +const MESSENGER_EXPOSED_METHODS = ['fetchData'] as const; + +class TestService { + fetchData() { + return []; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(serviceFile); + + expect(result).not.toBeNull(); + expect(result?.name).toBe('TestService'); + }); + + it('extracts methods without JSDoc', async () => { + const controllerFile = path.join(tmpDir, 'NoDocController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff'] as const; + +class NoDocController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods[0].jsDoc).toBe(''); + }); + + it('handles inherited methods via type checker', async () => { + // Create a tsconfig.json so the type checker can work + await fs.promises.writeFile( + path.join(tmpDir, 'tsconfig.json'), + JSON.stringify({ + compilerOptions: { + target: 'ES2020', + module: 'commonjs', + strict: true, + }, + include: ['./*.ts'], + }), + 'utf8', + ); + + await fs.promises.writeFile( + path.join(tmpDir, 'BaseController.ts'), + ` +export class BaseController { + /** + * Base method. + */ + baseMethod() { + return 'base'; + } +} +`, + 'utf8', + ); + + const controllerFile = path.join(tmpDir, 'ChildController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +import { BaseController } from './BaseController'; + +const MESSENGER_EXPOSED_METHODS = ['doStuff', 'baseMethod'] as const; + +class ChildController extends BaseController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods).toHaveLength(2); + expect(result?.methods[0].name).toBe('doStuff'); + expect(result?.methods[1].name).toBe('baseMethod'); + expect(result?.methods[1].jsDoc).toContain('Base method.'); + }); + + it('handles inherited methods without JSDoc', async () => { + await fs.promises.writeFile( + path.join(tmpDir, 'tsconfig.json'), + JSON.stringify({ + compilerOptions: { target: 'ES2020', module: 'commonjs', strict: true }, + include: ['./*.ts'], + }), + 'utf8', + ); + + await fs.promises.writeFile( + path.join(tmpDir, 'BaseNoDoc.ts'), + ` +export class BaseNoDoc { + baseMethod() { + return 'base'; + } +} +`, + 'utf8', + ); + + const controllerFile = path.join(tmpDir, 'ChildNoDocController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +import { BaseNoDoc } from './BaseNoDoc'; + +const MESSENGER_EXPOSED_METHODS = ['doStuff', 'baseMethod'] as const; + +class ChildNoDocController extends BaseNoDoc { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods).toHaveLength(2); + expect(result?.methods[1].name).toBe('baseMethod'); + // Method without JSDoc should have empty string + expect(result?.methods[1].jsDoc).toBe(''); + }); + + it('handles exposed method not found in hierarchy', async () => { + await fs.promises.writeFile( + path.join(tmpDir, 'tsconfig.json'), + JSON.stringify({ + compilerOptions: { target: 'ES2020', module: 'commonjs', strict: true }, + include: ['./*.ts'], + }), + 'utf8', + ); + + const controllerFile = path.join(tmpDir, 'MissingMethodController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff', 'nonExistentMethod'] as const; + +class MissingMethodController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods).toHaveLength(2); + expect(result?.methods[1].name).toBe('nonExistentMethod'); + expect(result?.methods[1].jsDoc).toBe(''); + }); + + it('formats JSDoc with empty middle lines', async () => { + const controllerFile = path.join(tmpDir, 'EmptyLineDocController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff'] as const; + +class EmptyLineDocController { + /** + * First line. + * + * After empty line. + */ + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods[0].jsDoc).toContain(' *\n'); + expect(result?.methods[0].jsDoc).toContain(' * First line.'); + expect(result?.methods[0].jsDoc).toContain(' * After empty line.'); + }); + + it('extracts JSDoc with non-standard middle lines', async () => { + const controllerFile = path.join(tmpDir, 'WeirdDocController.ts'); + // Write file with a JSDoc containing a line without * prefix and an empty line without * prefix + const source = [ + '', + "const MESSENGER_EXPOSED_METHODS = ['doStuff'] as const;", + '', + 'class WeirdDocController {', + ' /**', + ' This line has no asterisk prefix.', + ' ', + ' */', + ' doStuff() {', + ' return true;', + ' }', + '}', + '', + ].join('\n'); + await fs.promises.writeFile(controllerFile, source, 'utf8'); + + const result = await parseControllerFile(controllerFile); + + expect(result).not.toBeNull(); + expect(result?.methods[0].jsDoc).toContain( + ' * This line has no asterisk prefix.', + ); + // The empty line (only whitespace, no *) should become ' *' + expect(result?.methods[0].jsDoc).toContain(' *\n'); + }); + + it('handles inherited methods with malformed tsconfig', async () => { + // Write an invalid tsconfig to trigger readConfigFile error + await fs.promises.writeFile( + path.join(tmpDir, 'tsconfig.json'), + 'this is not valid json', + 'utf8', + ); + + const controllerFile = path.join(tmpDir, 'BadTsconfigController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff', 'inherited'] as const; + +class BadTsconfigController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + const result = await parseControllerFile(controllerFile); + + expect(result).toBeNull(); + expect(consoleErrorSpy).toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); + }); + + it('handles inherited methods when tsconfig is missing', async () => { + // No tsconfig.json in tmpDir — createProgramForFile should fail with assert + const controllerFile = path.join(tmpDir, 'NoTsconfigController.ts'); + await fs.promises.writeFile( + controllerFile, + ` +const MESSENGER_EXPOSED_METHODS = ['doStuff', 'inheritedMethod'] as const; + +class NoTsconfigController { + doStuff() { + return true; + } +} +`, + 'utf8', + ); + + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + const result = await parseControllerFile(controllerFile); + + // Should return null because assert fails when type checker can't be created + expect(result).toBeNull(); + expect(consoleErrorSpy).toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); + }); + + it('returns null and logs error for invalid file', async () => { + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + + const result = await parseControllerFile('/nonexistent/file.ts'); + + expect(result).toBeNull(); + expect(consoleErrorSpy).toHaveBeenCalled(); + consoleErrorSpy.mockRestore(); + }); +}); + +describe('findControllersWithExposedMethods', () => { + let tmpDir: string; + + beforeEach(async () => { + tmpDir = await fs.promises.mkdtemp( + path.join(os.tmpdir(), 'find-controllers-'), + ); + }); + + afterEach(async () => { + await fs.promises.rm(tmpDir, { recursive: true, force: true }); + }); + + it('finds controllers with MESSENGER_EXPOSED_METHODS in a directory', async () => { + await fs.promises.writeFile( + path.join(tmpDir, 'FooController.ts'), + ` +const MESSENGER_EXPOSED_METHODS = ['doFoo'] as const; +class FooController { + doFoo() { return 'foo'; } +} +`, + 'utf8', + ); + + await fs.promises.writeFile( + path.join(tmpDir, 'BarController.ts'), + ` +class BarController { + doBar() { return 'bar'; } +} +`, + 'utf8', + ); + + const result = await findControllersWithExposedMethods(tmpDir); + + expect(result).toHaveLength(1); + expect(result[0].name).toBe('FooController'); + }); + + it('skips test files', async () => { + await fs.promises.writeFile( + path.join(tmpDir, 'FooController.test.ts'), + ` +const MESSENGER_EXPOSED_METHODS = ['doFoo'] as const; +class FooController { + doFoo() { return 'foo'; } +} +`, + 'utf8', + ); + + const result = await findControllersWithExposedMethods(tmpDir); + + expect(result).toHaveLength(0); + }); + + it('throws an error when the path is not a directory', async () => { + await expect( + findControllersWithExposedMethods('/nonexistent/path'), + ).rejects.toThrow('The specified path is not a directory'); + }); + + it('re-throws non-ENOENT errors from isDirectory', async () => { + const statSpy = jest + .spyOn(fs.promises, 'stat') + .mockRejectedValue( + Object.assign(new Error('EACCES'), { code: 'EACCES' }), + ); + + await expect(findControllersWithExposedMethods(tmpDir)).rejects.toThrow( + 'EACCES', + ); + + statSpy.mockRestore(); + }); +}); diff --git a/packages/messenger/src/generate-action-types/parse-controller.ts b/packages/messenger/src/generate-action-types/parse-controller.ts new file mode 100644 index 00000000000..a329120247e --- /dev/null +++ b/packages/messenger/src/generate-action-types/parse-controller.ts @@ -0,0 +1,409 @@ +import { assert, hasProperty, isObject } from '@metamask/utils'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import type { + ArrayLiteralExpression, + ClassDeclaration, + MethodDeclaration, + Node as TSNode, + Program, + SourceFile, + Type, +} from 'typescript'; +import { + ScriptTarget, + createProgram, + createSourceFile, + findConfigFile, + forEachChild, + getJSDocCommentsAndTags, + isArrayLiteralExpression, + isAsExpression, + isClassDeclaration, + isIdentifier, + isJSDoc, + isMethodDeclaration, + isStringLiteral, + isVariableStatement, + parseJsonConfigFileContent, + readConfigFile, + sys, +} from 'typescript'; + +export type MethodInfo = { + name: string; + jsDoc: string; +}; + +export type ControllerInfo = { + name: string; + filePath: string; + methods: MethodInfo[]; +}; + +type VisitorContext = { + exposedMethods: string[]; + className: string; + methods: MethodInfo[]; + sourceFile: SourceFile; +}; + +/** + * Extracts JSDoc comment from a method declaration. + * + * @param node - The method declaration node. + * @param source - The source file. + * @returns The JSDoc comment. + */ +function extractJSDoc(node: MethodDeclaration, source: SourceFile): string { + const jsDocTags = getJSDocCommentsAndTags(node); + if (jsDocTags.length === 0) { + return ''; + } + + const jsDoc = jsDocTags[0]; + if (isJSDoc(jsDoc)) { + const fullText = source.getFullText(); + const start = jsDoc.getFullStart(); + const end = jsDoc.getEnd(); + const rawJsDoc = fullText.substring(start, end).trim(); + return formatJSDoc(rawJsDoc); + } + + // istanbul ignore next: defensive check — getJSDocCommentsAndTags always returns JSDoc nodes + return ''; +} + +/** + * Formats JSDoc comments to have consistent indentation for the generated file. + * + * @param rawJsDoc - The raw JSDoc comment from the source. + * @returns The formatted JSDoc comment. + */ +function formatJSDoc(rawJsDoc: string): string { + const lines = rawJsDoc.split('\n'); + const formattedLines: string[] = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (i === 0) { + formattedLines.push('/**'); + } else if (i === lines.length - 1) { + formattedLines.push(' */'); + } else { + const trimmed = line.trim(); + if (trimmed.startsWith('*')) { + const content = trimmed.substring(1).trim(); + formattedLines.push(content ? ` * ${content}` : ' *'); + } else { + formattedLines.push(trimmed ? ` * ${trimmed}` : ' *'); + } + } + } + + return formattedLines.join('\n'); +} + +/** + * Visits AST nodes to find exposed methods and controller class. + * + * @param context - The visitor context. + * @returns A function to visit nodes. + */ +function createASTVisitor(context: VisitorContext): (node: TSNode) => void { + function visitNode(node: TSNode): void { + if (isVariableStatement(node)) { + const declaration = node.declarationList.declarations[0]; + if ( + isIdentifier(declaration.name) && + declaration.name.text === 'MESSENGER_EXPOSED_METHODS' + ) { + if (declaration.initializer) { + let arrayExpression: ArrayLiteralExpression | undefined; + + if (isArrayLiteralExpression(declaration.initializer)) { + arrayExpression = declaration.initializer; + } else if ( + isAsExpression(declaration.initializer) && + isArrayLiteralExpression(declaration.initializer.expression) + ) { + arrayExpression = declaration.initializer.expression; + } + + if (arrayExpression) { + context.exposedMethods = arrayExpression.elements + .filter(isStringLiteral) + .map((element) => element.text); + } + } + } + } + + if (isClassDeclaration(node) && node.name) { + const classText = node.name.text; + if (classText.includes('Controller') || classText.includes('Service')) { + context.className = classText; + + const seenMethods = new Set(); + for (const member of node.members) { + if ( + isMethodDeclaration(member) && + member.name && + isIdentifier(member.name) + ) { + const methodName = member.name.text; + if ( + context.exposedMethods.includes(methodName) && + !seenMethods.has(methodName) + ) { + seenMethods.add(methodName); + const jsDoc = extractJSDoc(member, context.sourceFile); + context.methods.push({ + name: methodName, + jsDoc, + }); + } + } + } + } + } + + forEachChild(node, visitNode); + } + + return visitNode; +} + +/** + * Create a TypeScript program for the given file by locating the nearest + * tsconfig.json. + * + * @param filePath - Absolute path to the source file. + * @returns A TypeScript program, or null if no tsconfig was found. + */ +function createProgramForFile(filePath: string): Program | null { + const configPath = findConfigFile( + path.dirname(filePath), + sys.fileExists.bind(sys), + 'tsconfig.json', + ); + if (!configPath) { + return null; + } + + const { config, error } = readConfigFile(configPath, sys.readFile.bind(sys)); + + if (error) { + return null; + } + + const parsedConfig = parseJsonConfigFileContent( + config, + sys, + path.dirname(configPath), + ); + + return createProgram({ + rootNames: parsedConfig.fileNames, + options: parsedConfig.options, + }); +} + +/** + * Find a class declaration with the given name in a source file. + * + * @param source - The source file to search. + * @param className - The class name to look for. + * @returns The class declaration node, or null if not found. + */ +function findClassInSourceFile( + source: SourceFile, + className: string, +): ClassDeclaration | null { + return ( + source.statements.find( + (node): node is ClassDeclaration => + isClassDeclaration(node) && node.name?.text === className, + ) ?? // istanbul ignore next: class is always found when called from parseControllerFile + null + ); +} + +/** + * Search through the class hierarchy of a TypeScript type to find the + * declaration of a method with the given name. + * + * @param classType - The class type to search. + * @param methodName - The method name to look for. + * @returns The method declaration node, or null if not found. + */ +function findMethodInHierarchy( + classType: Type, + methodName: string, +): MethodDeclaration | null { + const symbol = classType.getProperty(methodName); + if (!symbol) { + return null; + } + + const declarations = symbol.getDeclarations(); + // istanbul ignore next: defensive check — symbols from getProperty always have declarations + if (!declarations) { + return null; + } + + for (const declaration of declarations) { + if (isMethodDeclaration(declaration)) { + return declaration; + } + } + + // istanbul ignore next: defensive fallback — property found but not a method declaration + return null; +} + +/** + * Check if a path is a directory. + * + * @param pathValue - The path to check. + * @returns True if the path is a directory, false otherwise. + */ +async function isDirectory(pathValue: string): Promise { + try { + const stats = await fs.promises.stat(pathValue); + return stats.isDirectory(); + } catch (error) { + if ( + isObject(error) && + hasProperty(error, 'code') && + error.code === 'ENOENT' + ) { + return false; + } + + throw error; + } +} + +/** + * Parses a controller file to extract exposed methods and their metadata. + * + * @param filePath - Path to the controller file to parse. + * @returns Controller information or null if parsing fails. + */ +export async function parseControllerFile( + filePath: string, +): Promise { + try { + const content = await fs.promises.readFile(filePath, 'utf8'); + const source = createSourceFile( + filePath, + content, + ScriptTarget.Latest, + true, + ); + + const context: VisitorContext = { + exposedMethods: [], + className: '', + methods: [], + sourceFile: source, + }; + + createASTVisitor(context)(source); + + if (context.exposedMethods.length === 0 || !context.className) { + return null; + } + + const foundMethodNames = new Set( + context.methods.map((method) => method.name), + ); + + const inheritedMethodNames = context.exposedMethods.filter( + (name) => !foundMethodNames.has(name), + ); + + if (inheritedMethodNames.length > 0) { + const program = createProgramForFile(filePath); + const checker = program?.getTypeChecker(); + const programSourceFile = program?.getSourceFile(filePath); + + assert( + checker, + `Type checker could not be created for "${filePath}". Ensure a valid tsconfig.json is present.`, + ); + + assert( + programSourceFile, + `Source file "${filePath}" not found in program.`, + ); + + const classNode = findClassInSourceFile( + programSourceFile, + context.className, + ); + + assert( + classNode, + `Class "${context.className}" not found in "${filePath}".`, + ); + + const classType = checker.getTypeAtLocation(classNode); + for (const methodName of inheritedMethodNames) { + const methodDeclaration = findMethodInHierarchy(classType, methodName); + + const jsDoc = methodDeclaration + ? extractJSDoc(methodDeclaration, methodDeclaration.getSourceFile()) + : ''; + context.methods.push({ name: methodName, jsDoc }); + } + } + + return { + name: context.className, + filePath, + methods: context.methods, + }; + } catch (error) { + console.error(`Error parsing ${filePath}:`, error); + return null; + } +} + +/** + * Finds all controller files that have MESSENGER_EXPOSED_METHODS constants. + * + * @param controllerPath - Path to the folder where controllers are located. + * @returns A list of controller information objects. + */ +export async function findControllersWithExposedMethods( + controllerPath: string, +): Promise { + const srcPath = path.resolve(globalThis.process.cwd(), controllerPath); + const controllers: ControllerInfo[] = []; + + if (!(await isDirectory(srcPath))) { + throw new Error(`The specified path is not a directory: ${srcPath}`); + } + + const srcFiles = await fs.promises.readdir(srcPath); + + for (const file of srcFiles) { + if (!file.endsWith('.ts') || file.endsWith('.test.ts')) { + continue; + } + + const filePath = path.join(srcPath, file); + const content = await fs.promises.readFile(filePath, 'utf8'); + + if (content.includes('MESSENGER_EXPOSED_METHODS')) { + const controllerInfo = await parseControllerFile(filePath); + if (controllerInfo) { + controllers.push(controllerInfo); + } + } + } + + return controllers; +} diff --git a/packages/messenger/src/generate-action-types/types.ts b/packages/messenger/src/generate-action-types/types.ts new file mode 100644 index 00000000000..1d7d3682efe --- /dev/null +++ b/packages/messenger/src/generate-action-types/types.ts @@ -0,0 +1,11 @@ +type LintResult = { output?: string; filePath: string }; + +export type ESLint = { + instance: { + lintFiles(files: string[]): Promise; + }; + static: { + outputFixes(results: LintResult[]): Promise; + getErrorResults(results: LintResult[]): LintResult[]; + }; +}; diff --git a/packages/multichain-account-service/package.json b/packages/multichain-account-service/package.json index beab7a520f0..698b4fca529 100644 --- a/packages/multichain-account-service/package.json +++ b/packages/multichain-account-service/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/multichain-account-service", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/multichain-account-service", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/multichain-account-service/src/MultichainAccountService-method-action-types.ts b/packages/multichain-account-service/src/MultichainAccountService-method-action-types.ts index fffb94f7f25..4748ef8a4bd 100644 --- a/packages/multichain-account-service/src/MultichainAccountService-method-action-types.ts +++ b/packages/multichain-account-service/src/MultichainAccountService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/name-controller/package.json b/packages/name-controller/package.json index 2251b8b1ff6..55b9bdf4541 100644 --- a/packages/name-controller/package.json +++ b/packages/name-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/name-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/name-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "prepare-manifest:preview": "../../scripts/prepare-preview-manifest.sh", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", diff --git a/packages/name-controller/src/NameController-method-action-types.ts b/packages/name-controller/src/NameController-method-action-types.ts index 5990d7a2618..3b1fcaf69ee 100644 --- a/packages/name-controller/src/NameController-method-action-types.ts +++ b/packages/name-controller/src/NameController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/network-enablement-controller/package.json b/packages/network-enablement-controller/package.json index 793427e3248..f11122528ee 100644 --- a/packages/network-enablement-controller/package.json +++ b/packages/network-enablement-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/network-enablement-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/network-enablement-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/network-enablement-controller/src/NetworkEnablementController-method-action-types.ts b/packages/network-enablement-controller/src/NetworkEnablementController-method-action-types.ts index 293f2623e5a..d22b9ad48d4 100644 --- a/packages/network-enablement-controller/src/NetworkEnablementController-method-action-types.ts +++ b/packages/network-enablement-controller/src/NetworkEnablementController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/notification-services-controller/package.json b/packages/notification-services-controller/package.json index df8c28fbd01..0d9e83ddf5a 100644 --- a/packages/notification-services-controller/package.json +++ b/packages/notification-services-controller/package.json @@ -93,8 +93,8 @@ "changelog:update": "../../scripts/update-changelog.sh @metamask/notification-services-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/notification-services-controller", "generate-method-action-types": "yarn generate-method-action-types:notifications-services-controller \"$@\" && yarn generate-method-action-types:notifications-services-push-controller \"$@\"", - "generate-method-action-types:notifications-services-controller": "tsx ../../scripts/generate-method-action-types.ts src/NotificationServicesController", - "generate-method-action-types:notifications-services-push-controller": "tsx ../../scripts/generate-method-action-types.ts src/NotificationServicesPushController", + "generate-method-action-types:notifications-services-controller": "tsx ../../packages/messenger/src/generate-action-types/cli.ts src/NotificationServicesController", + "generate-method-action-types:notifications-services-push-controller": "tsx ../../packages/messenger/src/generate-action-types/cli.ts src/NotificationServicesPushController", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController-method-action-types.ts b/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController-method-action-types.ts index 7f89067973a..ec89daa069d 100644 --- a/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController-method-action-types.ts +++ b/packages/notification-services-controller/src/NotificationServicesController/NotificationServicesController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/notification-services-controller/src/NotificationServicesPushController/NotificationServicesPushController-method-action-types.ts b/packages/notification-services-controller/src/NotificationServicesPushController/NotificationServicesPushController-method-action-types.ts index 0dae43eb522..5bbe56c66cf 100644 --- a/packages/notification-services-controller/src/NotificationServicesPushController/NotificationServicesPushController-method-action-types.ts +++ b/packages/notification-services-controller/src/NotificationServicesPushController/NotificationServicesPushController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/permission-controller/package.json b/packages/permission-controller/package.json index 352abd393b3..6f2006563c5 100644 --- a/packages/permission-controller/package.json +++ b/packages/permission-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/permission-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/permission-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/permission-controller/src/PermissionController-method-action-types.ts b/packages/permission-controller/src/PermissionController-method-action-types.ts index b434f719e89..fbabee895fc 100644 --- a/packages/permission-controller/src/PermissionController-method-action-types.ts +++ b/packages/permission-controller/src/PermissionController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/permission-controller/src/SubjectMetadataController-method-action-types.ts b/packages/permission-controller/src/SubjectMetadataController-method-action-types.ts index 2d5608af6e3..3ddc1c9e936 100644 --- a/packages/permission-controller/src/SubjectMetadataController-method-action-types.ts +++ b/packages/permission-controller/src/SubjectMetadataController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/permission-log-controller/package.json b/packages/permission-log-controller/package.json index 080c73294d3..2f24567a530 100644 --- a/packages/permission-log-controller/package.json +++ b/packages/permission-log-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/permission-log-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/permission-log-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/permission-log-controller/src/PermissionLogController-method-action-types.ts b/packages/permission-log-controller/src/PermissionLogController-method-action-types.ts index d4d6a321218..6784b6e17f0 100644 --- a/packages/permission-log-controller/src/PermissionLogController-method-action-types.ts +++ b/packages/permission-log-controller/src/PermissionLogController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/preferences-controller/package.json b/packages/preferences-controller/package.json index 208ec3b1129..13d78ef5f9d 100644 --- a/packages/preferences-controller/package.json +++ b/packages/preferences-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/preferences-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/preferences-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/preferences-controller/src/PreferencesController-method-action-types.ts b/packages/preferences-controller/src/PreferencesController-method-action-types.ts index 48a135c6ad5..517f4501870 100644 --- a/packages/preferences-controller/src/PreferencesController-method-action-types.ts +++ b/packages/preferences-controller/src/PreferencesController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/profile-metrics-controller/package.json b/packages/profile-metrics-controller/package.json index b9c164464dc..04db8c6c6c9 100644 --- a/packages/profile-metrics-controller/package.json +++ b/packages/profile-metrics-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/profile-metrics-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/profile-metrics-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/profile-metrics-controller/src/ProfileMetricsController-method-action-types.ts b/packages/profile-metrics-controller/src/ProfileMetricsController-method-action-types.ts index 81589990bb8..11967e83a5a 100644 --- a/packages/profile-metrics-controller/src/ProfileMetricsController-method-action-types.ts +++ b/packages/profile-metrics-controller/src/ProfileMetricsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/profile-metrics-controller/src/ProfileMetricsService-method-action-types.ts b/packages/profile-metrics-controller/src/ProfileMetricsService-method-action-types.ts index 7d84bb447ab..58dd563ba4f 100644 --- a/packages/profile-metrics-controller/src/ProfileMetricsService-method-action-types.ts +++ b/packages/profile-metrics-controller/src/ProfileMetricsService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/profile-sync-controller/package.json b/packages/profile-sync-controller/package.json index 5e745e4a093..e5872843004 100644 --- a/packages/profile-sync-controller/package.json +++ b/packages/profile-sync-controller/package.json @@ -94,8 +94,8 @@ "changelog:update": "../../scripts/update-changelog.sh @metamask/profile-sync-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/profile-sync-controller", "generate-method-action-types": "yarn generate-method-action-types:authentication \"$@\" && yarn generate-method-action-types:user-storage \"$@\"", - "generate-method-action-types:authentication": "tsx ../../scripts/generate-method-action-types.ts src/controllers/authentication", - "generate-method-action-types:user-storage": "tsx ../../scripts/generate-method-action-types.ts src/controllers/user-storage", + "generate-method-action-types:authentication": "tsx ../../packages/messenger/src/generate-action-types/cli.ts src/controllers/authentication", + "generate-method-action-types:user-storage": "tsx ../../packages/messenger/src/generate-action-types/cli.ts src/controllers/user-storage", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/profile-sync-controller/src/controllers/authentication/AuthenticationController-method-action-types.ts b/packages/profile-sync-controller/src/controllers/authentication/AuthenticationController-method-action-types.ts index 9b3db73e8c5..e5457085487 100644 --- a/packages/profile-sync-controller/src/controllers/authentication/AuthenticationController-method-action-types.ts +++ b/packages/profile-sync-controller/src/controllers/authentication/AuthenticationController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController-method-action-types.ts b/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController-method-action-types.ts index 46977986548..89848312122 100644 --- a/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController-method-action-types.ts +++ b/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/ramps-controller/package.json b/packages/ramps-controller/package.json index b3470383e8d..e77ef8c2fda 100644 --- a/packages/ramps-controller/package.json +++ b/packages/ramps-controller/package.json @@ -41,7 +41,7 @@ "changelog:update": "../../scripts/update-changelog.sh @metamask/ramps-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ramps-controller", "dev": "node dev-watch.js", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/ramps-controller/src/RampsController-method-action-types.ts b/packages/ramps-controller/src/RampsController-method-action-types.ts index e1bccd50175..40fc86ad153 100644 --- a/packages/ramps-controller/src/RampsController-method-action-types.ts +++ b/packages/ramps-controller/src/RampsController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/ramps-controller/src/RampsService-method-action-types.ts b/packages/ramps-controller/src/RampsService-method-action-types.ts index 2d9acd03527..f8f267b8e79 100644 --- a/packages/ramps-controller/src/RampsService-method-action-types.ts +++ b/packages/ramps-controller/src/RampsService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/ramps-controller/src/TransakService-method-action-types.ts b/packages/ramps-controller/src/TransakService-method-action-types.ts index 78a3e64d410..035eaed558a 100644 --- a/packages/ramps-controller/src/TransakService-method-action-types.ts +++ b/packages/ramps-controller/src/TransakService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/remote-feature-flag-controller/package.json b/packages/remote-feature-flag-controller/package.json index 44ed625483c..e7eea8a8f7e 100644 --- a/packages/remote-feature-flag-controller/package.json +++ b/packages/remote-feature-flag-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/remote-feature-flag-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/remote-feature-flag-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/remote-feature-flag-controller/src/remote-feature-flag-controller-method-action-types.ts b/packages/remote-feature-flag-controller/src/remote-feature-flag-controller-method-action-types.ts index ac01480adf5..92c160dd82c 100644 --- a/packages/remote-feature-flag-controller/src/remote-feature-flag-controller-method-action-types.ts +++ b/packages/remote-feature-flag-controller/src/remote-feature-flag-controller-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/sample-controllers/package.json b/packages/sample-controllers/package.json index a9c010afe2a..aef8b7bb171 100644 --- a/packages/sample-controllers/package.json +++ b/packages/sample-controllers/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/sample-controllers", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/sample-controllers", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/sample-controllers/src/sample-gas-prices-controller-method-action-types.ts b/packages/sample-controllers/src/sample-gas-prices-controller-method-action-types.ts index ac64a1ed661..c037e1b098c 100644 --- a/packages/sample-controllers/src/sample-gas-prices-controller-method-action-types.ts +++ b/packages/sample-controllers/src/sample-gas-prices-controller-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/sample-controllers/src/sample-petnames-controller-method-action-types.ts b/packages/sample-controllers/src/sample-petnames-controller-method-action-types.ts index 1efce10c161..bb53037336d 100644 --- a/packages/sample-controllers/src/sample-petnames-controller-method-action-types.ts +++ b/packages/sample-controllers/src/sample-petnames-controller-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/seedless-onboarding-controller/package.json b/packages/seedless-onboarding-controller/package.json index 4850d487bc4..e701ecb4852 100644 --- a/packages/seedless-onboarding-controller/package.json +++ b/packages/seedless-onboarding-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/seedless-onboarding-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/seedless-onboarding-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController-method-action-types.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController-method-action-types.ts index f63e0167656..ce0ebeaf690 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController-method-action-types.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/selected-network-controller/package.json b/packages/selected-network-controller/package.json index 4e7abcaf3d2..84c20b65c82 100644 --- a/packages/selected-network-controller/package.json +++ b/packages/selected-network-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/selected-network-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/selected-network-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/selected-network-controller/src/SelectedNetworkController-method-action-types.ts b/packages/selected-network-controller/src/SelectedNetworkController-method-action-types.ts index 8f527b4bb75..ef5cb8796fc 100644 --- a/packages/selected-network-controller/src/SelectedNetworkController-method-action-types.ts +++ b/packages/selected-network-controller/src/SelectedNetworkController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/shield-controller/package.json b/packages/shield-controller/package.json index f4d16ebe2a9..fa17103a9cb 100644 --- a/packages/shield-controller/package.json +++ b/packages/shield-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/shield-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/shield-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/shield-controller/src/ShieldController-method-action-types.ts b/packages/shield-controller/src/ShieldController-method-action-types.ts index 8a2d9a7f132..139e0eeba3c 100644 --- a/packages/shield-controller/src/ShieldController-method-action-types.ts +++ b/packages/shield-controller/src/ShieldController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/signature-controller/package.json b/packages/signature-controller/package.json index b0d9c5b92b2..794e46d47d1 100644 --- a/packages/signature-controller/package.json +++ b/packages/signature-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/signature-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/signature-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/signature-controller/src/SignatureController-method-action-types.ts b/packages/signature-controller/src/SignatureController-method-action-types.ts index 3c1676c0921..c647deb1ffb 100644 --- a/packages/signature-controller/src/SignatureController-method-action-types.ts +++ b/packages/signature-controller/src/SignatureController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/storage-service/package.json b/packages/storage-service/package.json index 04855e95ec1..09bd04cc0c9 100644 --- a/packages/storage-service/package.json +++ b/packages/storage-service/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/storage-service", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/storage-service", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/storage-service/src/StorageService-method-action-types.ts b/packages/storage-service/src/StorageService-method-action-types.ts index e6a033d0249..2e2191fef72 100644 --- a/packages/storage-service/src/StorageService-method-action-types.ts +++ b/packages/storage-service/src/StorageService-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/subscription-controller/package.json b/packages/subscription-controller/package.json index 1ebaf168c7a..748b37f3d65 100644 --- a/packages/subscription-controller/package.json +++ b/packages/subscription-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/subscription-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/subscription-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/subscription-controller/src/SubscriptionController-method-action-types.ts b/packages/subscription-controller/src/SubscriptionController-method-action-types.ts index d81456aec19..f7158ee9908 100644 --- a/packages/subscription-controller/src/SubscriptionController-method-action-types.ts +++ b/packages/subscription-controller/src/SubscriptionController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/transaction-controller/package.json b/packages/transaction-controller/package.json index e46c1533f15..80294e7e411 100644 --- a/packages/transaction-controller/package.json +++ b/packages/transaction-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/transaction-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/transaction-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/packages/transaction-controller/src/TransactionController-method-action-types.ts b/packages/transaction-controller/src/TransactionController-method-action-types.ts index 7dd6e81c13e..3ddf5a29660 100644 --- a/packages/transaction-controller/src/TransactionController-method-action-types.ts +++ b/packages/transaction-controller/src/TransactionController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/transaction-pay-controller/package.json b/packages/transaction-pay-controller/package.json index 682951ed0d2..c3586a9bee5 100644 --- a/packages/transaction-pay-controller/package.json +++ b/packages/transaction-pay-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/transaction-pay-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/transaction-pay-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "prepare-manifest:preview": "../../scripts/prepare-preview-manifest.sh", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", diff --git a/packages/transaction-pay-controller/src/TransactionPayController-method-action-types.ts b/packages/transaction-pay-controller/src/TransactionPayController-method-action-types.ts index 380361c8d81..8e6d969f97f 100644 --- a/packages/transaction-pay-controller/src/TransactionPayController-method-action-types.ts +++ b/packages/transaction-pay-controller/src/TransactionPayController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/packages/user-operation-controller/package.json b/packages/user-operation-controller/package.json index 4f9cd1066ec..c787ce1326a 100644 --- a/packages/user-operation-controller/package.json +++ b/packages/user-operation-controller/package.json @@ -40,7 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh @metamask/user-operation-controller", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/user-operation-controller", - "generate-method-action-types": "tsx ../../scripts/generate-method-action-types.ts", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "prepare-manifest:preview": "../../scripts/prepare-preview-manifest.sh", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", diff --git a/packages/user-operation-controller/src/UserOperationController-method-action-types.ts b/packages/user-operation-controller/src/UserOperationController-method-action-types.ts index 33978bc98f0..22bb7918755 100644 --- a/packages/user-operation-controller/src/UserOperationController-method-action-types.ts +++ b/packages/user-operation-controller/src/UserOperationController-method-action-types.ts @@ -1,5 +1,5 @@ /** - * This file is auto generated by `scripts/generate-method-action-types.ts`. + * This file is auto generated by `@metamask/messenger/generate-action-types`. * Do not edit manually. */ diff --git a/scripts/create-package/package-template/package.json b/scripts/create-package/package-template/package.json index 4b0c39fc028..3e62b61e574 100644 --- a/scripts/create-package/package-template/package.json +++ b/scripts/create-package/package-template/package.json @@ -40,6 +40,7 @@ "build:docs": "typedoc", "changelog:update": "../../scripts/update-changelog.sh PACKAGE_NAME", "changelog:validate": "../../scripts/validate-changelog.sh PACKAGE_NAME", + "generate-method-action-types": "tsx ../../packages/messenger/src/generate-action-types/cli.ts", "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", diff --git a/scripts/generate-method-action-types.ts b/scripts/generate-method-action-types.ts deleted file mode 100755 index 841900adcc2..00000000000 --- a/scripts/generate-method-action-types.ts +++ /dev/null @@ -1,752 +0,0 @@ -#!yarn tsx - -import { assert, hasProperty, isObject } from '@metamask/utils'; -import { ESLint } from 'eslint'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as ts from 'typescript'; -import yargs from 'yargs'; - -type MethodInfo = { - name: string; - jsDoc: string; - signature: string; -}; - -type ControllerInfo = { - name: string; - filePath: string; - exposedMethods: string[]; - methods: MethodInfo[]; -}; - -/** - * The parsed command-line arguments. - */ -type CommandLineArguments = { - /** - * Whether to check if the action types files are up to date. - */ - check: boolean; - /** - * Whether to fix the action types files. - */ - fix: boolean; - /** - * Optional path to a specific controller to process. - */ - controllerPath: string; -}; - -/** - * Uses `yargs` to parse the arguments given to the script. - * - * @returns The command line arguments. - */ -async function parseCommandLineArguments(): Promise { - const { - check, - fix, - path: controllerPath, - } = await yargs(process.argv.slice(2)) - .command( - '$0 [path]', - 'Generate method action types for a controller messenger', - (yargsInstance) => { - yargsInstance.positional('path', { - type: 'string', - description: 'Path to the folder where controllers are located', - default: 'src', - }); - }, - ) - .option('check', { - type: 'boolean', - description: 'Check if generated action type files are up to date', - default: false, - }) - .option('fix', { - type: 'boolean', - description: 'Generate/update action type files', - default: false, - }) - .help() - .check((argv) => { - if (!argv.check && !argv.fix) { - throw new Error('Either --check or --fix must be provided.\n'); - } - return true; - }).argv; - - return { - check, - fix, - // TypeScript doesn't narrow the type of `controllerPath` even though we defined it as a string in yargs, so we need to cast it here. - controllerPath: controllerPath as string, - }; -} - -/** - * Checks if generated action types files are up to date. - * - * @param controllers - Array of controller information objects. - * @param eslint - The ESLint instance to use for formatting. - */ -async function checkActionTypesFiles( - controllers: ControllerInfo[], - eslint: ESLint, -): Promise { - let hasErrors = false; - - // Track files that exist and their corresponding temp files - const fileComparisonJobs: { - expectedTempFile: string; - actualFile: string; - baseFileName: string; - }[] = []; - - try { - // Check each controller and prepare comparison jobs - for (const controller of controllers) { - console.log(`\nšŸ”§ Checking ${controller.name}...`); - const outputDir = path.dirname(controller.filePath); - const baseFileName = path.basename(controller.filePath, '.ts'); - const actualFile = path.join( - outputDir, - `${baseFileName}-method-action-types.ts`, - ); - - const expectedContent = generateActionTypesContent(controller); - const expectedTempFile = actualFile.replace('.ts', '.tmp.ts'); - - try { - // Check if actual file exists first - await fs.promises.access(actualFile); - - // Write expected content to temp file - await fs.promises.writeFile(expectedTempFile, expectedContent, 'utf8'); - - // Add to comparison jobs - fileComparisonJobs.push({ - expectedTempFile, - actualFile, - baseFileName, - }); - } catch (error) { - if ((error as NodeJS.ErrnoException).code === 'ENOENT') { - console.error( - `āŒ ${baseFileName}-method-action-types.ts does not exist`, - ); - } else { - console.error( - `āŒ Error reading ${baseFileName}-method-action-types.ts:`, - error, - ); - } - hasErrors = true; - } - } - - // Run ESLint on all files at once if we have comparisons to make - if (fileComparisonJobs.length > 0) { - console.log('\nšŸ“ Running ESLint to compare files...'); - - const results = await eslint.lintFiles( - fileComparisonJobs.map((job) => job.expectedTempFile), - ); - await ESLint.outputFixes(results); - - // Compare expected vs actual content - for (const job of fileComparisonJobs) { - const expectedContent = await fs.promises.readFile( - job.expectedTempFile, - 'utf8', - ); - const actualContent = await fs.promises.readFile( - job.actualFile, - 'utf8', - ); - - if (expectedContent === actualContent) { - console.log( - `āœ… ${job.baseFileName}-method-action-types.ts is up to date`, - ); - } else { - console.error( - `āŒ ${job.baseFileName}-method-action-types.ts is out of date`, - ); - hasErrors = true; - } - } - } - } finally { - // Clean up temp files - for (const job of fileComparisonJobs) { - try { - await fs.promises.unlink(job.expectedTempFile); - } catch { - // Ignore cleanup errors - } - } - } - - if (hasErrors) { - console.error('\nšŸ’„ Some action type files are out of date or missing.'); - console.error( - 'Run `yarn generate-method-action-types --fix` to update them.', - ); - process.exitCode = 1; - } else { - console.log('\nšŸŽ‰ All action type files are up to date!'); - } -} - -/** - * Main entry point for the script. - */ -async function main(): Promise { - const { fix, controllerPath } = await parseCommandLineArguments(); - - console.log('šŸ” Searching for controllers with MESSENGER_EXPOSED_METHODS...'); - - const controllers = await findControllersWithExposedMethods(controllerPath); - - if (controllers.length === 0) { - console.log('āš ļø No controllers found with MESSENGER_EXPOSED_METHODS'); - return; - } - - console.log( - `šŸ“¦ Found ${controllers.length} controller(s) with exposed methods`, - ); - - const eslint = new ESLint({ - fix: true, - errorOnUnmatchedPattern: false, - }); - - if (fix) { - await generateAllActionTypesFiles(controllers, eslint); - console.log('\nšŸŽ‰ All action types generated successfully!'); - } else { - // -check mode: check files - await checkActionTypesFiles(controllers, eslint); - } -} - -/** - * Check if a path is a directory. - * - * @param pathValue - The path to check. - * @returns True if the path is a directory, false otherwise. - * @throws If an error occurs other than the path not existing. - */ -async function isDirectory(pathValue: string): Promise { - try { - const stats = await fs.promises.stat(pathValue); - return stats.isDirectory(); - } catch (error) { - if ( - isObject(error) && - hasProperty(error, 'code') && - error.code === 'ENOENT' - ) { - return false; - } - - throw error; - } -} - -/** - * Finds all controller files that have MESSENGER_EXPOSED_METHODS constants. - * - * @param controllerPath - Path to the folder where controllers are located. - * @returns A list of controller information objects. - */ -async function findControllersWithExposedMethods( - controllerPath: string, -): Promise { - const srcPath = path.resolve(process.cwd(), controllerPath); - const controllers: ControllerInfo[] = []; - - if (!(await isDirectory(srcPath))) { - throw new Error(`The specified path is not a directory: ${srcPath}`); - } - - const srcFiles = await fs.promises.readdir(srcPath); - - for (const file of srcFiles) { - if (!file.endsWith('.ts') || file.endsWith('.test.ts')) { - continue; - } - - const filePath = path.join(srcPath, file); - const content = await fs.promises.readFile(filePath, 'utf8'); - - if (content.includes('MESSENGER_EXPOSED_METHODS')) { - const controllerInfo = await parseControllerFile(filePath); - if (controllerInfo) { - controllers.push(controllerInfo); - } - } - } - - return controllers; -} - -/** - * Context for AST visiting. - */ -type VisitorContext = { - exposedMethods: string[]; - className: string; - methods: MethodInfo[]; - sourceFile: ts.SourceFile; -}; - -/** - * Visits AST nodes to find exposed methods and controller class. - * - * @param context - The visitor context. - * @returns A function to visit nodes. - */ -function createASTVisitor(context: VisitorContext): (node: ts.Node) => void { - /** - * Visits AST nodes to find exposed methods and controller class. - * - * @param node - The AST node to visit. - */ - function visitNode(node: ts.Node): void { - if (ts.isVariableStatement(node)) { - const declaration = node.declarationList.declarations[0]; - if ( - ts.isIdentifier(declaration.name) && - declaration.name.text === 'MESSENGER_EXPOSED_METHODS' - ) { - if (declaration.initializer) { - let arrayExpression: ts.ArrayLiteralExpression | undefined; - - // Handle direct array literal - if (ts.isArrayLiteralExpression(declaration.initializer)) { - arrayExpression = declaration.initializer; - } - // Handle "as const" assertion: expression is wrapped in type assertion - else if ( - ts.isAsExpression(declaration.initializer) && - ts.isArrayLiteralExpression(declaration.initializer.expression) - ) { - arrayExpression = declaration.initializer.expression; - } - - if (arrayExpression) { - context.exposedMethods = arrayExpression.elements - .filter(ts.isStringLiteral) - .map((element) => element.text); - } - } - } - } - - // Find the controller or service class - if (ts.isClassDeclaration(node) && node.name) { - const classText = node.name.text; - if (classText.includes('Controller') || classText.includes('Service')) { - context.className = classText; - - // Extract method info for exposed methods - const seenMethods = new Set(); - for (const member of node.members) { - if ( - ts.isMethodDeclaration(member) && - member.name && - ts.isIdentifier(member.name) - ) { - const methodName = member.name.text; - if ( - context.exposedMethods.includes(methodName) && - !seenMethods.has(methodName) - ) { - seenMethods.add(methodName); - const jsDoc = extractJSDoc(member, context.sourceFile); - const signature = extractMethodSignature(member); - context.methods.push({ - name: methodName, - jsDoc, - signature, - }); - } - } - } - } - } - - ts.forEachChild(node, visitNode); - } - - return visitNode; -} - -/** - * Create a TypeScript program for the given file by locating the nearest - * tsconfig.json. - * - * @param filePath - Absolute path to the source file. - * @returns A TypeScript program, or null if no tsconfig was found. - */ -function createProgramForFile(filePath: string): ts.Program | null { - const configPath = ts.findConfigFile( - path.dirname(filePath), - ts.sys.fileExists.bind(ts.sys), - 'tsconfig.json', - ); - if (!configPath) { - return null; - } - - const { config, error } = ts.readConfigFile( - configPath, - ts.sys.readFile.bind(ts.sys), - ); - - if (error) { - return null; - } - - const parsedConfig = ts.parseJsonConfigFileContent( - config, - ts.sys, - path.dirname(configPath), - ); - - return ts.createProgram({ - rootNames: parsedConfig.fileNames, - options: parsedConfig.options, - }); -} - -/** - * Find a class declaration with the given name in a source file. - * - * @param sourceFile - The source file to search. - * @param className - The class name to look for. - * @returns The class declaration node, or null if not found. - */ -function findClassInSourceFile( - sourceFile: ts.SourceFile, - className: string, -): ts.ClassDeclaration | null { - return ( - sourceFile.statements.find( - (node): node is ts.ClassDeclaration => - ts.isClassDeclaration(node) && node.name?.text === className, - ) ?? null - ); -} - -/** - * Search through the class hierarchy of a TypeScript type to find the - * declaration of a method with the given name. - * - * @param classType - The class type to search. - * @param methodName - The method name to look for. - * @returns The method declaration node, or null if not found. - */ -function findMethodInHierarchy( - classType: ts.Type, - methodName: string, -): ts.MethodDeclaration | null { - const symbol = classType.getProperty(methodName); - if (!symbol) { - return null; - } - - const declarations = symbol.getDeclarations(); - if (!declarations) { - return null; - } - - for (const declaration of declarations) { - if (ts.isMethodDeclaration(declaration)) { - return declaration; - } - } - - return null; -} - -/** - * Parses a controller file to extract exposed methods and their metadata. - * - * @param filePath - Path to the controller file to parse. - * @returns Controller information or null if parsing fails. - */ -async function parseControllerFile( - filePath: string, -): Promise { - try { - const content = await fs.promises.readFile(filePath, 'utf8'); - const sourceFile = ts.createSourceFile( - filePath, - content, - ts.ScriptTarget.Latest, - true, - ); - - const context: VisitorContext = { - exposedMethods: [], - className: '', - methods: [], - sourceFile, - }; - - createASTVisitor(context)(sourceFile); - - if (context.exposedMethods.length === 0 || !context.className) { - return null; - } - - // For exposed methods not found directly in the class body, attempt to - // locate them in the inheritance hierarchy using the type checker. - const foundMethodNames = new Set( - context.methods.map((method) => method.name), - ); - - const inheritedMethodNames = context.exposedMethods.filter( - (name) => !foundMethodNames.has(name), - ); - - if (inheritedMethodNames.length > 0) { - const program = createProgramForFile(filePath); - const checker = program?.getTypeChecker(); - const programSourceFile = program?.getSourceFile(filePath); - - assert( - checker, - `Type checker could not be created for "${filePath}". Ensure a valid tsconfig.json is present.`, - ); - - assert( - programSourceFile, - `Source file "${filePath}" not found in program.`, - ); - - const classNode = findClassInSourceFile( - programSourceFile, - context.className, - ); - - assert( - classNode, - `Class "${context.className}" not found in "${filePath}".`, - ); - - const classType = checker.getTypeAtLocation(classNode); - for (const methodName of inheritedMethodNames) { - const methodDeclaration = findMethodInHierarchy(classType, methodName); - - const jsDoc = methodDeclaration - ? extractJSDoc(methodDeclaration, methodDeclaration.getSourceFile()) - : ''; - context.methods.push({ name: methodName, jsDoc, signature: '' }); - } - } - - return { - name: context.className, - filePath, - exposedMethods: context.exposedMethods, - methods: context.methods, - }; - } catch (error) { - console.error(`Error parsing ${filePath}:`, error); - return null; - } -} - -/** - * Extracts JSDoc comment from a method declaration. - * - * @param node - The method declaration node. - * @param sourceFile - The source file. - * @returns The JSDoc comment. - */ -function extractJSDoc( - node: ts.MethodDeclaration, - sourceFile: ts.SourceFile, -): string { - const jsDocTags = ts.getJSDocCommentsAndTags(node); - if (jsDocTags.length === 0) { - return ''; - } - - const jsDoc = jsDocTags[0]; - if (ts.isJSDoc(jsDoc)) { - const fullText = sourceFile.getFullText(); - const start = jsDoc.getFullStart(); - const end = jsDoc.getEnd(); - const rawJsDoc = fullText.substring(start, end).trim(); - return formatJSDoc(rawJsDoc); - } - - return ''; -} - -/** - * Formats JSDoc comments to have consistent indentation for the generated file. - * - * @param rawJsDoc - The raw JSDoc comment from the source. - * @returns The formatted JSDoc comment. - */ -function formatJSDoc(rawJsDoc: string): string { - const lines = rawJsDoc.split('\n'); - const formattedLines: string[] = []; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - if (i === 0) { - // First line should be /** - formattedLines.push('/**'); - } else if (i === lines.length - 1) { - // Last line should be */ - formattedLines.push(' */'); - } else { - // Middle lines should start with ' * ' - const trimmed = line.trim(); - if (trimmed.startsWith('*')) { - // Remove existing * and normalize - const content = trimmed.substring(1).trim(); - formattedLines.push(content ? ` * ${content}` : ' *'); - } else { - // Handle lines that don't start with * - formattedLines.push(trimmed ? ` * ${trimmed}` : ' *'); - } - } - } - - return formattedLines.join('\n'); -} - -/** - * Extracts method signature as a string for the handler type. - * - * @param node - The method declaration node. - * @returns The method signature. - */ -function extractMethodSignature(node: ts.MethodDeclaration): string { - // Since we're just using the method reference in the handler type, - // we don't need the full signature - just return the method name - // The actual signature will be inferred from the controller class - return node.name ? (node.name as ts.Identifier).text : ''; -} - -/** - * Generates action types files for all controllers. - * - * @param controllers - Array of controller information objects. - * @param eslint - The ESLint instance to use for formatting. - */ -async function generateAllActionTypesFiles( - controllers: ControllerInfo[], - eslint: ESLint, -): Promise { - const outputFiles: string[] = []; - - // Write all files first - for (const controller of controllers) { - console.log(`\nšŸ”§ Processing ${controller.name}...`); - const outputDir = path.dirname(controller.filePath); - const baseFileName = path.basename(controller.filePath, '.ts'); - const outputFile = path.join( - outputDir, - `${baseFileName}-method-action-types.ts`, - ); - - const generatedContent = generateActionTypesContent(controller); - await fs.promises.writeFile(outputFile, generatedContent, 'utf8'); - outputFiles.push(outputFile); - console.log(`āœ… Generated action types for ${controller.name}`); - } - - // Run ESLint on all the actual files - if (outputFiles.length > 0) { - console.log('\nšŸ“ Running ESLint on generated files...'); - - const results = await eslint.lintFiles(outputFiles); - await ESLint.outputFixes(results); - const errors = ESLint.getErrorResults(results); - if (errors.length > 0) { - console.error('āŒ ESLint errors:', errors); - process.exitCode = 1; - } else { - console.log('āœ… ESLint formatting applied'); - } - } -} - -/** - * Generates the content for the action types file. - * - * @param controller - The controller information object. - * @returns The content for the action types file. - */ -function generateActionTypesContent(controller: ControllerInfo): string { - const baseFileName = path.basename(controller.filePath, '.ts'); - const controllerImportPath = `./${baseFileName}`; - - let content = `/** - * This file is auto generated by \`scripts/generate-method-action-types.ts\`. - * Do not edit manually. - */ - -import type { ${controller.name} } from '${controllerImportPath}'; - -`; - - const actionTypeNames: string[] = []; - - // Generate action types for each exposed method - for (const method of controller.methods) { - const actionTypeName = `${controller.name}${capitalize(method.name)}Action`; - const actionString = `${controller.name}:${method.name}`; - - actionTypeNames.push(actionTypeName); - - // Add the JSDoc if available - if (method.jsDoc) { - content += `${method.jsDoc}\n`; - } - - content += `export type ${actionTypeName} = { - type: \`${actionString}\`; - handler: ${controller.name}['${method.name}']; -};\n\n`; - } - - // Generate union type of all action types - if (actionTypeNames.length > 0) { - const unionTypeName = `${controller.name}MethodActions`; - content += `/** - * Union of all ${controller.name} action types. - */ -export type ${unionTypeName} = ${actionTypeNames.join(' | ')};\n`; - } - - return `${content.trimEnd()}\n`; -} - -/** - * Capitalizes the first letter of a string. - * - * @param str - The string to capitalize. - * @returns The capitalized string. - */ -function capitalize(str: string): string { - return str.charAt(0).toUpperCase() + str.slice(1); -} - -// Error handling wrapper -main().catch((error) => { - console.error('āŒ Script failed:', error); - process.exitCode = 1; -}); diff --git a/yarn.config.cjs b/yarn.config.cjs index db5c54c7fe3..6e5bcae193e 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -111,7 +111,10 @@ module.exports = defineConfig({ // All non-root packages must set up ESM- and CommonJS-compatible // exports correctly. - if (workspace.ident !== '@metamask/foundryup') { + if ( + workspace.ident !== '@metamask/foundryup' && + workspace.ident !== '@metamask/messenger' + ) { expectCorrectWorkspaceExports(workspace); } diff --git a/yarn.lock b/yarn.lock index 529185d3373..e98b91cb08c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4331,15 +4331,32 @@ __metadata: resolution: "@metamask/messenger@workspace:packages/messenger" dependencies: "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^29.5.14" + "@types/yargs": "npm:^17.0.32" deepmerge: "npm:^4.2.2" + eslint: "npm:^9.39.1" immer: "npm:^9.0.6" jest: "npm:^29.7.0" ts-jest: "npm:^29.2.5" typedoc: "npm:^0.25.13" typedoc-plugin-missing-exports: "npm:^2.0.0" typescript: "npm:~5.3.3" + yargs: "npm:^17.7.2" + peerDependencies: + eslint: ">=8" + typescript: ~5.3.3 + yargs: ^17.7.2 + peerDependenciesMeta: + eslint: + optional: true + typescript: + optional: true + yargs: + optional: true + bin: + messenger-generate-action-types: ./dist/generate-action-types/cli.mjs languageName: unknown linkType: soft