@n8n/scan-community-package 0.1.0 → 0.1.1
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/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n8n/scan-community-package",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Static code analyser for n8n community packages",
|
|
5
5
|
"license": "none",
|
|
6
6
|
"packageManager": "pnpm@10.2.1",
|
|
7
|
-
"bin": "scanner/
|
|
7
|
+
"bin": "scanner/cli.mjs",
|
|
8
8
|
"files": [
|
|
9
9
|
"scanner"
|
|
10
10
|
],
|
package/scanner/cli.mjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const args = process.argv.slice(2);
|
|
4
|
+
if (args.length < 1) {
|
|
5
|
+
console.error(
|
|
6
|
+
"Usage: npx @n8n/scan-community-package <package-name>[@version]",
|
|
7
|
+
);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
import { resolvePackage, analyzePackageByName } from "./scanner.mjs";
|
|
12
|
+
|
|
13
|
+
const packageSpec = args[0];
|
|
14
|
+
const { packageName, version } = resolvePackage(packageSpec);
|
|
15
|
+
try {
|
|
16
|
+
const result = await analyzePackageByName(packageName, version);
|
|
17
|
+
|
|
18
|
+
if (result.passed) {
|
|
19
|
+
console.log(
|
|
20
|
+
`✅ Package ${packageName}@${result.version} has passed all security checks`,
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
console.log(
|
|
24
|
+
`❌ Package ${packageName}@${result.version} has failed security checks`,
|
|
25
|
+
);
|
|
26
|
+
console.log(`Reason: ${result.message}`);
|
|
27
|
+
|
|
28
|
+
if (result.details) {
|
|
29
|
+
console.log("\nDetails:");
|
|
30
|
+
console.log(result.details);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("Analysis failed:", error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
@@ -18,7 +18,27 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
18
18
|
const TEMP_DIR = tmp.dirSync({ unsafeCleanup: true }).name;
|
|
19
19
|
const registry = "https://registry.npmjs.org/";
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
export const resolvePackage = (packageSpec) => {
|
|
22
|
+
let packageName, version;
|
|
23
|
+
if (packageSpec.startsWith("@")) {
|
|
24
|
+
if (packageSpec.includes("@", 1)) {
|
|
25
|
+
// Handle scoped packages with versions
|
|
26
|
+
const lastAtIndex = packageSpec.lastIndexOf("@");
|
|
27
|
+
return {
|
|
28
|
+
packageName: packageSpec.substring(0, lastAtIndex),
|
|
29
|
+
version: packageSpec.substring(lastAtIndex + 1),
|
|
30
|
+
};
|
|
31
|
+
} else {
|
|
32
|
+
// Handle scoped packages without version
|
|
33
|
+
return { packageName: packageSpec, version: null };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Handle regular packages
|
|
37
|
+
const parts = packageSpec.split("@");
|
|
38
|
+
return { packageName: parts[0], version: parts[1] || null };
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const downloadAndExtractPackage = async (packageName, version) => {
|
|
22
42
|
try {
|
|
23
43
|
// Download the tarball
|
|
24
44
|
execSync(`npm -q pack ${packageName}@${version}`, { cwd: TEMP_DIR });
|
|
@@ -42,9 +62,9 @@ async function downloadAndExtractPackage(packageName, version) {
|
|
|
42
62
|
console.error(`\nFailed to download package: ${error.message}`);
|
|
43
63
|
throw error;
|
|
44
64
|
}
|
|
45
|
-
}
|
|
65
|
+
};
|
|
46
66
|
|
|
47
|
-
async
|
|
67
|
+
const analyzePackage = async (packageDir) => {
|
|
48
68
|
const { default: eslintPlugin } = await import("./eslint-plugin.mjs");
|
|
49
69
|
const eslint = new ESLint({
|
|
50
70
|
cwd: packageDir,
|
|
@@ -102,9 +122,9 @@ async function analyzePackage(packageDir) {
|
|
|
102
122
|
error,
|
|
103
123
|
};
|
|
104
124
|
}
|
|
105
|
-
}
|
|
125
|
+
};
|
|
106
126
|
|
|
107
|
-
export async
|
|
127
|
+
export const analyzePackageByName = async (packageName, version) => {
|
|
108
128
|
try {
|
|
109
129
|
let exactVersion = version;
|
|
110
130
|
|
|
@@ -156,66 +176,4 @@ export async function analyzePackageByName(packageName, version) {
|
|
|
156
176
|
message: `Analysis failed: ${error.message}`,
|
|
157
177
|
};
|
|
158
178
|
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const resolvePackage = (packageSpec) => {
|
|
162
|
-
let packageName, version;
|
|
163
|
-
if (packageSpec.startsWith("@")) {
|
|
164
|
-
if (packageSpec.includes("@", 1)) {
|
|
165
|
-
// Handle scoped packages with versions
|
|
166
|
-
const lastAtIndex = packageSpec.lastIndexOf("@");
|
|
167
|
-
return {
|
|
168
|
-
packageName: packageSpec.substring(0, lastAtIndex),
|
|
169
|
-
version: packageSpec.substring(lastAtIndex + 1),
|
|
170
|
-
};
|
|
171
|
-
} else {
|
|
172
|
-
// Handle scoped packages without version
|
|
173
|
-
return { packageName: packageSpec, version: null };
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// Handle regular packages
|
|
177
|
-
const parts = packageSpec.split("@");
|
|
178
|
-
return { packageName: parts[0], version: parts[1] || null };
|
|
179
179
|
};
|
|
180
|
-
|
|
181
|
-
async function main() {
|
|
182
|
-
const args = process.argv.slice(2);
|
|
183
|
-
|
|
184
|
-
if (args.length < 1) {
|
|
185
|
-
console.error(
|
|
186
|
-
"Usage: node scan-community-package.mjs <package-name>[@version]",
|
|
187
|
-
);
|
|
188
|
-
process.exit(1);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const packageSpec = args[0];
|
|
192
|
-
const { packageName, version } = resolvePackage(packageSpec);
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
const result = await analyzePackageByName(packageName, version);
|
|
196
|
-
|
|
197
|
-
if (result.passed) {
|
|
198
|
-
console.log(
|
|
199
|
-
`✅ Package ${packageName}@${result.version} has passed all security checks`,
|
|
200
|
-
);
|
|
201
|
-
} else {
|
|
202
|
-
console.log(
|
|
203
|
-
`❌ Package ${packageName}@${result.version} has failed security checks`,
|
|
204
|
-
);
|
|
205
|
-
console.log(`Reason: ${result.message}`);
|
|
206
|
-
|
|
207
|
-
if (result.details) {
|
|
208
|
-
console.log("\nDetails:");
|
|
209
|
-
console.log(result.details);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
} catch (error) {
|
|
213
|
-
console.error("Analysis failed:", error);
|
|
214
|
-
process.exit(1);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// In ESM, check if the current file is being executed directly
|
|
219
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
220
|
-
void main();
|
|
221
|
-
}
|