dittory 0.0.1 → 0.0.3

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,73 +1,267 @@
1
1
  # dittory
2
2
 
3
- Reactコンポーネントや関数の引数使用状況を静的解析し、**常に同じ値が渡されているパラメータ**を検出するCLIツールです。
3
+ [![npm version](https://img.shields.io/npm/v/dittory.svg)](https://www.npmjs.com/package/dittory)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
 
5
- ## 用途
6
+ A static analysis CLI that detects **parameters always receiving the same value** in React components and functions.
6
7
 
7
- - 不要なパラメータの発見(デフォルト値化の候補)
8
- - コードベースのリファクタリング支援
9
- - APIの簡素化
8
+ > **dittory** = "ditto" (same) + "-ory" — finds repetitive patterns in your code
10
9
 
11
- ## インストール
10
+ ## Why?
11
+
12
+ When a prop or argument is always passed the same value across your codebase, it's often a sign that:
13
+
14
+ - The parameter could be **removed** and replaced with a default value
15
+ - The API could be **simplified** by eliminating unnecessary options
16
+ - There's **copy-paste code** that should be refactored
17
+
18
+ dittory helps you identify these opportunities automatically.
19
+
20
+ ## Installation
12
21
 
13
22
  ```bash
14
23
  npm install -g dittory
15
24
  ```
16
25
 
17
- ## 使い方
26
+ Or use directly with npx:
27
+
28
+ ```bash
29
+ npx dittory
30
+ ```
31
+
32
+ ## Usage
18
33
 
19
34
  ```bash
20
- # srcディレクトリを解析(デフォルト)
35
+ # Analyze ./src directory (default)
21
36
  dittory
22
37
 
23
- # 特定のディレクトリを解析
38
+ # Analyze a specific directory
24
39
  dittory ./path/to/src
25
40
 
26
- # 最小使用回数を指定(デフォルト: 2
41
+ # Set minimum usage count (default: 2)
27
42
  dittory --min=3
28
43
 
29
- # 解析対象を指定
30
- dittory --target=components # Reactコンポーネントのみ
31
- dittory --target=functions # 関数・クラスメソッドのみ
32
- dittory --target=all # 両方(デフォルト)
44
+ # Analyze specific targets
45
+ dittory --target=components # React components only
46
+ dittory --target=functions # Functions and class methods only
47
+ dittory --target=all # Both (default)
48
+
49
+ # Output mode
50
+ dittory --output=simple # Show only constants (default)
51
+ dittory --output=verbose # Show all exported functions and details
52
+ ```
53
+
54
+ ## Example Output
55
+
56
+ ```
57
+ Button src/components/Button.tsx:15
58
+ Constant Arguments:
59
+ - variant = "primary"
60
+ Usages (5):
61
+ - src/pages/Home.tsx:23
62
+ - src/pages/About.tsx:45
63
+ - src/pages/Contact.tsx:12
64
+ - src/features/auth/Login.tsx:67
65
+ - src/features/auth/Register.tsx:89
66
+
67
+
68
+ fetchUser src/api/users.ts:42
69
+ Constant Arguments:
70
+ - includeProfile = true
71
+ - cache = false
72
+ Usages (3):
73
+ - src/hooks/useUser.ts:18
74
+ - src/pages/Profile.tsx:31
75
+ - src/components/UserCard.tsx:55
76
+
77
+
78
+ ---
79
+ Found 2 function(s) with constant arguments out of 24 function(s).
80
+ ```
81
+
82
+ ## What It Detects
83
+
84
+ | Target | Description |
85
+ |--------|-------------|
86
+ | **React Components** | Props passed to JSX elements (`<Button variant="primary" />`) |
87
+ | **Functions** | Arguments passed to exported function calls |
88
+ | **Class Methods** | Arguments passed to methods of exported classes |
89
+
90
+ ## Supported Detection Patterns
91
+
92
+ ### Value Types
93
+
94
+ | Pattern | Example | Supported |
95
+ |---------|---------|-----------|
96
+ | String literals | `"hello"` | ✅ |
97
+ | Number literals | `42` | ✅ |
98
+ | Boolean literals | `true`, `false` | ✅ |
99
+ | Enum values | `Status.Active` | ✅ |
100
+ | Imported constants | `import { VALUE } from "./constants"` | ✅ |
101
+ | Variable references | `const x = 3; fn(x)` | ✅ |
102
+ | Variable chains | `const a = 1; const b = a; fn(b)` → resolves to `1` | ✅ |
103
+ | Object literals | `{ nested: { value: 1 } }` | ✅ |
104
+ | Function references | `onClick={handleClick}` | ✅ (by location) |
105
+ | `undefined` | `fn(undefined)` | ✅ |
106
+
107
+ ### Parameter Propagation (Call Graph Analysis)
108
+
109
+ dittory can track values through component/function chains:
110
+
111
+ ```tsx
112
+ // App passes "42" to Parent, Parent passes props.number to Child
113
+ // → Child.number is detected as constant "42"
114
+
115
+ const Child = ({ number }) => <div>{number}</div>;
116
+ const Parent = ({ number }) => <Child number={number} />;
117
+ export const App = () => <Parent number="42" />;
118
+ ```
119
+
120
+ | Pattern | Example | Supported |
121
+ |---------|---------|-----------|
122
+ | Direct props access | `props.value` | ✅ |
123
+ | Destructured props | `({ value }) => ...` | ✅ |
124
+ | Nested access | `props.user.name` | ✅ |
125
+ | Multi-level chains | `A → B → C` propagation | ✅ |
126
+ | Circular reference protection | Prevents infinite loops | ✅ |
127
+
128
+ ### Scope
129
+
130
+ | Pattern | Supported |
131
+ |---------|-----------|
132
+ | Exported functions/components | ✅ |
133
+ | Non-exported (internal) functions | ❌ |
134
+
135
+ ## Unsupported Detection Patterns
33
136
 
34
- # ヘルプ
35
- dittory --help
137
+ ### Spread Syntax
138
+
139
+ ```tsx
140
+ // ❌ Props passed via spread are NOT tracked
141
+ const Parent = ({ num, ...others }) => <Child {...others} />;
142
+ ```
143
+
144
+ ### Dynamic Values
145
+
146
+ ```tsx
147
+ // ❌ Values computed at runtime
148
+ <Button count={items.length} />
149
+ <Input value={getValue()} />
150
+ <List items={data.filter(x => x.active)} />
151
+ ```
152
+
153
+ ### Conditional Branches
154
+
155
+ When different code paths pass different values, dittory correctly identifies them as different values (not constant):
156
+
157
+ ```tsx
158
+ // Different values in branches → correctly NOT reported as constant
159
+ const App = () => {
160
+ if (condition) {
161
+ return <Button variant="primary" />;
162
+ }
163
+ return <Button variant="secondary" />;
164
+ };
165
+ ```
166
+
167
+ Note: This is expected behavior. dittory performs static analysis and considers all code paths.
168
+
169
+ ### Template Literals
170
+
171
+ ```tsx
172
+ // ❌ Template strings with expressions
173
+ <Label text={`Hello, ${name}`} />
174
+ ```
175
+
176
+ ### Array/Object Spread in Arguments
177
+
178
+ ```tsx
179
+ // ❌ Spread in function arguments
180
+ fn(...args);
181
+ fn({ ...defaults, custom: value });
182
+ ```
183
+
184
+ ### Higher-Order Components / Render Props
185
+
186
+ ```tsx
187
+ // ❌ HOC patterns are not analyzed
188
+ const Enhanced = withAuth(Component);
189
+ <Enhanced role="admin" />
190
+ ```
191
+
192
+ ## CLI Options
193
+
194
+ | Option | Description | Default |
195
+ |--------|-------------|---------|
196
+ | `--min=<n>` | Minimum number of usages to consider | `2` |
197
+ | `--target=<mode>` | What to analyze: `all`, `components`, `functions` | `all` |
198
+ | `--output=<mode>` | Output verbosity: `simple`, `verbose` | `simple` |
199
+ | `--tsconfig=<path>` | Path to tsconfig.json | `./tsconfig.json` |
200
+ | `--help` | Show help message | — |
201
+
202
+ ## Configuration File
203
+
204
+ Create a configuration file to set default options. dittory looks for:
205
+
206
+ 1. `dittory.config.js` or `dittory.config.mjs`
207
+ 2. `dittory.config.json`
208
+
209
+ ```js
210
+ // dittory.config.js
211
+ /** @type {import('dittory').DittoryConfig} */
212
+ export default {
213
+ minUsages: 3,
214
+ target: "components",
215
+ output: "verbose",
216
+ tsconfig: "./tsconfig.app.json",
217
+ targetDir: "./src",
218
+ };
36
219
  ```
37
220
 
38
- ## 出力例
221
+ **Priority:** CLI options > Config file > Default values
222
+
223
+ ## Disabling Detection
224
+
225
+ Exclude specific usages from detection using comments:
226
+
227
+ ```ts
228
+ // Exclude the next line
229
+ // dittory-disable-next-line
230
+ fetchData(id, { cache: false });
39
231
 
232
+ // Exclude the same line
233
+ fetchData(id, { cache: false }); // dittory-disable-line
40
234
  ```
41
- 解析対象ディレクトリ: ./src
42
- 最小使用箇所数: 2
43
- 解析対象: all
44
235
 
45
- 1. exportされたコンポーネントを収集中...
46
- → 15個のコンポーネントを検出
236
+ Works alongside other directives like `eslint-disable-line` or `@ts-ignore`.
47
237
 
48
- === 常に同じ値が渡されているprops ===
238
+ ## Use Cases
49
239
 
50
- コンポーネント: Button
51
- 定義: src/components/Button.tsx
52
- prop: variant
53
- 常に渡される値: "primary"
54
- 使用箇所: 5箇所
55
- - src/pages/Home.tsx:23
56
- - src/pages/About.tsx:45
57
- ...
240
+ ### Simplify Component APIs
241
+
242
+ ```tsx
243
+ // Before: variant is always "primary" across 20 usages
244
+ <Button variant="primary" onClick={handleClick}>Submit</Button>
245
+
246
+ // After: make "primary" the default
247
+ <Button onClick={handleClick}>Submit</Button>
58
248
  ```
59
249
 
60
- ## 検出対象
250
+ ### Remove Unused Flexibility
61
251
 
62
- - **Reactコンポーネント**: JSX要素として使用されているコンポーネントのprops
63
- - **関数**: exportされた関数の引数
64
- - **クラスメソッド**: exportされたクラスのメソッド引数
252
+ ```ts
253
+ // Before: cache is always false in all 15 call sites
254
+ const data = await fetchData(id, { cache: false });
255
+
256
+ // After: remove the option or change the default
257
+ const data = await fetchData(id);
258
+ ```
65
259
 
66
- ## 要件
260
+ ## Requirements
67
261
 
68
262
  - Node.js >= 18
69
- - プロジェクトに `tsconfig.json` が必要
263
+ - Project must have a `tsconfig.json`
70
264
 
71
- ## ライセンス
265
+ ## License
72
266
 
73
267
  MIT