jsx-prop-lookup-mcp-server 3.3.3 → 3.4.0

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.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
- # JSX Prop Lookup MCP Server
1
+ # JSX Prop Analyzer (CLI & MCP Server)
2
2
 
3
- An MCP (Model Context Protocol) server that analyzes JSX prop usage in React/TypeScript codebases using AST parsing.
3
+ A command-line tool and MCP (Model Context Protocol) server for analyzing JSX prop usage in React/TypeScript codebases using AST parsing.
4
+
5
+ This tool can be used as a standalone CLI (`jsx-analyzer`) or as an MCP server (`jsx-prop-lookup-mcp-server`).
4
6
 
5
7
  ## Features
6
8
 
@@ -12,60 +14,96 @@ An MCP (Model Context Protocol) server that analyzes JSX prop usage in React/Typ
12
14
 
13
15
  ## Installation
14
16
 
15
- ### Option 1: Use with npx (Recommended)
16
- No installation required! Use directly with npx:
17
+ This project uses Bun as its package manager and runtime.
18
+
19
+ ### Standalone CLI
17
20
 
18
21
  ```bash
19
- npx jsx-prop-lookup-mcp-server
22
+ # Install the package globally
23
+ bun install -g jsx-prop-lookup-mcp-server
24
+
25
+ # Now you can use the jsx-analyzer command
26
+ jsx-analyzer --help
20
27
  ```
21
28
 
22
- ### Option 2: Install Globally
29
+ ### MCP Server
30
+
31
+ If you wish to use the MCP server, you can still use `npx` which will handle the installation for you:
32
+
23
33
  ```bash
24
- npm install -g jsx-prop-lookup-mcp-server
25
- jsx-prop-lookup-mcp-server
34
+ npx jsx-prop-lookup-mcp-server
26
35
  ```
27
36
 
28
- ### Option 3: Development Setup
37
+ ### Development Setup
38
+
29
39
  ```bash
30
- git clone https://github.com/your-username/jsx-prop-lookup-mcp-server.git
40
+ git clone https://github.com/lmn451/jsx-prop-lookup-mcp-server.git
31
41
  cd jsx-prop-lookup-mcp-server
32
- npm install
33
- npm run build
34
- npm start
42
+ bun install
43
+ bun run build
35
44
  ```
36
45
 
37
- ## Usage
46
+ ## Standalone CLI Usage
47
+
48
+ The `jsx-analyzer` command allows you to perform analysis directly from your terminal.
49
+
50
+ **Commands:**
51
+
52
+ - `analyze_jsx_props`: Analyze JSX prop usage in files or directories.
53
+
54
+ - `jsx-analyzer analyze_jsx_props --path <file_or_dir> [--componentName <name>] [--propName <name>]`
55
+
56
+ - `find_prop_usage`: Find all usages of a specific prop across JSX files.
57
+
58
+ - `jsx-analyzer find_prop_usage --propName <prop_name> --path <directory>`
59
+
60
+ - `get_component_props`: Get all props used by a specific component.
61
+
62
+ - `jsx-analyzer get_component_props --componentName <component_name> --path <directory>`
63
+
64
+ - `find_components_without_prop`: Find component instances that are missing a required prop.
65
+ - `jsx-analyzer find_components_without_prop --componentName <name> --requiredProp <prop> --path <directory>`
66
+
67
+ ## MCP Server Usage
38
68
 
39
69
  The server provides four main tools:
40
70
 
41
71
  ### 1. `analyze_jsx_props`
72
+
42
73
  Analyze JSX prop usage in files or directories.
43
74
 
44
75
  **Parameters:**
76
+
45
77
  - `path` (required): File or directory path to analyze
46
78
  - `componentName` (optional): Specific component name to analyze
47
79
  - `propName` (optional): Specific prop name to search for
48
80
  - `includeTypes` (optional): Include TypeScript type information (default: true)
49
81
 
50
82
  ### 2. `find_prop_usage`
83
+
51
84
  Find all usages of a specific prop across JSX files.
52
85
 
53
86
  **Parameters:**
87
+
54
88
  - `propName` (required): Name of the prop to search for
55
89
  - `directory` (optional): Directory to search in (default: ".")
56
90
  - `componentName` (optional): Limit search to specific component
57
91
 
58
92
  ### 3. `get_component_props`
93
+
59
94
  Get all props used by a specific component.
60
95
 
61
96
  **Parameters:**
97
+
62
98
  - `componentName` (required): Name of the component to analyze
63
99
  - `directory` (optional): Directory to search in (default: ".")
64
100
 
65
101
  ### 4. `find_components_without_prop`
102
+
66
103
  Find component instances that are missing a required prop (e.g., Select components without width prop).
67
104
 
68
105
  **Parameters:**
106
+
69
107
  - `componentName` (required): Name of the component to check (e.g., "Select")
70
108
  - `requiredProp` (required): Name of the required prop (e.g., "width")
71
109
  - `directory` (optional): Directory to search in (default: ".")
@@ -118,6 +156,7 @@ Find component instances that are missing a required prop (e.g., Select componen
118
156
  ## MCP Client Configuration
119
157
 
120
158
  ### Using with npx (Recommended)
159
+
121
160
  Add to your MCP client configuration:
122
161
 
123
162
  ```json
@@ -132,6 +171,7 @@ Add to your MCP client configuration:
132
171
  ```
133
172
 
134
173
  ### Using with global installation
174
+
135
175
  ```json
136
176
  {
137
177
  "mcpServers": {
@@ -143,11 +183,12 @@ Add to your MCP client configuration:
143
183
  ```
144
184
 
145
185
  ### Using with local development
186
+
146
187
  ```json
147
188
  {
148
189
  "mcpServers": {
149
190
  "jsx-prop-lookup": {
150
- "command": "node",
191
+ "command": "bun",
151
192
  "args": ["dist/index.js"],
152
193
  "cwd": "/path/to/jsx-prop-lookup-mcp-server"
153
194
  }
@@ -157,8 +198,12 @@ Add to your MCP client configuration:
157
198
 
158
199
  ## Development
159
200
 
160
- ```bash
161
- npm run dev # Run in development mode
162
- npm run build # Build for production
163
- npm start # Run built version
164
- ```
201
+ The project uses Bun for package management and as a runtime.
202
+
203
+ - `bun run dev`: Run the MCP server in development mode with hot-reloading.
204
+ - `bun run build`: Build the project. This runs two sub-scripts:
205
+ - `build:js`: Creates a fast JavaScript build using Bun's bundler.
206
+ - `build:types`: Creates TypeScript declaration files (`.d.ts`) using `tsc`.
207
+ - `bun run typecheck`: Run a full type-check of the project.
208
+ - `bun run start`: Run the production MCP server from the `dist` directory.
209
+ - `bun test`: Run the test suite.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { spawn } from 'child_process';
3
+ import * as path from 'path';
4
+ const cliPath = path.resolve(__dirname, '../../dist/index.js');
5
+ describe('CLI Tests', () => {
6
+ let cliProcess;
7
+ let responses = [];
8
+ beforeAll(() => {
9
+ cliProcess = spawn('node', [cliPath]);
10
+ cliProcess.stdout.on('data', (data) => {
11
+ responses.push(JSON.parse(data.toString()));
12
+ });
13
+ cliProcess.stderr.on('data', (data) => {
14
+ console.error(`CLI STDERR: ${data.toString()}`);
15
+ });
16
+ });
17
+ afterAll(() => {
18
+ cliProcess.kill();
19
+ });
20
+ const sendRequest = (request) => {
21
+ cliProcess.stdin.write(JSON.stringify(request) + '\n');
22
+ };
23
+ it('should start and list tools', async () => {
24
+ sendRequest({
25
+ type: 'request',
26
+ id: '1',
27
+ schema: 'mcp:request:list_tools',
28
+ params: {},
29
+ });
30
+ await new Promise(resolve => setTimeout(resolve, 500)); // Wait for response
31
+ const response = responses.find(r => r.id === '1');
32
+ expect(response).toBeDefined();
33
+ expect(response.type).toBe('response');
34
+ expect(response.payload.tools).toHaveLength(4);
35
+ expect(response.payload.tools.map((t) => t.name)).toEqual([
36
+ 'analyze_jsx_props',
37
+ 'find_prop_usage',
38
+ 'get_component_props',
39
+ 'find_components_without_prop',
40
+ ]);
41
+ });
42
+ it('should respond to analyze_jsx_props tool call', async () => {
43
+ const fixturesPath = path.resolve(__dirname, 'fixtures');
44
+ sendRequest({
45
+ type: 'request',
46
+ id: '2',
47
+ schema: 'mcp:request:call_tool',
48
+ params: {
49
+ name: 'analyze_jsx_props',
50
+ arguments: {
51
+ path: fixturesPath,
52
+ componentName: 'Button',
53
+ },
54
+ },
55
+ });
56
+ await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for analysis
57
+ const response = responses.find(r => r.id === '2');
58
+ expect(response).toBeDefined();
59
+ expect(response.type).toBe('response');
60
+ const content = JSON.parse(response.payload.content[0].text);
61
+ expect(content.components).toHaveLength(1);
62
+ expect(content.components[0].componentName).toBe('Button');
63
+ });
64
+ });
65
+ //# sourceMappingURL=cli.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const App: () => any;
2
+ export default App;
3
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/App.tsx"],"names":[],"mappings":"AAIA,QAAA,MAAM,GAAG,WAWR,CAAC;AAEF,eAAe,GAAG,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Card } from './Card';
3
+ const App = () => {
4
+ return (<div>
5
+ <h1>My App</h1>
6
+ <Card title="My Card" content="This is a card component." onAction={() => console.log('Card action')}/>
7
+ </div>);
8
+ };
9
+ export default App;
10
+ //# sourceMappingURL=App.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/App.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,MAAM,GAAG,GAAG,GAAG,EAAE;IACf,OAAO,CACL,CAAC,GAAG,CACF;MAAA,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CACd;MAAA,CAAC,IAAI,CACH,KAAK,CAAC,SAAS,CACf,OAAO,CAAC,2BAA2B,CACnC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,EAE/C;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,GAAG,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export interface ButtonProps {
3
+ onClick: () => void;
4
+ children: React.ReactNode;
5
+ disabled?: boolean;
6
+ }
7
+ export declare const Button: React.FC<ButtonProps>;
8
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/Button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAMxC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export const Button = ({ onClick, children, disabled }) => {
3
+ return (<button onClick={onClick} disabled={disabled}>
4
+ {children}
5
+ </button>);
6
+ };
7
+ //# sourceMappingURL=Button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/Button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,MAAM,CAAC,MAAM,MAAM,GAA0B,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC/E,OAAO,CACL,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAC3C;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,MAAM,CAAC,CACV,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export interface CardProps {
3
+ title: string;
4
+ content: string;
5
+ onAction: () => void;
6
+ }
7
+ export declare const Card: React.FC<CardProps>;
8
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/Card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAQpC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Button } from './Button';
3
+ export const Card = ({ title, content, onAction }) => {
4
+ return (<div>
5
+ <h2>{title}</h2>
6
+ <p>{content}</p>
7
+ <Button onClick={onAction}>Click me</Button>
8
+ </div>);
9
+ };
10
+ //# sourceMappingURL=Card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/Card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAQlC,MAAM,CAAC,MAAM,IAAI,GAAwB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;IACxE,OAAO,CACL,CAAC,GAAG,CACF;MAAA,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CACf;MAAA,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CACf;MAAA,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,MAAM,CAC7C;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=jsx-analyzer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-analyzer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/jsx-analyzer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { JSXPropAnalyzer } from '../jsx-analyzer';
3
+ import * as path from 'path';
4
+ describe('JSXPropAnalyzer', () => {
5
+ const analyzer = new JSXPropAnalyzer();
6
+ const fixturesPath = path.resolve(__dirname, 'fixtures');
7
+ it('should correctly analyze props in a simple component', async () => {
8
+ const buttonPath = path.join(fixturesPath, 'Button.tsx');
9
+ const result = await analyzer.analyzeProps(buttonPath, 'Button');
10
+ expect(result.components).toHaveLength(1);
11
+ const buttonComponent = result.components[0];
12
+ expect(buttonComponent.componentName).toBe('Button');
13
+ expect(buttonComponent.props).toHaveLength(3);
14
+ expect(buttonComponent.props.map(p => p.propName)).toEqual(['onClick', 'children', 'disabled']);
15
+ });
16
+ it('should find all usages of a specific prop', async () => {
17
+ const propUsages = await analyzer.findPropUsage('onClick', fixturesPath);
18
+ expect(propUsages.length).toBeGreaterThan(0);
19
+ const buttonUsage = propUsages.find(p => p.componentName === 'Button');
20
+ expect(buttonUsage).toBeDefined();
21
+ expect(buttonUsage?.propName).toBe('onClick');
22
+ });
23
+ it('should get all props for a specific component', async () => {
24
+ const components = await analyzer.getComponentProps('Card', fixturesPath);
25
+ expect(components).toHaveLength(1);
26
+ const cardComponent = components[0];
27
+ expect(cardComponent.componentName).toBe('Card');
28
+ expect(cardComponent.props.map(p => p.propName)).toEqual(['title', 'content', 'onAction']);
29
+ });
30
+ it('should find components without a required prop', async () => {
31
+ // First, let's add a component without the required prop
32
+ const appContent = `
33
+ import React from 'react';
34
+ import { Button } from './Button';
35
+
36
+ const App = () => {
37
+ return (
38
+ <div>
39
+ <Button>Missing onClick</Button>
40
+ </div>
41
+ );
42
+ };
43
+ `;
44
+ const fs = await import('fs/promises');
45
+ const tempFilePath = path.join(fixturesPath, 'tempApp.tsx');
46
+ await fs.writeFile(tempFilePath, appContent);
47
+ const result = await analyzer.findComponentsWithoutProp('Button', 'onClick', fixturesPath);
48
+ // Cleanup the temp file
49
+ await fs.unlink(tempFilePath);
50
+ expect(result.missingPropUsages.length).toBe(1);
51
+ const missingProp = result.missingPropUsages[0];
52
+ expect(missingProp.componentName).toBe('Button');
53
+ expect(missingProp.file).toContain('tempApp.tsx');
54
+ });
55
+ });
56
+ //# sourceMappingURL=jsx-analyzer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-analyzer.test.js","sourceRoot":"","sources":["../../src/__tests__/jsx-analyzer.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,MAAM,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAEzD,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEjE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACzE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC;QACvE,MAAM,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC1E,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,yDAAyD;QACzD,MAAM,UAAU,GAAG;;;;;;;;;;;CAWtB,CAAC;QACE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAE7C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,yBAAyB,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QAE3F,wBAAwB;QACxB,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAE9B,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}