polydup-node 0.1.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 +181 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# @polydup/core
|
|
2
|
+
|
|
3
|
+
Node.js bindings for PolyDup - a cross-language duplicate code detector powered by Rust.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Fast**: Built in Rust with Tree-sitter for efficient parsing
|
|
8
|
+
- 🔄 **Multi-language**: Supports Rust, Python, JavaScript/TypeScript
|
|
9
|
+
- ⚡ **Non-blocking**: Async API runs on background threads
|
|
10
|
+
- 🎯 **Type-2 clones**: Detects structurally similar code with different variable names
|
|
11
|
+
- 📊 **Detailed reports**: Statistics and similarity scores
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @polydup/core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const { findDuplicates } = require('@polydup/core');
|
|
23
|
+
|
|
24
|
+
findDuplicates(['./src', './lib'], 50, 0.85)
|
|
25
|
+
.then(report => {
|
|
26
|
+
console.log(`Found ${report.duplicates.length} duplicates`);
|
|
27
|
+
console.log(`Scanned ${report.filesScanned} files in ${report.stats.durationMs}ms`);
|
|
28
|
+
|
|
29
|
+
report.duplicates.forEach(dup => {
|
|
30
|
+
console.log(`${dup.file1} ↔️ ${dup.file2} (${(dup.similarity * 100).toFixed(1)}%)`);
|
|
31
|
+
});
|
|
32
|
+
})
|
|
33
|
+
.catch(err => console.error('Scan failed:', err));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
### `findDuplicates(paths, minBlockSize?, threshold?)`
|
|
39
|
+
|
|
40
|
+
Asynchronously scans for duplicate code (recommended).
|
|
41
|
+
|
|
42
|
+
**Parameters:**
|
|
43
|
+
- `paths: string[]` - File or directory paths to scan
|
|
44
|
+
- `minBlockSize?: number` - Minimum code block size in tokens (default: 50)
|
|
45
|
+
- `threshold?: number` - Similarity threshold 0.0-1.0 (default: 0.85)
|
|
46
|
+
|
|
47
|
+
**Returns:** `Promise<Report>`
|
|
48
|
+
|
|
49
|
+
**Example:**
|
|
50
|
+
```javascript
|
|
51
|
+
const report = await findDuplicates(['./src'], 30, 0.9);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### `findDuplicatesSync(paths, minBlockSize?, threshold?)`
|
|
55
|
+
|
|
56
|
+
Synchronously scans for duplicate code (blocks event loop - use sparingly).
|
|
57
|
+
|
|
58
|
+
**Parameters:** Same as `findDuplicates`
|
|
59
|
+
|
|
60
|
+
**Returns:** `Report`
|
|
61
|
+
|
|
62
|
+
**Example:**
|
|
63
|
+
```javascript
|
|
64
|
+
const report = findDuplicatesSync(['./src'], 50, 0.85);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### `version()`
|
|
68
|
+
|
|
69
|
+
Returns the library version string.
|
|
70
|
+
|
|
71
|
+
**Returns:** `string`
|
|
72
|
+
|
|
73
|
+
## TypeScript
|
|
74
|
+
|
|
75
|
+
Type definitions are automatically generated:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { findDuplicates, Report, DuplicateMatch } from '@polydup/core';
|
|
79
|
+
|
|
80
|
+
const report: Report = await findDuplicates(['./src']);
|
|
81
|
+
|
|
82
|
+
report.duplicates.forEach((dup: DuplicateMatch) => {
|
|
83
|
+
console.log(`${dup.file1} ↔️ ${dup.file2}`);
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Report Structure
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
interface Report {
|
|
91
|
+
filesScanned: number;
|
|
92
|
+
functionsAnalyzed: number;
|
|
93
|
+
duplicates: DuplicateMatch[];
|
|
94
|
+
stats: ScanStats;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface DuplicateMatch {
|
|
98
|
+
file1: string;
|
|
99
|
+
file2: string;
|
|
100
|
+
startLine1: number;
|
|
101
|
+
startLine2: number;
|
|
102
|
+
length: number; // Block size in tokens
|
|
103
|
+
similarity: number; // 0.0 - 1.0
|
|
104
|
+
hash: string; // Hash signature
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface ScanStats {
|
|
108
|
+
totalLines: number;
|
|
109
|
+
totalTokens: number;
|
|
110
|
+
uniqueHashes: number;
|
|
111
|
+
durationMs: number;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Performance Tips
|
|
116
|
+
|
|
117
|
+
1. **Use async API**: Always prefer `findDuplicates()` over `findDuplicatesSync()` to avoid blocking
|
|
118
|
+
2. **Adjust window size**: Smaller `minBlockSize` finds more matches but may include false positives
|
|
119
|
+
3. **Filter results**: Apply post-processing to filter duplicates by file patterns or directories
|
|
120
|
+
4. **Parallel scans**: Use Promise.all for multiple independent scans
|
|
121
|
+
|
|
122
|
+
## Example: Custom Analysis
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const { findDuplicates } = require('@polydup/core');
|
|
126
|
+
|
|
127
|
+
async function analyzeCrossProject() {
|
|
128
|
+
const [frontend, backend] = await Promise.all([
|
|
129
|
+
findDuplicates(['./frontend/src'], 40, 0.9),
|
|
130
|
+
findDuplicates(['./backend/src'], 40, 0.9),
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
console.log('Frontend duplicates:', frontend.duplicates.length);
|
|
134
|
+
console.log('Backend duplicates:', backend.duplicates.length);
|
|
135
|
+
|
|
136
|
+
// Find cross-project duplicates
|
|
137
|
+
const allPaths = ['./frontend', './backend'];
|
|
138
|
+
const crossProject = await findDuplicates(allPaths, 50, 0.95);
|
|
139
|
+
|
|
140
|
+
const crossDuplicates = crossProject.duplicates.filter(d =>
|
|
141
|
+
d.file1.includes('frontend') && d.file2.includes('backend')
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
console.log('Cross-project duplicates:', crossDuplicates.length);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
analyzeCrossProject();
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Building from Source
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
cd crates/dupe-node
|
|
154
|
+
npm install
|
|
155
|
+
npm run build
|
|
156
|
+
npm test
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Generating Type Definitions
|
|
160
|
+
|
|
161
|
+
Type definitions are auto-generated during build:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npm run typegen
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
This creates `index.d.ts` with TypeScript definitions for all exported functions.
|
|
168
|
+
|
|
169
|
+
## Supported Platforms
|
|
170
|
+
|
|
171
|
+
- macOS (Intel & Apple Silicon)
|
|
172
|
+
- Linux (x64 & ARM64)
|
|
173
|
+
- Windows (x64)
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT
|
|
178
|
+
|
|
179
|
+
## Repository
|
|
180
|
+
|
|
181
|
+
https://github.com/wiesnerbernard/polydup
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "polydup-node",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Cross-language duplicate code detector - Node.js bindings",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"duplicate",
|
|
9
|
+
"code",
|
|
10
|
+
"detection",
|
|
11
|
+
"tree-sitter",
|
|
12
|
+
"ast",
|
|
13
|
+
"clone",
|
|
14
|
+
"rust",
|
|
15
|
+
"napi"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/wiesnerbernard/polydup.git"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"napi": {
|
|
23
|
+
"name": "dupe-node",
|
|
24
|
+
"triples": {
|
|
25
|
+
"additional": [
|
|
26
|
+
"aarch64-apple-darwin",
|
|
27
|
+
"x86_64-apple-darwin",
|
|
28
|
+
"x86_64-unknown-linux-gnu",
|
|
29
|
+
"x86_64-pc-windows-msvc",
|
|
30
|
+
"aarch64-unknown-linux-gnu"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"artifacts": "napi artifacts",
|
|
36
|
+
"build": "napi build --platform --release",
|
|
37
|
+
"build:debug": "napi build --platform",
|
|
38
|
+
"prepublishOnly": "napi prepublish -t npm",
|
|
39
|
+
"test": "node test.js",
|
|
40
|
+
"version": "napi version",
|
|
41
|
+
"typegen": "napi build --platform --release --dts index.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@napi-rs/cli": "^2.18.0",
|
|
45
|
+
"prettier": "^3.1.0"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">= 12"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"index.js",
|
|
52
|
+
"index.d.ts",
|
|
53
|
+
"README.md"
|
|
54
|
+
],
|
|
55
|
+
"optionalDependencies": {
|
|
56
|
+
"polydup-node-win32-x64-msvc": "0.1.0",
|
|
57
|
+
"polydup-node-darwin-x64": "0.1.0",
|
|
58
|
+
"polydup-node-linux-x64-gnu": "0.1.0",
|
|
59
|
+
"polydup-node-darwin-arm64": "0.1.0",
|
|
60
|
+
"polydup-node-linux-arm64-gnu": "0.1.0"
|
|
61
|
+
}
|
|
62
|
+
}
|