@metamask-previews/messenger-cli 0.1.0-preview-3f6f27f → 0.1.0-preview-b6a517f5e

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 (58) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/docs/cli.cjs +199 -0
  3. package/dist/docs/cli.cjs.map +1 -0
  4. package/dist/docs/cli.d.cts +3 -0
  5. package/dist/docs/cli.d.cts.map +1 -0
  6. package/dist/docs/cli.d.mts +3 -0
  7. package/dist/docs/cli.d.mts.map +1 -0
  8. package/dist/docs/cli.mjs +198 -0
  9. package/dist/docs/cli.mjs.map +1 -0
  10. package/dist/docs/discovery.cjs +93 -0
  11. package/dist/docs/discovery.cjs.map +1 -0
  12. package/dist/docs/discovery.d.cts +17 -0
  13. package/dist/docs/discovery.d.cts.map +1 -0
  14. package/dist/docs/discovery.d.mts +17 -0
  15. package/dist/docs/discovery.d.mts.map +1 -0
  16. package/dist/docs/discovery.mjs +65 -0
  17. package/dist/docs/discovery.mjs.map +1 -0
  18. package/dist/docs/extraction.cjs +580 -0
  19. package/dist/docs/extraction.cjs.map +1 -0
  20. package/dist/docs/extraction.d.cts +10 -0
  21. package/dist/docs/extraction.d.cts.map +1 -0
  22. package/dist/docs/extraction.d.mts +10 -0
  23. package/dist/docs/extraction.d.mts.map +1 -0
  24. package/dist/docs/extraction.mjs +554 -0
  25. package/dist/docs/extraction.mjs.map +1 -0
  26. package/dist/docs/generate.cjs +257 -0
  27. package/dist/docs/generate.cjs.map +1 -0
  28. package/dist/docs/generate.d.cts +27 -0
  29. package/dist/docs/generate.d.cts.map +1 -0
  30. package/dist/docs/generate.d.mts +27 -0
  31. package/dist/docs/generate.d.mts.map +1 -0
  32. package/dist/docs/generate.mjs +230 -0
  33. package/dist/docs/generate.mjs.map +1 -0
  34. package/dist/docs/markdown.cjs +210 -0
  35. package/dist/docs/markdown.cjs.map +1 -0
  36. package/dist/docs/markdown.d.cts +35 -0
  37. package/dist/docs/markdown.d.cts.map +1 -0
  38. package/dist/docs/markdown.d.mts +35 -0
  39. package/dist/docs/markdown.d.mts.map +1 -0
  40. package/dist/docs/markdown.mjs +203 -0
  41. package/dist/docs/markdown.mjs.map +1 -0
  42. package/dist/docs/types.cjs +3 -0
  43. package/dist/docs/types.cjs.map +1 -0
  44. package/dist/docs/types.d.cts +23 -0
  45. package/dist/docs/types.d.cts.map +1 -0
  46. package/dist/docs/types.d.mts +23 -0
  47. package/dist/docs/types.d.mts.map +1 -0
  48. package/dist/docs/types.mjs +2 -0
  49. package/dist/docs/types.mjs.map +1 -0
  50. package/package.json +18 -4
  51. package/template/docusaurus.config.ts +123 -0
  52. package/template/src/css/custom.css +314 -0
  53. package/template/static/fonts/MM-Sans/MM_Sans_Mono-Regular.woff2 +0 -0
  54. package/template/static/img/favicons/favicon-96x96.png +0 -0
  55. package/template/static/img/metamask-fox.svg +12 -0
  56. package/template/static/img/metamask-logo-dark.svg +3 -0
  57. package/template/static/img/metamask-logo.svg +3 -0
  58. package/template/tsconfig.json +13 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - Add `messenger-docs` CLI binary for generating Messenger API documentation
13
+
10
14
  ## [0.1.0]
11
15
 
12
16
  ### Added
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const execa_1 = __importDefault(require("execa/index.js"));
31
+ const fs = __importStar(require("node:fs/promises"));
32
+ const path = __importStar(require("node:path"));
33
+ const yargs_1 = __importDefault(require("yargs"));
34
+ const generate_1 = require("./generate.cjs");
35
+ /**
36
+ * Resolve the path to the docusaurus CLI binary and the node_modules
37
+ * directory that contains the Docusaurus packages.
38
+ *
39
+ * @returns The docusaurus binary path and the node_modules directory.
40
+ */
41
+ function resolveDocusaurus() {
42
+ const bin = require.resolve('@docusaurus/core/bin/docusaurus.mjs');
43
+ const coreDir = path.dirname(path.dirname(bin));
44
+ const nodeModules = path.dirname(path.dirname(coreDir));
45
+ return { bin, nodeModules };
46
+ }
47
+ /**
48
+ * Run a Docusaurus command.
49
+ *
50
+ * @param command - The docusaurus command (start, build, serve).
51
+ * @param cwd - The site directory.
52
+ */
53
+ async function runDocusaurus(command, cwd) {
54
+ const { bin, nodeModules } = resolveDocusaurus();
55
+ await (0, execa_1.default)(process.execPath, [bin, command], {
56
+ cwd,
57
+ stdio: 'inherit',
58
+ // eslint-disable-next-line n/no-process-env
59
+ env: { ...process.env, NODE_PATH: nodeModules },
60
+ });
61
+ }
62
+ /**
63
+ * Copy template files into the output directory using fs.cp with filtering.
64
+ *
65
+ * @param outDir - The output directory to set up.
66
+ */
67
+ async function setupSite(outDir) {
68
+ const templateDir = path.resolve(__dirname, '..', '..', 'template');
69
+ const skip = new Set(['node_modules', 'docs']);
70
+ console.log(`\nSetting up Docusaurus site in ${outDir}...`);
71
+ await copyDir(templateDir, outDir, skip);
72
+ // Write a minimal package.json so Docusaurus doesn't warn about a missing one
73
+ const pkgJsonPath = path.join(outDir, 'package.json');
74
+ try {
75
+ await fs.access(pkgJsonPath);
76
+ }
77
+ catch {
78
+ await fs.writeFile(pkgJsonPath, JSON.stringify({ name: 'messenger-docs-site', private: true }, null, 2));
79
+ }
80
+ }
81
+ /**
82
+ * Resolve scanDirs from CLI args, package.json config, or default.
83
+ *
84
+ * @param projectPath - The project root path.
85
+ * @param cliScanDirs - Scan dirs provided via CLI flags.
86
+ * @returns Resolved scan directories.
87
+ */
88
+ async function resolveScanDirs(projectPath, cliScanDirs) {
89
+ if (cliScanDirs.length > 0) {
90
+ return cliScanDirs;
91
+ }
92
+ try {
93
+ const pkgRaw = await fs.readFile(path.join(projectPath, 'package.json'), 'utf8');
94
+ const pkg = JSON.parse(pkgRaw);
95
+ const config = pkg['messenger-docs'];
96
+ if (Array.isArray(config?.scanDirs)) {
97
+ return config.scanDirs;
98
+ }
99
+ }
100
+ catch {
101
+ // No package.json or invalid — use default.
102
+ }
103
+ return ['src'];
104
+ }
105
+ /**
106
+ * Main CLI entry point.
107
+ */
108
+ async function main() {
109
+ const argv = await (0, yargs_1.default)(process.argv.slice(2))
110
+ .command('$0 [project-path]', 'Generate Messenger API documentation for MetaMask controller packages', (yargsInstance) => {
111
+ yargsInstance.positional('project-path', {
112
+ type: 'string',
113
+ description: 'Path to the project to scan',
114
+ default: '.',
115
+ });
116
+ })
117
+ .option('build', {
118
+ type: 'boolean',
119
+ description: 'Generate docs and build static site',
120
+ default: false,
121
+ })
122
+ .option('serve', {
123
+ type: 'boolean',
124
+ description: 'Generate docs, build, and serve static site',
125
+ default: false,
126
+ })
127
+ .option('dev', {
128
+ type: 'boolean',
129
+ description: 'Generate docs and start dev server with hot reload',
130
+ default: false,
131
+ })
132
+ .option('scan-dir', {
133
+ type: 'string',
134
+ array: true,
135
+ description: 'Source directory to scan (repeatable)',
136
+ default: [],
137
+ })
138
+ .option('output', {
139
+ type: 'string',
140
+ description: 'Output directory',
141
+ })
142
+ .epilogue('Source directories can also be configured in package.json:\n "messenger-docs": { "scanDirs": ["app", "src"] }')
143
+ .help().argv;
144
+ const projectPathArg = argv['project-path'];
145
+ const resolvedProjectPath = path.resolve(typeof projectPathArg === 'string' ? projectPathArg : '.');
146
+ const resolvedOutputDir = path.resolve(argv.output ?? path.join(resolvedProjectPath, '.messenger-docs'));
147
+ const scanDirs = await resolveScanDirs(resolvedProjectPath, argv['scan-dir']);
148
+ // Step 1: Generate docs
149
+ await (0, generate_1.generate)({
150
+ projectPath: resolvedProjectPath,
151
+ outputDir: resolvedOutputDir,
152
+ scanDirs,
153
+ });
154
+ // Step 2: If --build, --serve, or --dev, set up and run Docusaurus
155
+ if (argv.build || argv.serve || argv.dev) {
156
+ await setupSite(resolvedOutputDir);
157
+ if (argv.dev) {
158
+ console.log('\nStarting dev server...');
159
+ await runDocusaurus('start', resolvedOutputDir);
160
+ }
161
+ else if (argv.build || argv.serve) {
162
+ console.log('\nBuilding static site...');
163
+ await runDocusaurus('build', resolvedOutputDir);
164
+ if (argv.serve) {
165
+ console.log('\nServing static site...');
166
+ await runDocusaurus('serve', resolvedOutputDir);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ /**
172
+ * Recursively copy a directory, skipping specified directory names.
173
+ *
174
+ * @param src - Source directory.
175
+ * @param dest - Destination directory.
176
+ * @param skip - Set of directory names to skip.
177
+ */
178
+ async function copyDir(src, dest, skip) {
179
+ await fs.mkdir(dest, { recursive: true });
180
+ const entries = await fs.readdir(src, { withFileTypes: true });
181
+ for (const entry of entries) {
182
+ if (skip.has(entry.name)) {
183
+ continue;
184
+ }
185
+ const srcPath = path.join(src, entry.name);
186
+ const destPath = path.join(dest, entry.name);
187
+ if (entry.isDirectory()) {
188
+ await copyDir(srcPath, destPath, skip);
189
+ }
190
+ else {
191
+ await fs.copyFile(srcPath, destPath);
192
+ }
193
+ }
194
+ }
195
+ main().catch((error) => {
196
+ console.error(error);
197
+ process.exitCode = 1;
198
+ });
199
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.cjs","sourceRoot":"","sources":["../../src/docs/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport execa from 'execa';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport yargs from 'yargs';\n\nimport { generate } from './generate';\n\n/**\n * Resolve the path to the docusaurus CLI binary and the node_modules\n * directory that contains the Docusaurus packages.\n *\n * @returns The docusaurus binary path and the node_modules directory.\n */\nfunction resolveDocusaurus(): { bin: string; nodeModules: string } {\n const bin = require.resolve('@docusaurus/core/bin/docusaurus.mjs');\n const coreDir = path.dirname(path.dirname(bin));\n const nodeModules = path.dirname(path.dirname(coreDir));\n return { bin, nodeModules };\n}\n\n/**\n * Run a Docusaurus command.\n *\n * @param command - The docusaurus command (start, build, serve).\n * @param cwd - The site directory.\n */\nasync function runDocusaurus(command: string, cwd: string): Promise<void> {\n const { bin, nodeModules } = resolveDocusaurus();\n await execa(process.execPath, [bin, command], {\n cwd,\n stdio: 'inherit',\n // eslint-disable-next-line n/no-process-env\n env: { ...process.env, NODE_PATH: nodeModules },\n });\n}\n\n/**\n * Copy template files into the output directory using fs.cp with filtering.\n *\n * @param outDir - The output directory to set up.\n */\nasync function setupSite(outDir: string): Promise<void> {\n const templateDir = path.resolve(__dirname, '..', '..', 'template');\n const skip = new Set(['node_modules', 'docs']);\n\n console.log(`\\nSetting up Docusaurus site in ${outDir}...`);\n\n await copyDir(templateDir, outDir, skip);\n\n // Write a minimal package.json so Docusaurus doesn't warn about a missing one\n const pkgJsonPath = path.join(outDir, 'package.json');\n try {\n await fs.access(pkgJsonPath);\n } catch {\n await fs.writeFile(\n pkgJsonPath,\n JSON.stringify({ name: 'messenger-docs-site', private: true }, null, 2),\n );\n }\n}\n\n/**\n * Resolve scanDirs from CLI args, package.json config, or default.\n *\n * @param projectPath - The project root path.\n * @param cliScanDirs - Scan dirs provided via CLI flags.\n * @returns Resolved scan directories.\n */\nasync function resolveScanDirs(\n projectPath: string,\n cliScanDirs: string[],\n): Promise<string[]> {\n if (cliScanDirs.length > 0) {\n return cliScanDirs;\n }\n\n try {\n const pkgRaw = await fs.readFile(\n path.join(projectPath, 'package.json'),\n 'utf8',\n );\n const pkg = JSON.parse(pkgRaw) as Record<string, unknown>;\n const config = pkg['messenger-docs'] as { scanDirs?: string[] } | undefined;\n if (Array.isArray(config?.scanDirs)) {\n return config.scanDirs;\n }\n } catch {\n // No package.json or invalid — use default.\n }\n\n return ['src'];\n}\n\n/**\n * Main CLI entry point.\n */\nasync function main(): Promise<void> {\n const argv = await yargs(process.argv.slice(2))\n .command(\n '$0 [project-path]',\n 'Generate Messenger API documentation for MetaMask controller packages',\n (yargsInstance) => {\n yargsInstance.positional('project-path', {\n type: 'string',\n description: 'Path to the project to scan',\n default: '.',\n });\n },\n )\n .option('build', {\n type: 'boolean',\n description: 'Generate docs and build static site',\n default: false,\n })\n .option('serve', {\n type: 'boolean',\n description: 'Generate docs, build, and serve static site',\n default: false,\n })\n .option('dev', {\n type: 'boolean',\n description: 'Generate docs and start dev server with hot reload',\n default: false,\n })\n .option('scan-dir', {\n type: 'string',\n array: true,\n description: 'Source directory to scan (repeatable)',\n default: [] as string[],\n })\n .option('output', {\n type: 'string',\n description: 'Output directory',\n })\n .epilogue(\n 'Source directories can also be configured in package.json:\\n \"messenger-docs\": { \"scanDirs\": [\"app\", \"src\"] }',\n )\n .help().argv;\n\n const projectPathArg = argv['project-path'];\n const resolvedProjectPath = path.resolve(\n typeof projectPathArg === 'string' ? projectPathArg : '.',\n );\n const resolvedOutputDir = path.resolve(\n argv.output ?? path.join(resolvedProjectPath, '.messenger-docs'),\n );\n const scanDirs = await resolveScanDirs(resolvedProjectPath, argv['scan-dir']);\n\n // Step 1: Generate docs\n await generate({\n projectPath: resolvedProjectPath,\n outputDir: resolvedOutputDir,\n scanDirs,\n });\n\n // Step 2: If --build, --serve, or --dev, set up and run Docusaurus\n if (argv.build || argv.serve || argv.dev) {\n await setupSite(resolvedOutputDir);\n\n if (argv.dev) {\n console.log('\\nStarting dev server...');\n await runDocusaurus('start', resolvedOutputDir);\n } else if (argv.build || argv.serve) {\n console.log('\\nBuilding static site...');\n await runDocusaurus('build', resolvedOutputDir);\n\n if (argv.serve) {\n console.log('\\nServing static site...');\n await runDocusaurus('serve', resolvedOutputDir);\n }\n }\n }\n}\n\n/**\n * Recursively copy a directory, skipping specified directory names.\n *\n * @param src - Source directory.\n * @param dest - Destination directory.\n * @param skip - Set of directory names to skip.\n */\nasync function copyDir(\n src: string,\n dest: string,\n skip: Set<string>,\n): Promise<void> {\n await fs.mkdir(dest, { recursive: true });\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n if (skip.has(entry.name)) {\n continue;\n }\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n if (entry.isDirectory()) {\n await copyDir(srcPath, destPath, skip);\n } else {\n await fs.copyFile(srcPath, destPath);\n }\n }\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exitCode = 1;\n});\n"]}
@@ -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/docs/cli.ts"],"names":[],"mappings":""}
@@ -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/docs/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as $createRequire } from "module";
3
+ const $require = $createRequire(import.meta.url);
4
+ function $__filename(fileUrl) {
5
+ const url = new URL(fileUrl);
6
+ return url.pathname.replace(/^\/([a-zA-Z]:)/u, "$1");
7
+ }
8
+ function $getDirname(path) {
9
+ const sanitisedPath = path.toString().replace(/\\/gu, "/").replace(/\/$/u, "");
10
+ const index = sanitisedPath.lastIndexOf("/");
11
+ if (index === -1) {
12
+ return path;
13
+ }
14
+ if (index === 0) {
15
+ return "/";
16
+ }
17
+ return sanitisedPath.slice(0, index);
18
+ }
19
+ function $__dirname(url) {
20
+ return $getDirname($__filename(url));
21
+ }
22
+ function $importDefault(module) {
23
+ if (module?.__esModule) {
24
+ return module.default;
25
+ }
26
+ return module;
27
+ }
28
+ import $execa from "execa/index.js";
29
+ const execa = $importDefault($execa);
30
+ import * as fs from "node:fs/promises";
31
+ import * as path from "node:path";
32
+ import yargs from "yargs";
33
+ import { generate } from "./generate.mjs";
34
+ /**
35
+ * Resolve the path to the docusaurus CLI binary and the node_modules
36
+ * directory that contains the Docusaurus packages.
37
+ *
38
+ * @returns The docusaurus binary path and the node_modules directory.
39
+ */
40
+ function resolveDocusaurus() {
41
+ const bin = $require.resolve('@docusaurus/core/bin/docusaurus.mjs');
42
+ const coreDir = path.dirname(path.dirname(bin));
43
+ const nodeModules = path.dirname(path.dirname(coreDir));
44
+ return { bin, nodeModules };
45
+ }
46
+ /**
47
+ * Run a Docusaurus command.
48
+ *
49
+ * @param command - The docusaurus command (start, build, serve).
50
+ * @param cwd - The site directory.
51
+ */
52
+ async function runDocusaurus(command, cwd) {
53
+ const { bin, nodeModules } = resolveDocusaurus();
54
+ await execa(process.execPath, [bin, command], {
55
+ cwd,
56
+ stdio: 'inherit',
57
+ // eslint-disable-next-line n/no-process-env
58
+ env: { ...process.env, NODE_PATH: nodeModules },
59
+ });
60
+ }
61
+ /**
62
+ * Copy template files into the output directory using fs.cp with filtering.
63
+ *
64
+ * @param outDir - The output directory to set up.
65
+ */
66
+ async function setupSite(outDir) {
67
+ const templateDir = path.resolve($__dirname(import.meta.url), '..', '..', 'template');
68
+ const skip = new Set(['node_modules', 'docs']);
69
+ console.log(`\nSetting up Docusaurus site in ${outDir}...`);
70
+ await copyDir(templateDir, outDir, skip);
71
+ // Write a minimal package.json so Docusaurus doesn't warn about a missing one
72
+ const pkgJsonPath = path.join(outDir, 'package.json');
73
+ try {
74
+ await fs.access(pkgJsonPath);
75
+ }
76
+ catch {
77
+ await fs.writeFile(pkgJsonPath, JSON.stringify({ name: 'messenger-docs-site', private: true }, null, 2));
78
+ }
79
+ }
80
+ /**
81
+ * Resolve scanDirs from CLI args, package.json config, or default.
82
+ *
83
+ * @param projectPath - The project root path.
84
+ * @param cliScanDirs - Scan dirs provided via CLI flags.
85
+ * @returns Resolved scan directories.
86
+ */
87
+ async function resolveScanDirs(projectPath, cliScanDirs) {
88
+ if (cliScanDirs.length > 0) {
89
+ return cliScanDirs;
90
+ }
91
+ try {
92
+ const pkgRaw = await fs.readFile(path.join(projectPath, 'package.json'), 'utf8');
93
+ const pkg = JSON.parse(pkgRaw);
94
+ const config = pkg['messenger-docs'];
95
+ if (Array.isArray(config?.scanDirs)) {
96
+ return config.scanDirs;
97
+ }
98
+ }
99
+ catch {
100
+ // No package.json or invalid — use default.
101
+ }
102
+ return ['src'];
103
+ }
104
+ /**
105
+ * Main CLI entry point.
106
+ */
107
+ async function main() {
108
+ const argv = await yargs(process.argv.slice(2))
109
+ .command('$0 [project-path]', 'Generate Messenger API documentation for MetaMask controller packages', (yargsInstance) => {
110
+ yargsInstance.positional('project-path', {
111
+ type: 'string',
112
+ description: 'Path to the project to scan',
113
+ default: '.',
114
+ });
115
+ })
116
+ .option('build', {
117
+ type: 'boolean',
118
+ description: 'Generate docs and build static site',
119
+ default: false,
120
+ })
121
+ .option('serve', {
122
+ type: 'boolean',
123
+ description: 'Generate docs, build, and serve static site',
124
+ default: false,
125
+ })
126
+ .option('dev', {
127
+ type: 'boolean',
128
+ description: 'Generate docs and start dev server with hot reload',
129
+ default: false,
130
+ })
131
+ .option('scan-dir', {
132
+ type: 'string',
133
+ array: true,
134
+ description: 'Source directory to scan (repeatable)',
135
+ default: [],
136
+ })
137
+ .option('output', {
138
+ type: 'string',
139
+ description: 'Output directory',
140
+ })
141
+ .epilogue('Source directories can also be configured in package.json:\n "messenger-docs": { "scanDirs": ["app", "src"] }')
142
+ .help().argv;
143
+ const projectPathArg = argv['project-path'];
144
+ const resolvedProjectPath = path.resolve(typeof projectPathArg === 'string' ? projectPathArg : '.');
145
+ const resolvedOutputDir = path.resolve(argv.output ?? path.join(resolvedProjectPath, '.messenger-docs'));
146
+ const scanDirs = await resolveScanDirs(resolvedProjectPath, argv['scan-dir']);
147
+ // Step 1: Generate docs
148
+ await generate({
149
+ projectPath: resolvedProjectPath,
150
+ outputDir: resolvedOutputDir,
151
+ scanDirs,
152
+ });
153
+ // Step 2: If --build, --serve, or --dev, set up and run Docusaurus
154
+ if (argv.build || argv.serve || argv.dev) {
155
+ await setupSite(resolvedOutputDir);
156
+ if (argv.dev) {
157
+ console.log('\nStarting dev server...');
158
+ await runDocusaurus('start', resolvedOutputDir);
159
+ }
160
+ else if (argv.build || argv.serve) {
161
+ console.log('\nBuilding static site...');
162
+ await runDocusaurus('build', resolvedOutputDir);
163
+ if (argv.serve) {
164
+ console.log('\nServing static site...');
165
+ await runDocusaurus('serve', resolvedOutputDir);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ /**
171
+ * Recursively copy a directory, skipping specified directory names.
172
+ *
173
+ * @param src - Source directory.
174
+ * @param dest - Destination directory.
175
+ * @param skip - Set of directory names to skip.
176
+ */
177
+ async function copyDir(src, dest, skip) {
178
+ await fs.mkdir(dest, { recursive: true });
179
+ const entries = await fs.readdir(src, { withFileTypes: true });
180
+ for (const entry of entries) {
181
+ if (skip.has(entry.name)) {
182
+ continue;
183
+ }
184
+ const srcPath = path.join(src, entry.name);
185
+ const destPath = path.join(dest, entry.name);
186
+ if (entry.isDirectory()) {
187
+ await copyDir(srcPath, destPath, skip);
188
+ }
189
+ else {
190
+ await fs.copyFile(srcPath, destPath);
191
+ }
192
+ }
193
+ }
194
+ main().catch((error) => {
195
+ console.error(error);
196
+ process.exitCode = 1;
197
+ });
198
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","sourceRoot":"","sources":["../../src/docs/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,OAAO,MAAK,uBAAc;;AAC1B,OAAO,KAAK,EAAE,yBAAyB;AACvC,OAAO,KAAK,IAAI,kBAAkB;AAClC,OAAO,KAAK,cAAc;AAE1B,OAAO,EAAE,QAAQ,EAAE,uBAAmB;AAEtC;;;;;GAKG;AACH,SAAS,iBAAiB;IACxB,MAAM,GAAG,oBAAmB,qCAAqC,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,GAAW;IACvD,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,iBAAiB,EAAE,CAAC;IACjD,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE;QAC5C,GAAG;QACH,KAAK,EAAE,SAAS;QAChB,4CAA4C;QAC5C,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE;KAChD,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,SAAS,CAAC,MAAc;IACrC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,8BAAY,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,mCAAmC,MAAM,KAAK,CAAC,CAAC;IAE5D,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAEzC,8EAA8E;IAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,SAAS,CAChB,WAAW,EACX,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CACxE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,eAAe,CAC5B,WAAmB,EACnB,WAAqB;IAErB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAC9B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EACtC,MAAM,CACP,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAA4B,CAAC;QAC1D,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAwC,CAAC;QAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YACpC,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC5C,OAAO,CACN,mBAAmB,EACnB,uEAAuE,EACvE,CAAC,aAAa,EAAE,EAAE;QAChB,aAAa,CAAC,UAAU,CAAC,cAAc,EAAE;YACvC,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,6BAA6B;YAC1C,OAAO,EAAE,GAAG;SACb,CAAC,CAAC;IACL,CAAC,CACF;SACA,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,KAAK;KACf,CAAC;SACD,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,6CAA6C;QAC1D,OAAO,EAAE,KAAK;KACf,CAAC;SACD,MAAM,CAAC,KAAK,EAAE;QACb,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,oDAAoD;QACjE,OAAO,EAAE,KAAK;KACf,CAAC;SACD,MAAM,CAAC,UAAU,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,uCAAuC;QACpD,OAAO,EAAE,EAAc;KACxB,CAAC;SACD,MAAM,CAAC,QAAQ,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,kBAAkB;KAChC,CAAC;SACD,QAAQ,CACP,gHAAgH,CACjH;SACA,IAAI,EAAE,CAAC,IAAI,CAAC;IAEf,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5C,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CACtC,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAC1D,CAAC;IACF,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CACpC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CACjE,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9E,wBAAwB;IACxB,MAAM,QAAQ,CAAC;QACb,WAAW,EAAE,mBAAmB;QAChC,SAAS,EAAE,iBAAiB;QAC5B,QAAQ;KACT,CAAC,CAAC;IAEH,mEAAmE;IACnE,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACzC,MAAM,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAEnC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACxC,MAAM,aAAa,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,MAAM,aAAa,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;YAEhD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;gBACxC,MAAM,aAAa,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,OAAO,CACpB,GAAW,EACX,IAAY,EACZ,IAAiB;IAEjB,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport execa from 'execa';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport yargs from 'yargs';\n\nimport { generate } from './generate';\n\n/**\n * Resolve the path to the docusaurus CLI binary and the node_modules\n * directory that contains the Docusaurus packages.\n *\n * @returns The docusaurus binary path and the node_modules directory.\n */\nfunction resolveDocusaurus(): { bin: string; nodeModules: string } {\n const bin = require.resolve('@docusaurus/core/bin/docusaurus.mjs');\n const coreDir = path.dirname(path.dirname(bin));\n const nodeModules = path.dirname(path.dirname(coreDir));\n return { bin, nodeModules };\n}\n\n/**\n * Run a Docusaurus command.\n *\n * @param command - The docusaurus command (start, build, serve).\n * @param cwd - The site directory.\n */\nasync function runDocusaurus(command: string, cwd: string): Promise<void> {\n const { bin, nodeModules } = resolveDocusaurus();\n await execa(process.execPath, [bin, command], {\n cwd,\n stdio: 'inherit',\n // eslint-disable-next-line n/no-process-env\n env: { ...process.env, NODE_PATH: nodeModules },\n });\n}\n\n/**\n * Copy template files into the output directory using fs.cp with filtering.\n *\n * @param outDir - The output directory to set up.\n */\nasync function setupSite(outDir: string): Promise<void> {\n const templateDir = path.resolve(__dirname, '..', '..', 'template');\n const skip = new Set(['node_modules', 'docs']);\n\n console.log(`\\nSetting up Docusaurus site in ${outDir}...`);\n\n await copyDir(templateDir, outDir, skip);\n\n // Write a minimal package.json so Docusaurus doesn't warn about a missing one\n const pkgJsonPath = path.join(outDir, 'package.json');\n try {\n await fs.access(pkgJsonPath);\n } catch {\n await fs.writeFile(\n pkgJsonPath,\n JSON.stringify({ name: 'messenger-docs-site', private: true }, null, 2),\n );\n }\n}\n\n/**\n * Resolve scanDirs from CLI args, package.json config, or default.\n *\n * @param projectPath - The project root path.\n * @param cliScanDirs - Scan dirs provided via CLI flags.\n * @returns Resolved scan directories.\n */\nasync function resolveScanDirs(\n projectPath: string,\n cliScanDirs: string[],\n): Promise<string[]> {\n if (cliScanDirs.length > 0) {\n return cliScanDirs;\n }\n\n try {\n const pkgRaw = await fs.readFile(\n path.join(projectPath, 'package.json'),\n 'utf8',\n );\n const pkg = JSON.parse(pkgRaw) as Record<string, unknown>;\n const config = pkg['messenger-docs'] as { scanDirs?: string[] } | undefined;\n if (Array.isArray(config?.scanDirs)) {\n return config.scanDirs;\n }\n } catch {\n // No package.json or invalid — use default.\n }\n\n return ['src'];\n}\n\n/**\n * Main CLI entry point.\n */\nasync function main(): Promise<void> {\n const argv = await yargs(process.argv.slice(2))\n .command(\n '$0 [project-path]',\n 'Generate Messenger API documentation for MetaMask controller packages',\n (yargsInstance) => {\n yargsInstance.positional('project-path', {\n type: 'string',\n description: 'Path to the project to scan',\n default: '.',\n });\n },\n )\n .option('build', {\n type: 'boolean',\n description: 'Generate docs and build static site',\n default: false,\n })\n .option('serve', {\n type: 'boolean',\n description: 'Generate docs, build, and serve static site',\n default: false,\n })\n .option('dev', {\n type: 'boolean',\n description: 'Generate docs and start dev server with hot reload',\n default: false,\n })\n .option('scan-dir', {\n type: 'string',\n array: true,\n description: 'Source directory to scan (repeatable)',\n default: [] as string[],\n })\n .option('output', {\n type: 'string',\n description: 'Output directory',\n })\n .epilogue(\n 'Source directories can also be configured in package.json:\\n \"messenger-docs\": { \"scanDirs\": [\"app\", \"src\"] }',\n )\n .help().argv;\n\n const projectPathArg = argv['project-path'];\n const resolvedProjectPath = path.resolve(\n typeof projectPathArg === 'string' ? projectPathArg : '.',\n );\n const resolvedOutputDir = path.resolve(\n argv.output ?? path.join(resolvedProjectPath, '.messenger-docs'),\n );\n const scanDirs = await resolveScanDirs(resolvedProjectPath, argv['scan-dir']);\n\n // Step 1: Generate docs\n await generate({\n projectPath: resolvedProjectPath,\n outputDir: resolvedOutputDir,\n scanDirs,\n });\n\n // Step 2: If --build, --serve, or --dev, set up and run Docusaurus\n if (argv.build || argv.serve || argv.dev) {\n await setupSite(resolvedOutputDir);\n\n if (argv.dev) {\n console.log('\\nStarting dev server...');\n await runDocusaurus('start', resolvedOutputDir);\n } else if (argv.build || argv.serve) {\n console.log('\\nBuilding static site...');\n await runDocusaurus('build', resolvedOutputDir);\n\n if (argv.serve) {\n console.log('\\nServing static site...');\n await runDocusaurus('serve', resolvedOutputDir);\n }\n }\n }\n}\n\n/**\n * Recursively copy a directory, skipping specified directory names.\n *\n * @param src - Source directory.\n * @param dest - Destination directory.\n * @param skip - Set of directory names to skip.\n */\nasync function copyDir(\n src: string,\n dest: string,\n skip: Set<string>,\n): Promise<void> {\n await fs.mkdir(dest, { recursive: true });\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n if (skip.has(entry.name)) {\n continue;\n }\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n if (entry.isDirectory()) {\n await copyDir(srcPath, destPath, skip);\n } else {\n await fs.copyFile(srcPath, destPath);\n }\n }\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exitCode = 1;\n});\n"]}
@@ -0,0 +1,93 @@
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.findDtsFiles = exports.findTsFiles = void 0;
27
+ const fs = __importStar(require("node:fs/promises"));
28
+ const path = __importStar(require("node:path"));
29
+ const SKIP_DIRS = new Set([
30
+ 'node_modules',
31
+ 'dist',
32
+ '__tests__',
33
+ 'tests',
34
+ 'test',
35
+ '__mocks__',
36
+ ]);
37
+ const SKIP_SUFFIXES = ['.test.ts', '.test-d.ts', '.spec.ts', '.d.ts'];
38
+ /**
39
+ * Find all non-test TypeScript source files in a directory.
40
+ * Skips node_modules, dist, test directories, and declaration files.
41
+ *
42
+ * @param dir - The directory to search.
43
+ * @returns A promise that resolves to an array of absolute file paths.
44
+ */
45
+ async function findTsFiles(dir) {
46
+ const results = [];
47
+ async function walk(directory) {
48
+ const entries = await fs.readdir(directory, { withFileTypes: true });
49
+ for (const entry of entries) {
50
+ const fullPath = path.join(directory, entry.name);
51
+ if (entry.isDirectory()) {
52
+ if (!SKIP_DIRS.has(entry.name)) {
53
+ await walk(fullPath);
54
+ }
55
+ }
56
+ else if (entry.name.endsWith('.ts') &&
57
+ !SKIP_SUFFIXES.some((suffix) => entry.name.endsWith(suffix))) {
58
+ results.push(fullPath);
59
+ }
60
+ }
61
+ }
62
+ await walk(dir);
63
+ return results;
64
+ }
65
+ exports.findTsFiles = findTsFiles;
66
+ /**
67
+ * Find all `.d.cts` declaration files in a directory.
68
+ * Skips nested node_modules subdirectories.
69
+ *
70
+ * @param dir - The directory to search.
71
+ * @returns A promise that resolves to an array of absolute file paths.
72
+ */
73
+ async function findDtsFiles(dir) {
74
+ const results = [];
75
+ async function walk(directory) {
76
+ const entries = await fs.readdir(directory, { withFileTypes: true });
77
+ for (const entry of entries) {
78
+ const fullPath = path.join(directory, entry.name);
79
+ if (entry.isDirectory()) {
80
+ if (entry.name !== 'node_modules') {
81
+ await walk(fullPath);
82
+ }
83
+ }
84
+ else if (entry.name.endsWith('.d.cts')) {
85
+ results.push(fullPath);
86
+ }
87
+ }
88
+ }
89
+ await walk(dir);
90
+ return results;
91
+ }
92
+ exports.findDtsFiles = findDtsFiles;
93
+ //# sourceMappingURL=discovery.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.cjs","sourceRoot":"","sources":["../../src/docs/discovery.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qDAAuC;AACvC,gDAAkC;AAElC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,cAAc;IACd,MAAM;IACN,WAAW;IACX,OAAO;IACP,MAAM;IACN,WAAW;CACZ,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AAEtE;;;;;;GAMG;AACI,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,IAAI,CAAC,SAAiB;QACnC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/B,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;iBAAM,IACL,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC1B,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAC5D,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,OAAO,CAAC;AACjB,CAAC;AAtBD,kCAsBC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,IAAI,CAAC,SAAiB;QACnC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBAClC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,OAAO,CAAC;AACjB,CAAC;AAnBD,oCAmBC","sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nconst SKIP_DIRS = new Set([\n 'node_modules',\n 'dist',\n '__tests__',\n 'tests',\n 'test',\n '__mocks__',\n]);\n\nconst SKIP_SUFFIXES = ['.test.ts', '.test-d.ts', '.spec.ts', '.d.ts'];\n\n/**\n * Find all non-test TypeScript source files in a directory.\n * Skips node_modules, dist, test directories, and declaration files.\n *\n * @param dir - The directory to search.\n * @returns A promise that resolves to an array of absolute file paths.\n */\nexport async function findTsFiles(dir: string): Promise<string[]> {\n const results: string[] = [];\n\n async function walk(directory: string): Promise<void> {\n const entries = await fs.readdir(directory, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n if (!SKIP_DIRS.has(entry.name)) {\n await walk(fullPath);\n }\n } else if (\n entry.name.endsWith('.ts') &&\n !SKIP_SUFFIXES.some((suffix) => entry.name.endsWith(suffix))\n ) {\n results.push(fullPath);\n }\n }\n }\n\n await walk(dir);\n return results;\n}\n\n/**\n * Find all `.d.cts` declaration files in a directory.\n * Skips nested node_modules subdirectories.\n *\n * @param dir - The directory to search.\n * @returns A promise that resolves to an array of absolute file paths.\n */\nexport async function findDtsFiles(dir: string): Promise<string[]> {\n const results: string[] = [];\n\n async function walk(directory: string): Promise<void> {\n const entries = await fs.readdir(directory, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== 'node_modules') {\n await walk(fullPath);\n }\n } else if (entry.name.endsWith('.d.cts')) {\n results.push(fullPath);\n }\n }\n }\n\n await walk(dir);\n return results;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Find all non-test TypeScript source files in a directory.
3
+ * Skips node_modules, dist, test directories, and declaration files.
4
+ *
5
+ * @param dir - The directory to search.
6
+ * @returns A promise that resolves to an array of absolute file paths.
7
+ */
8
+ export declare function findTsFiles(dir: string): Promise<string[]>;
9
+ /**
10
+ * Find all `.d.cts` declaration files in a directory.
11
+ * Skips nested node_modules subdirectories.
12
+ *
13
+ * @param dir - The directory to search.
14
+ * @returns A promise that resolves to an array of absolute file paths.
15
+ */
16
+ export declare function findDtsFiles(dir: string): Promise<string[]>;
17
+ //# sourceMappingURL=discovery.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.cts","sourceRoot":"","sources":["../../src/docs/discovery.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBhE;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBjE"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Find all non-test TypeScript source files in a directory.
3
+ * Skips node_modules, dist, test directories, and declaration files.
4
+ *
5
+ * @param dir - The directory to search.
6
+ * @returns A promise that resolves to an array of absolute file paths.
7
+ */
8
+ export declare function findTsFiles(dir: string): Promise<string[]>;
9
+ /**
10
+ * Find all `.d.cts` declaration files in a directory.
11
+ * Skips nested node_modules subdirectories.
12
+ *
13
+ * @param dir - The directory to search.
14
+ * @returns A promise that resolves to an array of absolute file paths.
15
+ */
16
+ export declare function findDtsFiles(dir: string): Promise<string[]>;
17
+ //# sourceMappingURL=discovery.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.mts","sourceRoot":"","sources":["../../src/docs/discovery.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBhE;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBjE"}