-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathpre-publish-check.js
More file actions
executable file
Β·144 lines (128 loc) Β· 4.54 KB
/
pre-publish-check.js
File metadata and controls
executable file
Β·144 lines (128 loc) Β· 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env node
/**
* @fileoverview Pre-publish validation script for NPM package
* @description Performs comprehensive checks before publishing to NPM registry including:
* metadata validation, sensitive data scanning, permissions verification, and authentication status.
*
* @module pre-publish-check
* @requires fs
* @requires path
* @requires child_process
*
* Usage: node pre-publish-check.js
*
* Checks performed:
* 1. Package.json metadata (author, repository)
* 2. Files to be published (npm pack --dry-run)
* 3. Sensitive data patterns in code
* 4. Executable permissions on index.js
* 5. NPM authentication status
* 6. Package name availability
*
* Exit codes:
* - 0: All checks passed
* - 1: One or more checks failed
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
console.log('π Running pre-publish checks...\n');
let hasErrors = false;
// Check 1: Verify package.json
console.log('1. Checking package.json...');
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
if (packageJson.author === 'Your Name') {
console.log(' β Update the author field in package.json');
hasErrors = true;
} else {
console.log(' β
Author field is set');
}
if (packageJson.repository?.url?.includes('yourusername')) {
console.log(' β Update the repository URL in package.json');
hasErrors = true;
} else {
console.log(' β
Repository URL is set');
}
// Check 2: Verify files that will be published
console.log('\n2. Files that will be published:');
try {
const output = execSync('npm pack --dry-run', { encoding: 'utf8' });
const files = output.split('\n').filter(line => line.includes('npm notice'));
files.forEach(file => console.log(' ' + file));
} catch (e) {
console.log(' β Could not run npm pack --dry-run');
hasErrors = true;
}
// Check 3: Check for sensitive data
console.log('\n3. Checking for sensitive data...');
const filesToCheck = ['index.js', 'README.md'];
const sensitivePatterns = [
/api[_-]?key/i,
/secret/i,
/password/i,
/token/i,
/private[_-]?key/i
];
filesToCheck.forEach(file => {
if (fs.existsSync(file)) {
const content = fs.readFileSync(file, 'utf8');
let foundSensitive = false;
sensitivePatterns.forEach(pattern => {
const matches = content.match(pattern);
if (matches && !content.includes('// This is safe') && !content.includes('config.secret')) {
// Allow some known safe occurrences
if (file === 'index.js' && pattern.toString().includes('secret') && content.includes('crypto.randomBytes')) {
// This is the secret generation, which is safe
return;
}
console.log(` β οΈ Found potential sensitive data in ${file}: "${matches[0]}"`);
foundSensitive = true;
}
});
if (!foundSensitive) {
console.log(` β
${file} looks clean`);
}
}
});
// Check 4: Verify executable permissions
console.log('\n4. Checking executable permissions...');
if (fs.existsSync('index.js')) {
const stats = fs.statSync('index.js');
const isExecutable = (stats.mode & parseInt('111', 8)) !== 0;
if (!isExecutable) {
console.log(' β οΈ index.js is not executable. Run: chmod +x index.js');
} else {
console.log(' β
index.js is executable');
}
}
// Check 5: Check npm user
console.log('\n5. Checking npm authentication...');
try {
const npmUser = execSync('npm whoami', { encoding: 'utf8' }).trim();
console.log(` β
Logged in as: ${npmUser}`);
} catch (e) {
console.log(' β Not logged in to npm. Run: npm login');
hasErrors = true;
}
// Check 6: Check if package name is available
console.log('\n6. Checking package name availability...');
try {
execSync(`npm view ${packageJson.name}`, { encoding: 'utf8' });
console.log(` β οΈ Package "${packageJson.name}" already exists on npm`);
console.log(' Consider incrementing version or using a scoped name');
} catch (e) {
console.log(` β
Package name "${packageJson.name}" is available`);
}
// Summary
console.log('\n' + '='.repeat(50));
if (hasErrors) {
console.log('β Some checks failed. Please fix the issues above before publishing.');
process.exit(1);
} else {
console.log('β
All checks passed! You can publish with: npm publish');
console.log('\nRecommended steps:');
console.log('1. Make sure you\'re on the correct npm registry: npm config get registry');
console.log('2. Do a final dry run: npm publish --dry-run');
console.log('3. Publish: npm publish');
console.log('4. Verify: npm view synchronizer-cli');
}