@metamask-previews/messenger-cli 0.0.0-preview-23f4dfd

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +20 -0
  3. package/README.md +15 -0
  4. package/dist/check.cjs +105 -0
  5. package/dist/check.cjs.map +1 -0
  6. package/dist/check.d.cts +11 -0
  7. package/dist/check.d.cts.map +1 -0
  8. package/dist/check.d.mts +11 -0
  9. package/dist/check.d.mts.map +1 -0
  10. package/dist/check.mjs +78 -0
  11. package/dist/check.mjs.map +1 -0
  12. package/dist/cli.cjs +107 -0
  13. package/dist/cli.cjs.map +1 -0
  14. package/dist/cli.d.cts +3 -0
  15. package/dist/cli.d.cts.map +1 -0
  16. package/dist/cli.d.mts +3 -0
  17. package/dist/cli.d.mts.map +1 -0
  18. package/dist/cli.mjs +102 -0
  19. package/dist/cli.mjs.map +1 -0
  20. package/dist/fix.cjs +63 -0
  21. package/dist/fix.cjs.map +1 -0
  22. package/dist/fix.d.cts +11 -0
  23. package/dist/fix.d.cts.map +1 -0
  24. package/dist/fix.d.mts +11 -0
  25. package/dist/fix.d.mts.map +1 -0
  26. package/dist/fix.mjs +36 -0
  27. package/dist/fix.mjs.map +1 -0
  28. package/dist/generate-content.cjs +69 -0
  29. package/dist/generate-content.cjs.map +1 -0
  30. package/dist/generate-content.d.cts +9 -0
  31. package/dist/generate-content.d.cts.map +1 -0
  32. package/dist/generate-content.d.mts +9 -0
  33. package/dist/generate-content.d.mts.map +1 -0
  34. package/dist/generate-content.mjs +42 -0
  35. package/dist/generate-content.mjs.map +1 -0
  36. package/dist/index.cjs +13 -0
  37. package/dist/index.cjs.map +1 -0
  38. package/dist/index.d.cts +7 -0
  39. package/dist/index.d.cts.map +1 -0
  40. package/dist/index.d.mts +7 -0
  41. package/dist/index.d.mts.map +1 -0
  42. package/dist/index.mjs +5 -0
  43. package/dist/index.mjs.map +1 -0
  44. package/dist/parse-source.cjs +324 -0
  45. package/dist/parse-source.cjs.map +1 -0
  46. package/dist/parse-source.d.cts +25 -0
  47. package/dist/parse-source.d.cts.map +1 -0
  48. package/dist/parse-source.d.mts +25 -0
  49. package/dist/parse-source.d.mts.map +1 -0
  50. package/dist/parse-source.mjs +297 -0
  51. package/dist/parse-source.mjs.map +1 -0
  52. package/dist/types.cjs +3 -0
  53. package/dist/types.cjs.map +1 -0
  54. package/dist/types.d.cts +6 -0
  55. package/dist/types.d.cts.map +1 -0
  56. package/dist/types.d.mts +6 -0
  57. package/dist/types.d.mts.map +1 -0
  58. package/dist/types.mjs +2 -0
  59. package/dist/types.mjs.map +1 -0
  60. package/package.json +77 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - Initial release, extracted from `@metamask/messenger` ([#8378](https://github.com/MetaMask/core/pull/8378))
13
+ - CLI tool for generating TypeScript action type files for controllers and services that define `MESSENGER_EXPOSED_METHODS`.
14
+ - Available as a CLI binary (`messenger-generate-action-types`).
15
+
16
+ [Unreleased]: https://github.com/MetaMask/core/
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MetaMask
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # `@metamask/messenger-cli`
2
+
3
+ CLI tools for the MetaMask messenger system
4
+
5
+ ## Installation
6
+
7
+ `yarn add @metamask/messenger-cli`
8
+
9
+ or
10
+
11
+ `npm install @metamask/messenger-cli`
12
+
13
+ ## Contributing
14
+
15
+ This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).
package/dist/check.cjs ADDED
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.checkActionTypesFiles = void 0;
27
+ const fs = __importStar(require("node:fs"));
28
+ const path = __importStar(require("node:path"));
29
+ const generate_content_1 = require("./generate-content.cjs");
30
+ /**
31
+ * Checks if generated action types files are up to date.
32
+ *
33
+ * @param sources - Array of source information objects.
34
+ * @param eslint - Optional ESLint instance and static methods for formatting.
35
+ * @returns Whether all files are up to date.
36
+ */
37
+ async function checkActionTypesFiles(sources, eslint) {
38
+ let hasErrors = false;
39
+ const fileComparisonJobs = [];
40
+ try {
41
+ for (const source of sources) {
42
+ console.log(`\nšŸ”§ Checking ${source.name}...`);
43
+ const outputDir = path.dirname(source.filePath);
44
+ const baseFileName = path.basename(source.filePath, '.ts');
45
+ const actualFile = path.join(outputDir, `${baseFileName}-method-action-types.ts`);
46
+ const expectedContent = (0, generate_content_1.generateActionTypesContent)(source);
47
+ const expectedTempFile = actualFile.replace('.ts', '.tmp.ts');
48
+ try {
49
+ await fs.promises.access(actualFile);
50
+ await fs.promises.writeFile(expectedTempFile, expectedContent, 'utf8');
51
+ fileComparisonJobs.push({
52
+ expectedTempFile,
53
+ actualFile,
54
+ baseFileName,
55
+ });
56
+ }
57
+ catch (error) {
58
+ if (error.code === 'ENOENT') {
59
+ console.error(`āŒ ${baseFileName}-method-action-types.ts does not exist`);
60
+ }
61
+ else {
62
+ console.error(`āŒ Error reading ${baseFileName}-method-action-types.ts:`, error);
63
+ }
64
+ hasErrors = true;
65
+ }
66
+ }
67
+ if (fileComparisonJobs.length > 0) {
68
+ if (eslint) {
69
+ console.log('\nšŸ“ Running ESLint to compare files...');
70
+ const results = await eslint.instance.lintFiles(fileComparisonJobs.map((job) => job.expectedTempFile));
71
+ await eslint.eslintClass.outputFixes(results);
72
+ }
73
+ for (const job of fileComparisonJobs) {
74
+ const expectedContent = await fs.promises.readFile(job.expectedTempFile, 'utf8');
75
+ const actualContent = await fs.promises.readFile(job.actualFile, 'utf8');
76
+ if (expectedContent === actualContent) {
77
+ console.log(`āœ… ${job.baseFileName}-method-action-types.ts is up to date`);
78
+ }
79
+ else {
80
+ console.error(`āŒ ${job.baseFileName}-method-action-types.ts is out of date`);
81
+ hasErrors = true;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ finally {
87
+ for (const job of fileComparisonJobs) {
88
+ try {
89
+ await fs.promises.unlink(job.expectedTempFile);
90
+ }
91
+ catch {
92
+ // Ignore cleanup errors
93
+ }
94
+ }
95
+ }
96
+ if (hasErrors) {
97
+ console.error('\nšŸ’„ Some action type files are out of date or missing.');
98
+ console.error('Run `messenger-generate-action-types --fix` to update them.');
99
+ return false;
100
+ }
101
+ console.log('\nšŸŽ‰ All action type files are up to date!');
102
+ return true;
103
+ }
104
+ exports.checkActionTypesFiles = checkActionTypesFiles;
105
+ //# sourceMappingURL=check.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.cjs","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAC9B,gDAAkC;AAElC,6DAAgE;AAIhE;;;;;;GAMG;AACI,KAAK,UAAU,qBAAqB,CACzC,OAAqB,EACrB,MAAqB;IAErB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,kBAAkB,GAIlB,EAAE,CAAC;IAET,IAAI,CAAC;QACH,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC;YAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,SAAS,EACT,GAAG,YAAY,yBAAyB,CACzC,CAAC;YAEF,MAAM,eAAe,GAAG,IAAA,6CAA0B,EAAC,MAAM,CAAC,CAAC;YAC3D,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAE9D,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBAErC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,gBAAgB,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;gBAEvE,kBAAkB,CAAC,IAAI,CAAC;oBACtB,gBAAgB;oBAChB,UAAU;oBACV,YAAY;iBACb,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACvD,OAAO,CAAC,KAAK,CACX,KAAK,YAAY,wCAAwC,CAC1D,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CACX,mBAAmB,YAAY,0BAA0B,EACzD,KAAK,CACN,CAAC;gBACJ,CAAC;gBACD,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;QACH,CAAC;QAED,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;gBAEvD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC7C,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,CACtD,CAAC;gBACF,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAChD,CAAC;YAED,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;gBACrC,MAAM,eAAe,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAChD,GAAG,CAAC,gBAAgB,EACpB,MAAM,CACP,CAAC;gBACF,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAC9C,GAAG,CAAC,UAAU,EACd,MAAM,CACP,CAAC;gBAEF,IAAI,eAAe,KAAK,aAAa,EAAE,CAAC;oBACtC,OAAO,CAAC,GAAG,CACT,KAAK,GAAG,CAAC,YAAY,uCAAuC,CAC7D,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CACX,KAAK,GAAG,CAAC,YAAY,wCAAwC,CAC9D,CAAC;oBACF,SAAS,GAAG,IAAI,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACzE,OAAO,CAAC,KAAK,CACX,6DAA6D,CAC9D,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAtGD,sDAsGC","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { generateActionTypesContent } from './generate-content';\nimport type { SourceInfo } from './parse-source';\nimport type { ESLint } from './types';\n\n/**\n * Checks if generated action types files are up to date.\n *\n * @param sources - Array of source information objects.\n * @param eslint - Optional ESLint instance and static methods for formatting.\n * @returns Whether all files are up to date.\n */\nexport async function checkActionTypesFiles(\n sources: SourceInfo[],\n eslint: ESLint | null,\n): Promise<boolean> {\n let hasErrors = false;\n\n const fileComparisonJobs: {\n expectedTempFile: string;\n actualFile: string;\n baseFileName: string;\n }[] = [];\n\n try {\n for (const source of sources) {\n console.log(`\\nšŸ”§ Checking ${source.name}...`);\n const outputDir = path.dirname(source.filePath);\n const baseFileName = path.basename(source.filePath, '.ts');\n const actualFile = path.join(\n outputDir,\n `${baseFileName}-method-action-types.ts`,\n );\n\n const expectedContent = generateActionTypesContent(source);\n const expectedTempFile = actualFile.replace('.ts', '.tmp.ts');\n\n try {\n await fs.promises.access(actualFile);\n\n await fs.promises.writeFile(expectedTempFile, expectedContent, 'utf8');\n\n fileComparisonJobs.push({\n expectedTempFile,\n actualFile,\n baseFileName,\n });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error(\n `āŒ ${baseFileName}-method-action-types.ts does not exist`,\n );\n } else {\n console.error(\n `āŒ Error reading ${baseFileName}-method-action-types.ts:`,\n error,\n );\n }\n hasErrors = true;\n }\n }\n\n if (fileComparisonJobs.length > 0) {\n if (eslint) {\n console.log('\\nšŸ“ Running ESLint to compare files...');\n\n const results = await eslint.instance.lintFiles(\n fileComparisonJobs.map((job) => job.expectedTempFile),\n );\n await eslint.eslintClass.outputFixes(results);\n }\n\n for (const job of fileComparisonJobs) {\n const expectedContent = await fs.promises.readFile(\n job.expectedTempFile,\n 'utf8',\n );\n const actualContent = await fs.promises.readFile(\n job.actualFile,\n 'utf8',\n );\n\n if (expectedContent === actualContent) {\n console.log(\n `āœ… ${job.baseFileName}-method-action-types.ts is up to date`,\n );\n } else {\n console.error(\n `āŒ ${job.baseFileName}-method-action-types.ts is out of date`,\n );\n hasErrors = true;\n }\n }\n }\n } finally {\n for (const job of fileComparisonJobs) {\n try {\n await fs.promises.unlink(job.expectedTempFile);\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n\n if (hasErrors) {\n console.error('\\nšŸ’„ Some action type files are out of date or missing.');\n console.error(\n 'Run `messenger-generate-action-types --fix` to update them.',\n );\n return false;\n }\n\n console.log('\\nšŸŽ‰ All action type files are up to date!');\n return true;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import type { SourceInfo } from "./parse-source.cjs";
2
+ import type { ESLint } from "./types.cjs";
3
+ /**
4
+ * Checks if generated action types files are up to date.
5
+ *
6
+ * @param sources - Array of source information objects.
7
+ * @param eslint - Optional ESLint instance and static methods for formatting.
8
+ * @returns Whether all files are up to date.
9
+ */
10
+ export declare function checkActionTypesFiles(sources: SourceInfo[], eslint: ESLint | null): Promise<boolean>;
11
+ //# sourceMappingURL=check.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.cts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,2BAAuB;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAgB;AAEtC;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,OAAO,CAAC,CAmGlB"}
@@ -0,0 +1,11 @@
1
+ import type { SourceInfo } from "./parse-source.mjs";
2
+ import type { ESLint } from "./types.mjs";
3
+ /**
4
+ * Checks if generated action types files are up to date.
5
+ *
6
+ * @param sources - Array of source information objects.
7
+ * @param eslint - Optional ESLint instance and static methods for formatting.
8
+ * @returns Whether all files are up to date.
9
+ */
10
+ export declare function checkActionTypesFiles(sources: SourceInfo[], eslint: ESLint | null): Promise<boolean>;
11
+ //# sourceMappingURL=check.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.mts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,2BAAuB;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAgB;AAEtC;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,OAAO,CAAC,CAmGlB"}
package/dist/check.mjs ADDED
@@ -0,0 +1,78 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { generateActionTypesContent } from "./generate-content.mjs";
4
+ /**
5
+ * Checks if generated action types files are up to date.
6
+ *
7
+ * @param sources - Array of source information objects.
8
+ * @param eslint - Optional ESLint instance and static methods for formatting.
9
+ * @returns Whether all files are up to date.
10
+ */
11
+ export async function checkActionTypesFiles(sources, eslint) {
12
+ let hasErrors = false;
13
+ const fileComparisonJobs = [];
14
+ try {
15
+ for (const source of sources) {
16
+ console.log(`\nšŸ”§ Checking ${source.name}...`);
17
+ const outputDir = path.dirname(source.filePath);
18
+ const baseFileName = path.basename(source.filePath, '.ts');
19
+ const actualFile = path.join(outputDir, `${baseFileName}-method-action-types.ts`);
20
+ const expectedContent = generateActionTypesContent(source);
21
+ const expectedTempFile = actualFile.replace('.ts', '.tmp.ts');
22
+ try {
23
+ await fs.promises.access(actualFile);
24
+ await fs.promises.writeFile(expectedTempFile, expectedContent, 'utf8');
25
+ fileComparisonJobs.push({
26
+ expectedTempFile,
27
+ actualFile,
28
+ baseFileName,
29
+ });
30
+ }
31
+ catch (error) {
32
+ if (error.code === 'ENOENT') {
33
+ console.error(`āŒ ${baseFileName}-method-action-types.ts does not exist`);
34
+ }
35
+ else {
36
+ console.error(`āŒ Error reading ${baseFileName}-method-action-types.ts:`, error);
37
+ }
38
+ hasErrors = true;
39
+ }
40
+ }
41
+ if (fileComparisonJobs.length > 0) {
42
+ if (eslint) {
43
+ console.log('\nšŸ“ Running ESLint to compare files...');
44
+ const results = await eslint.instance.lintFiles(fileComparisonJobs.map((job) => job.expectedTempFile));
45
+ await eslint.eslintClass.outputFixes(results);
46
+ }
47
+ for (const job of fileComparisonJobs) {
48
+ const expectedContent = await fs.promises.readFile(job.expectedTempFile, 'utf8');
49
+ const actualContent = await fs.promises.readFile(job.actualFile, 'utf8');
50
+ if (expectedContent === actualContent) {
51
+ console.log(`āœ… ${job.baseFileName}-method-action-types.ts is up to date`);
52
+ }
53
+ else {
54
+ console.error(`āŒ ${job.baseFileName}-method-action-types.ts is out of date`);
55
+ hasErrors = true;
56
+ }
57
+ }
58
+ }
59
+ }
60
+ finally {
61
+ for (const job of fileComparisonJobs) {
62
+ try {
63
+ await fs.promises.unlink(job.expectedTempFile);
64
+ }
65
+ catch {
66
+ // Ignore cleanup errors
67
+ }
68
+ }
69
+ }
70
+ if (hasErrors) {
71
+ console.error('\nšŸ’„ Some action type files are out of date or missing.');
72
+ console.error('Run `messenger-generate-action-types --fix` to update them.');
73
+ return false;
74
+ }
75
+ console.log('\nšŸŽ‰ All action type files are up to date!');
76
+ return true;
77
+ }
78
+ //# sourceMappingURL=check.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.mjs","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { generateActionTypesContent } from './generate-content';\nimport type { SourceInfo } from './parse-source';\nimport type { ESLint } from './types';\n\n/**\n * Checks if generated action types files are up to date.\n *\n * @param sources - Array of source information objects.\n * @param eslint - Optional ESLint instance and static methods for formatting.\n * @returns Whether all files are up to date.\n */\nexport async function checkActionTypesFiles(\n sources: SourceInfo[],\n eslint: ESLint | null,\n): Promise<boolean> {\n let hasErrors = false;\n\n const fileComparisonJobs: {\n expectedTempFile: string;\n actualFile: string;\n baseFileName: string;\n }[] = [];\n\n try {\n for (const source of sources) {\n console.log(`\\nšŸ”§ Checking ${source.name}...`);\n const outputDir = path.dirname(source.filePath);\n const baseFileName = path.basename(source.filePath, '.ts');\n const actualFile = path.join(\n outputDir,\n `${baseFileName}-method-action-types.ts`,\n );\n\n const expectedContent = generateActionTypesContent(source);\n const expectedTempFile = actualFile.replace('.ts', '.tmp.ts');\n\n try {\n await fs.promises.access(actualFile);\n\n await fs.promises.writeFile(expectedTempFile, expectedContent, 'utf8');\n\n fileComparisonJobs.push({\n expectedTempFile,\n actualFile,\n baseFileName,\n });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error(\n `āŒ ${baseFileName}-method-action-types.ts does not exist`,\n );\n } else {\n console.error(\n `āŒ Error reading ${baseFileName}-method-action-types.ts:`,\n error,\n );\n }\n hasErrors = true;\n }\n }\n\n if (fileComparisonJobs.length > 0) {\n if (eslint) {\n console.log('\\nšŸ“ Running ESLint to compare files...');\n\n const results = await eslint.instance.lintFiles(\n fileComparisonJobs.map((job) => job.expectedTempFile),\n );\n await eslint.eslintClass.outputFixes(results);\n }\n\n for (const job of fileComparisonJobs) {\n const expectedContent = await fs.promises.readFile(\n job.expectedTempFile,\n 'utf8',\n );\n const actualContent = await fs.promises.readFile(\n job.actualFile,\n 'utf8',\n );\n\n if (expectedContent === actualContent) {\n console.log(\n `āœ… ${job.baseFileName}-method-action-types.ts is up to date`,\n );\n } else {\n console.error(\n `āŒ ${job.baseFileName}-method-action-types.ts is out of date`,\n );\n hasErrors = true;\n }\n }\n }\n } finally {\n for (const job of fileComparisonJobs) {\n try {\n await fs.promises.unlink(job.expectedTempFile);\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n\n if (hasErrors) {\n console.error('\\nšŸ’„ Some action type files are out of date or missing.');\n console.error(\n 'Run `messenger-generate-action-types --fix` to update them.',\n );\n return false;\n }\n\n console.log('\\nšŸŽ‰ All action type files are up to date!');\n return true;\n}\n"]}
package/dist/cli.cjs ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const yargs_1 = __importDefault(require("yargs"));
8
+ const check_1 = require("./check.cjs");
9
+ const fix_1 = require("./fix.cjs");
10
+ const parse_source_1 = require("./parse-source.cjs");
11
+ /**
12
+ * Parses the given CLI arguments.
13
+ *
14
+ * @param args - The arguments to parse.
15
+ * @returns The parsed command line arguments.
16
+ */
17
+ async function parseCommandLineArguments(args) {
18
+ const { check, fix, path: sourcePath, } = await (0, yargs_1.default)(args)
19
+ .command('$0 [path]', 'Generate method action types for controller and service messengers', (yargsInstance) => {
20
+ yargsInstance.positional('path', {
21
+ type: 'string',
22
+ description: 'Path to the folder where controllers/services are located',
23
+ default: 'src',
24
+ });
25
+ })
26
+ .option('check', {
27
+ type: 'boolean',
28
+ description: 'Check if generated action type files are up to date',
29
+ default: false,
30
+ })
31
+ .option('fix', {
32
+ type: 'boolean',
33
+ description: 'Generate/update action type files',
34
+ default: false,
35
+ })
36
+ .help()
37
+ .check((argv) => {
38
+ if (!argv.check && !argv.fix) {
39
+ throw new Error('Either --check or --fix must be provided.\n');
40
+ }
41
+ return true;
42
+ }).argv;
43
+ return {
44
+ check,
45
+ fix,
46
+ sourcePath: sourcePath,
47
+ };
48
+ }
49
+ /**
50
+ * Attempt to load ESLint from the current project. Returns null if unavailable.
51
+ *
52
+ * @returns An ESLint object with instance and static methods, or null if unavailable.
53
+ */
54
+ async function loadESLint() {
55
+ try {
56
+ const { ESLint: ESLintClass } = await import("eslint");
57
+ const instance = new ESLintClass({
58
+ fix: true,
59
+ errorOnUnmatchedPattern: false,
60
+ });
61
+ return {
62
+ instance,
63
+ eslintClass: ESLintClass,
64
+ };
65
+ }
66
+ catch {
67
+ console.warn('āš ļø ESLint could not be loaded. Generated files will not be formatted.');
68
+ return null;
69
+ }
70
+ }
71
+ /**
72
+ * Main entry point for the CLI.
73
+ */
74
+ async function main() {
75
+ const { fix, sourcePath } = await parseCommandLineArguments(globalThis.process.argv.slice(2));
76
+ console.log('šŸ” Searching for controllers/services with MESSENGER_EXPOSED_METHODS...');
77
+ const sources = await (0, parse_source_1.findSourcesWithExposedMethods)(sourcePath);
78
+ if (sources.length === 0) {
79
+ console.log('āš ļø No controllers/services found with MESSENGER_EXPOSED_METHODS');
80
+ return;
81
+ }
82
+ console.log(`šŸ“¦ Found ${sources.length} controller(s)/service(s) with exposed methods`);
83
+ const eslint = await loadESLint();
84
+ if (fix) {
85
+ const success = await (0, fix_1.generateAllActionTypesFiles)(sources, eslint);
86
+ if (success) {
87
+ console.log('\nšŸŽ‰ All action types generated successfully!');
88
+ }
89
+ else {
90
+ // eslint-disable-next-line no-restricted-globals
91
+ process.exitCode = 1;
92
+ }
93
+ }
94
+ else {
95
+ const success = await (0, check_1.checkActionTypesFiles)(sources, eslint);
96
+ if (!success) {
97
+ // eslint-disable-next-line no-restricted-globals
98
+ process.exitCode = 1;
99
+ }
100
+ }
101
+ }
102
+ main().catch((error) => {
103
+ console.error('āŒ Script failed:', error);
104
+ // eslint-disable-next-line no-restricted-globals
105
+ process.exitCode = 1;
106
+ });
107
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.cjs","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,kDAA0B;AAE1B,uCAAgD;AAChD,mCAAoD;AACpD,qDAA+D;AAS/D;;;;;GAKG;AACH,KAAK,UAAU,yBAAyB,CACtC,IAAc;IAEd,MAAM,EACJ,KAAK,EACL,GAAG,EACH,IAAI,EAAE,UAAU,GACjB,GAAG,MAAM,IAAA,eAAK,EAAC,IAAI,CAAC;SAClB,OAAO,CACN,WAAW,EACX,oEAAoE,EACpE,CAAC,aAAa,EAAE,EAAE;QAChB,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,2DAA2D;YAC7D,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC,CACF;SACA,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,KAAK;KACf,CAAC;SACD,MAAM,CAAC,KAAK,EAAE;QACb,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,mCAAmC;QAChD,OAAO,EAAE,KAAK;KACf,CAAC;SACD,IAAI,EAAE;SACN,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACd,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC,IAAI,CAAC;IAEV,OAAO;QACL,KAAK;QACL,GAAG;QACH,UAAU,EAAE,UAAoB;KACjC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,UAAU,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC;YAC/B,GAAG,EAAE,IAAI;YACT,uBAAuB,EAAE,KAAK;SAC/B,CAAC,CAAC;QACH,OAAO;YACL,QAAQ;YACR,WAAW,EAAE,WAAW;SACzB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CACV,wEAAwE,CACzE,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,MAAM,yBAAyB,CACzD,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CACjC,CAAC;IAEF,OAAO,CAAC,GAAG,CACT,yEAAyE,CAC1E,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,IAAA,4CAA6B,EAAC,UAAU,CAAC,CAAC;IAEhE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CACT,kEAAkE,CACnE,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,YAAY,OAAO,CAAC,MAAM,gDAAgD,CAC3E,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,OAAO,GAAG,MAAM,IAAA,iCAA2B,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnE,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,iDAAiD;YACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,MAAM,IAAA,6BAAqB,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,iDAAiD;YACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IACzC,iDAAiD;IACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\n\nimport { checkActionTypesFiles } from './check';\nimport { generateAllActionTypesFiles } from './fix';\nimport { findSourcesWithExposedMethods } from './parse-source';\nimport type { ESLint } from './types';\n\ntype CommandLineArguments = {\n check: boolean;\n fix: boolean;\n sourcePath: string;\n};\n\n/**\n * Parses the given CLI arguments.\n *\n * @param args - The arguments to parse.\n * @returns The parsed command line arguments.\n */\nasync function parseCommandLineArguments(\n args: string[],\n): Promise<CommandLineArguments> {\n const {\n check,\n fix,\n path: sourcePath,\n } = await yargs(args)\n .command(\n '$0 [path]',\n 'Generate method action types for controller and service messengers',\n (yargsInstance) => {\n yargsInstance.positional('path', {\n type: 'string',\n description:\n 'Path to the folder where controllers/services are located',\n default: 'src',\n });\n },\n )\n .option('check', {\n type: 'boolean',\n description: 'Check if generated action type files are up to date',\n default: false,\n })\n .option('fix', {\n type: 'boolean',\n description: 'Generate/update action type files',\n default: false,\n })\n .help()\n .check((argv) => {\n if (!argv.check && !argv.fix) {\n throw new Error('Either --check or --fix must be provided.\\n');\n }\n return true;\n }).argv;\n\n return {\n check,\n fix,\n sourcePath: sourcePath as string,\n };\n}\n\n/**\n * Attempt to load ESLint from the current project. Returns null if unavailable.\n *\n * @returns An ESLint object with instance and static methods, or null if unavailable.\n */\nasync function loadESLint(): Promise<ESLint | null> {\n try {\n const { ESLint: ESLintClass } = await import('eslint');\n const instance = new ESLintClass({\n fix: true,\n errorOnUnmatchedPattern: false,\n });\n return {\n instance,\n eslintClass: ESLintClass,\n };\n } catch {\n console.warn(\n 'āš ļø ESLint could not be loaded. Generated files will not be formatted.',\n );\n return null;\n }\n}\n\n/**\n * Main entry point for the CLI.\n */\nasync function main(): Promise<void> {\n const { fix, sourcePath } = await parseCommandLineArguments(\n globalThis.process.argv.slice(2),\n );\n\n console.log(\n 'šŸ” Searching for controllers/services with MESSENGER_EXPOSED_METHODS...',\n );\n\n const sources = await findSourcesWithExposedMethods(sourcePath);\n\n if (sources.length === 0) {\n console.log(\n 'āš ļø No controllers/services found with MESSENGER_EXPOSED_METHODS',\n );\n return;\n }\n\n console.log(\n `šŸ“¦ Found ${sources.length} controller(s)/service(s) with exposed methods`,\n );\n\n const eslint = await loadESLint();\n\n if (fix) {\n const success = await generateAllActionTypesFiles(sources, eslint);\n if (success) {\n console.log('\\nšŸŽ‰ All action types generated successfully!');\n } else {\n // eslint-disable-next-line no-restricted-globals\n process.exitCode = 1;\n }\n } else {\n const success = await checkActionTypesFiles(sources, eslint);\n if (!success) {\n // eslint-disable-next-line no-restricted-globals\n process.exitCode = 1;\n }\n }\n}\n\nmain().catch((error) => {\n console.error('āŒ Script failed:', error);\n // eslint-disable-next-line no-restricted-globals\n process.exitCode = 1;\n});\n"]}
package/dist/cli.d.cts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.cts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.d.mts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.mts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.mjs ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import yargs from "yargs";
3
+ import { checkActionTypesFiles } from "./check.mjs";
4
+ import { generateAllActionTypesFiles } from "./fix.mjs";
5
+ import { findSourcesWithExposedMethods } from "./parse-source.mjs";
6
+ /**
7
+ * Parses the given CLI arguments.
8
+ *
9
+ * @param args - The arguments to parse.
10
+ * @returns The parsed command line arguments.
11
+ */
12
+ async function parseCommandLineArguments(args) {
13
+ const { check, fix, path: sourcePath, } = await yargs(args)
14
+ .command('$0 [path]', 'Generate method action types for controller and service messengers', (yargsInstance) => {
15
+ yargsInstance.positional('path', {
16
+ type: 'string',
17
+ description: 'Path to the folder where controllers/services are located',
18
+ default: 'src',
19
+ });
20
+ })
21
+ .option('check', {
22
+ type: 'boolean',
23
+ description: 'Check if generated action type files are up to date',
24
+ default: false,
25
+ })
26
+ .option('fix', {
27
+ type: 'boolean',
28
+ description: 'Generate/update action type files',
29
+ default: false,
30
+ })
31
+ .help()
32
+ .check((argv) => {
33
+ if (!argv.check && !argv.fix) {
34
+ throw new Error('Either --check or --fix must be provided.\n');
35
+ }
36
+ return true;
37
+ }).argv;
38
+ return {
39
+ check,
40
+ fix,
41
+ sourcePath: sourcePath,
42
+ };
43
+ }
44
+ /**
45
+ * Attempt to load ESLint from the current project. Returns null if unavailable.
46
+ *
47
+ * @returns An ESLint object with instance and static methods, or null if unavailable.
48
+ */
49
+ async function loadESLint() {
50
+ try {
51
+ const { ESLint: ESLintClass } = await import("eslint");
52
+ const instance = new ESLintClass({
53
+ fix: true,
54
+ errorOnUnmatchedPattern: false,
55
+ });
56
+ return {
57
+ instance,
58
+ eslintClass: ESLintClass,
59
+ };
60
+ }
61
+ catch {
62
+ console.warn('āš ļø ESLint could not be loaded. Generated files will not be formatted.');
63
+ return null;
64
+ }
65
+ }
66
+ /**
67
+ * Main entry point for the CLI.
68
+ */
69
+ async function main() {
70
+ const { fix, sourcePath } = await parseCommandLineArguments(globalThis.process.argv.slice(2));
71
+ console.log('šŸ” Searching for controllers/services with MESSENGER_EXPOSED_METHODS...');
72
+ const sources = await findSourcesWithExposedMethods(sourcePath);
73
+ if (sources.length === 0) {
74
+ console.log('āš ļø No controllers/services found with MESSENGER_EXPOSED_METHODS');
75
+ return;
76
+ }
77
+ console.log(`šŸ“¦ Found ${sources.length} controller(s)/service(s) with exposed methods`);
78
+ const eslint = await loadESLint();
79
+ if (fix) {
80
+ const success = await generateAllActionTypesFiles(sources, eslint);
81
+ if (success) {
82
+ console.log('\nšŸŽ‰ All action types generated successfully!');
83
+ }
84
+ else {
85
+ // eslint-disable-next-line no-restricted-globals
86
+ process.exitCode = 1;
87
+ }
88
+ }
89
+ else {
90
+ const success = await checkActionTypesFiles(sources, eslint);
91
+ if (!success) {
92
+ // eslint-disable-next-line no-restricted-globals
93
+ process.exitCode = 1;
94
+ }
95
+ }
96
+ }
97
+ main().catch((error) => {
98
+ console.error('āŒ Script failed:', error);
99
+ // eslint-disable-next-line no-restricted-globals
100
+ process.exitCode = 1;
101
+ });
102
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,cAAc;AAE1B,OAAO,EAAE,qBAAqB,EAAE,oBAAgB;AAChD,OAAO,EAAE,2BAA2B,EAAE,kBAAc;AACpD,OAAO,EAAE,6BAA6B,EAAE,2BAAuB;AAS/D;;;;;GAKG;AACH,KAAK,UAAU,yBAAyB,CACtC,IAAc;IAEd,MAAM,EACJ,KAAK,EACL,GAAG,EACH,IAAI,EAAE,UAAU,GACjB,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;SAClB,OAAO,CACN,WAAW,EACX,oEAAoE,EACpE,CAAC,aAAa,EAAE,EAAE;QAChB,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,2DAA2D;YAC7D,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC,CACF;SACA,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,KAAK;KACf,CAAC;SACD,MAAM,CAAC,KAAK,EAAE;QACb,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,mCAAmC;QAChD,OAAO,EAAE,KAAK;KACf,CAAC;SACD,IAAI,EAAE;SACN,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACd,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC,IAAI,CAAC;IAEV,OAAO;QACL,KAAK;QACL,GAAG;QACH,UAAU,EAAE,UAAoB;KACjC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,UAAU,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC;YAC/B,GAAG,EAAE,IAAI;YACT,uBAAuB,EAAE,KAAK;SAC/B,CAAC,CAAC;QACH,OAAO;YACL,QAAQ;YACR,WAAW,EAAE,WAAW;SACzB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CACV,wEAAwE,CACzE,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,MAAM,yBAAyB,CACzD,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CACjC,CAAC;IAEF,OAAO,CAAC,GAAG,CACT,yEAAyE,CAC1E,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,6BAA6B,CAAC,UAAU,CAAC,CAAC;IAEhE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CACT,kEAAkE,CACnE,CAAC;QACF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,YAAY,OAAO,CAAC,MAAM,gDAAgD,CAC3E,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnE,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,iDAAiD;YACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,iDAAiD;YACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IACzC,iDAAiD;IACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\n\nimport { checkActionTypesFiles } from './check';\nimport { generateAllActionTypesFiles } from './fix';\nimport { findSourcesWithExposedMethods } from './parse-source';\nimport type { ESLint } from './types';\n\ntype CommandLineArguments = {\n check: boolean;\n fix: boolean;\n sourcePath: string;\n};\n\n/**\n * Parses the given CLI arguments.\n *\n * @param args - The arguments to parse.\n * @returns The parsed command line arguments.\n */\nasync function parseCommandLineArguments(\n args: string[],\n): Promise<CommandLineArguments> {\n const {\n check,\n fix,\n path: sourcePath,\n } = await yargs(args)\n .command(\n '$0 [path]',\n 'Generate method action types for controller and service messengers',\n (yargsInstance) => {\n yargsInstance.positional('path', {\n type: 'string',\n description:\n 'Path to the folder where controllers/services are located',\n default: 'src',\n });\n },\n )\n .option('check', {\n type: 'boolean',\n description: 'Check if generated action type files are up to date',\n default: false,\n })\n .option('fix', {\n type: 'boolean',\n description: 'Generate/update action type files',\n default: false,\n })\n .help()\n .check((argv) => {\n if (!argv.check && !argv.fix) {\n throw new Error('Either --check or --fix must be provided.\\n');\n }\n return true;\n }).argv;\n\n return {\n check,\n fix,\n sourcePath: sourcePath as string,\n };\n}\n\n/**\n * Attempt to load ESLint from the current project. Returns null if unavailable.\n *\n * @returns An ESLint object with instance and static methods, or null if unavailable.\n */\nasync function loadESLint(): Promise<ESLint | null> {\n try {\n const { ESLint: ESLintClass } = await import('eslint');\n const instance = new ESLintClass({\n fix: true,\n errorOnUnmatchedPattern: false,\n });\n return {\n instance,\n eslintClass: ESLintClass,\n };\n } catch {\n console.warn(\n 'āš ļø ESLint could not be loaded. Generated files will not be formatted.',\n );\n return null;\n }\n}\n\n/**\n * Main entry point for the CLI.\n */\nasync function main(): Promise<void> {\n const { fix, sourcePath } = await parseCommandLineArguments(\n globalThis.process.argv.slice(2),\n );\n\n console.log(\n 'šŸ” Searching for controllers/services with MESSENGER_EXPOSED_METHODS...',\n );\n\n const sources = await findSourcesWithExposedMethods(sourcePath);\n\n if (sources.length === 0) {\n console.log(\n 'āš ļø No controllers/services found with MESSENGER_EXPOSED_METHODS',\n );\n return;\n }\n\n console.log(\n `šŸ“¦ Found ${sources.length} controller(s)/service(s) with exposed methods`,\n );\n\n const eslint = await loadESLint();\n\n if (fix) {\n const success = await generateAllActionTypesFiles(sources, eslint);\n if (success) {\n console.log('\\nšŸŽ‰ All action types generated successfully!');\n } else {\n // eslint-disable-next-line no-restricted-globals\n process.exitCode = 1;\n }\n } else {\n const success = await checkActionTypesFiles(sources, eslint);\n if (!success) {\n // eslint-disable-next-line no-restricted-globals\n process.exitCode = 1;\n }\n }\n}\n\nmain().catch((error) => {\n console.error('āŒ Script failed:', error);\n // eslint-disable-next-line no-restricted-globals\n process.exitCode = 1;\n});\n"]}
package/dist/fix.cjs ADDED
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.generateAllActionTypesFiles = void 0;
27
+ const fs = __importStar(require("node:fs"));
28
+ const path = __importStar(require("node:path"));
29
+ const generate_content_1 = require("./generate-content.cjs");
30
+ /**
31
+ * Generates action types files for all controllers/services.
32
+ *
33
+ * @param sources - Array of source information objects.
34
+ * @param eslint - Optional ESLint instance and static methods for formatting.
35
+ * @returns Whether all files were generated successfully.
36
+ */
37
+ async function generateAllActionTypesFiles(sources, eslint) {
38
+ const outputFiles = [];
39
+ for (const source of sources) {
40
+ console.log(`\nšŸ”§ Processing ${source.name}...`);
41
+ const outputDir = path.dirname(source.filePath);
42
+ const baseFileName = path.basename(source.filePath, '.ts');
43
+ const outputFile = path.join(outputDir, `${baseFileName}-method-action-types.ts`);
44
+ const generatedContent = (0, generate_content_1.generateActionTypesContent)(source);
45
+ await fs.promises.writeFile(outputFile, generatedContent, 'utf8');
46
+ outputFiles.push(outputFile);
47
+ console.log(`āœ… Generated action types for ${source.name}`);
48
+ }
49
+ if (outputFiles.length > 0 && eslint) {
50
+ console.log('\nšŸ“ Running ESLint on generated files...');
51
+ const results = await eslint.instance.lintFiles(outputFiles);
52
+ await eslint.eslintClass.outputFixes(results);
53
+ const errors = eslint.eslintClass.getErrorResults(results);
54
+ if (errors.length > 0) {
55
+ console.error('āŒ ESLint errors:', errors);
56
+ return false;
57
+ }
58
+ console.log('āœ… ESLint formatting applied');
59
+ }
60
+ return true;
61
+ }
62
+ exports.generateAllActionTypesFiles = generateAllActionTypesFiles;
63
+ //# sourceMappingURL=fix.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.cjs","sourceRoot":"","sources":["../src/fix.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAC9B,gDAAkC;AAElC,6DAAgE;AAIhE;;;;;;GAMG;AACI,KAAK,UAAU,2BAA2B,CAC/C,OAAqB,EACrB,MAAqB;IAErB,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,SAAS,EACT,GAAG,YAAY,yBAAyB,CACzC,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAA,6CAA0B,EAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;QAClE,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QAEzD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC7D,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAnCD,kEAmCC","sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { generateActionTypesContent } from './generate-content';\nimport type { SourceInfo } from './parse-source';\nimport type { ESLint } from './types';\n\n/**\n * Generates action types files for all controllers/services.\n *\n * @param sources - Array of source information objects.\n * @param eslint - Optional ESLint instance and static methods for formatting.\n * @returns Whether all files were generated successfully.\n */\nexport async function generateAllActionTypesFiles(\n sources: SourceInfo[],\n eslint: ESLint | null,\n): Promise<boolean> {\n const outputFiles: string[] = [];\n\n for (const source of sources) {\n console.log(`\\nšŸ”§ Processing ${source.name}...`);\n const outputDir = path.dirname(source.filePath);\n const baseFileName = path.basename(source.filePath, '.ts');\n const outputFile = path.join(\n outputDir,\n `${baseFileName}-method-action-types.ts`,\n );\n\n const generatedContent = generateActionTypesContent(source);\n await fs.promises.writeFile(outputFile, generatedContent, 'utf8');\n outputFiles.push(outputFile);\n console.log(`āœ… Generated action types for ${source.name}`);\n }\n\n if (outputFiles.length > 0 && eslint) {\n console.log('\\nšŸ“ Running ESLint on generated files...');\n\n const results = await eslint.instance.lintFiles(outputFiles);\n await eslint.eslintClass.outputFixes(results);\n const errors = eslint.eslintClass.getErrorResults(results);\n if (errors.length > 0) {\n console.error('āŒ ESLint errors:', errors);\n return false;\n }\n console.log('āœ… ESLint formatting applied');\n }\n\n return true;\n}\n"]}
package/dist/fix.d.cts ADDED
@@ -0,0 +1,11 @@
1
+ import type { SourceInfo } from "./parse-source.cjs";
2
+ import type { ESLint } from "./types.cjs";
3
+ /**
4
+ * Generates action types files for all controllers/services.
5
+ *
6
+ * @param sources - Array of source information objects.
7
+ * @param eslint - Optional ESLint instance and static methods for formatting.
8
+ * @returns Whether all files were generated successfully.
9
+ */
10
+ export declare function generateAllActionTypesFiles(sources: SourceInfo[], eslint: ESLint | null): Promise<boolean>;
11
+ //# sourceMappingURL=fix.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.d.cts","sourceRoot":"","sources":["../src/fix.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,2BAAuB;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAgB;AAEtC;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,OAAO,CAAC,CAgClB"}