@bobfrankston/npmglobalize 1.0.112 → 1.0.113
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/lib.js +111 -11
- package/package.json +1 -1
package/lib.js
CHANGED
|
@@ -1406,6 +1406,77 @@ function getSecurityNpmignorePatterns() {
|
|
|
1406
1406
|
function lineHasPattern(lines, pattern) {
|
|
1407
1407
|
return lines.some(line => line === pattern || line === pattern.replace('/', ''));
|
|
1408
1408
|
}
|
|
1409
|
+
/** Detect OAuth credentials.json type: "installed" (public app ID, safe to include) or "web" (has real secret, must ignore).
|
|
1410
|
+
* Returns null if no credentials.json exists or it can't be parsed. */
|
|
1411
|
+
function detectCredentialsType(cwd) {
|
|
1412
|
+
const credPath = path.join(cwd, 'credentials.json');
|
|
1413
|
+
if (!fs.existsSync(credPath))
|
|
1414
|
+
return null;
|
|
1415
|
+
try {
|
|
1416
|
+
const content = fs.readFileSync(credPath, 'utf-8');
|
|
1417
|
+
const parsed = JSON.parse(content);
|
|
1418
|
+
if (parsed.installed)
|
|
1419
|
+
return 'installed';
|
|
1420
|
+
if (parsed.web)
|
|
1421
|
+
return 'web';
|
|
1422
|
+
return null; // Unknown format (e.g., Microsoft OAuth)
|
|
1423
|
+
}
|
|
1424
|
+
catch {
|
|
1425
|
+
return null;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
/** Ensure credentials.json is handled correctly in ignore files based on OAuth type.
|
|
1429
|
+
* "installed" apps: client_secret is just a public app registration ID — must be INCLUDED.
|
|
1430
|
+
* "web" apps: client_secret is a real secret — must be IGNORED. */
|
|
1431
|
+
function conformCredentialsIgnore(cwd) {
|
|
1432
|
+
const credType = detectCredentialsType(cwd);
|
|
1433
|
+
if (!credType)
|
|
1434
|
+
return;
|
|
1435
|
+
for (const ignoreFile of ['.gitignore', '.npmignore']) {
|
|
1436
|
+
const ignorePath = path.join(cwd, ignoreFile);
|
|
1437
|
+
if (!fs.existsSync(ignorePath))
|
|
1438
|
+
continue;
|
|
1439
|
+
const content = fs.readFileSync(ignorePath, 'utf-8');
|
|
1440
|
+
const lines = content.split('\n');
|
|
1441
|
+
const trimmed = lines.map(l => l.trim());
|
|
1442
|
+
if (credType === 'installed') {
|
|
1443
|
+
// Ensure credentials.json is NOT ignored — add negation if it's being blocked
|
|
1444
|
+
const hasBlock = trimmed.some(l => l === 'credentials.json' || l === 'credentials.json/');
|
|
1445
|
+
const hasNegation = trimmed.some(l => l === '!credentials.json');
|
|
1446
|
+
if (hasBlock && !hasNegation) {
|
|
1447
|
+
// Add negation after the blocking line
|
|
1448
|
+
const newLines = [...lines];
|
|
1449
|
+
const blockIdx = trimmed.findIndex(l => l === 'credentials.json' || l === 'credentials.json/');
|
|
1450
|
+
newLines.splice(blockIdx + 1, 0, '!credentials.json');
|
|
1451
|
+
fs.writeFileSync(ignorePath, newLines.join('\n'));
|
|
1452
|
+
console.log(colors.cyan(` ✓ ${ignoreFile}: added !credentials.json (installed app — public OAuth app ID)`));
|
|
1453
|
+
}
|
|
1454
|
+
else if (!hasBlock && !hasNegation) {
|
|
1455
|
+
// No block exists, but add negation defensively in case a broader pattern catches it
|
|
1456
|
+
const newContent = content.trimEnd() + '\n!credentials.json\n';
|
|
1457
|
+
fs.writeFileSync(ignorePath, newContent);
|
|
1458
|
+
console.log(colors.cyan(` ✓ ${ignoreFile}: added !credentials.json (installed app — public OAuth app ID)`));
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
else if (credType === 'web') {
|
|
1462
|
+
// Ensure credentials.json IS ignored
|
|
1463
|
+
const hasBlock = trimmed.some(l => l === 'credentials.json');
|
|
1464
|
+
if (!hasBlock) {
|
|
1465
|
+
const newContent = content.trimEnd() + '\ncredentials.json\n';
|
|
1466
|
+
fs.writeFileSync(ignorePath, newContent);
|
|
1467
|
+
console.log(colors.cyan(` ✓ ${ignoreFile}: added credentials.json to ignore (web app — real secret)`));
|
|
1468
|
+
}
|
|
1469
|
+
// Remove any negation that would un-ignore it
|
|
1470
|
+
const negIdx = trimmed.findIndex(l => l === '!credentials.json');
|
|
1471
|
+
if (negIdx >= 0) {
|
|
1472
|
+
const newLines = [...lines];
|
|
1473
|
+
newLines.splice(negIdx, 1);
|
|
1474
|
+
fs.writeFileSync(ignorePath, newLines.join('\n'));
|
|
1475
|
+
console.log(colors.yellow(` ✓ ${ignoreFile}: removed !credentials.json (web app — must not be public)`));
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1409
1480
|
/** Check if ignore files need updates; separates security (auto-fix) from recommended (prompt) */
|
|
1410
1481
|
function checkIgnoreFiles(cwd, options) {
|
|
1411
1482
|
const changes = [];
|
|
@@ -2832,29 +2903,58 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
2832
2903
|
}
|
|
2833
2904
|
}
|
|
2834
2905
|
else if (install) {
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2906
|
+
// Quick check: does this version actually exist on npm?
|
|
2907
|
+
const vCheck = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
|
|
2908
|
+
shell: process.platform === 'win32',
|
|
2909
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
2910
|
+
encoding: 'utf-8'
|
|
2911
|
+
});
|
|
2912
|
+
const versionOnNpm = vCheck.status === 0 && vCheck.stdout?.trim() === pkgVersion;
|
|
2913
|
+
if (versionOnNpm) {
|
|
2914
|
+
console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
|
|
2915
|
+
const registryInstallResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
|
|
2916
|
+
if (registryInstallResult.success) {
|
|
2917
|
+
console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
|
|
2918
|
+
}
|
|
2919
|
+
else {
|
|
2920
|
+
console.error(colors.red(`✗ Global install failed`));
|
|
2921
|
+
console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
|
|
2922
|
+
}
|
|
2840
2923
|
}
|
|
2841
2924
|
else {
|
|
2842
|
-
console.
|
|
2843
|
-
console.
|
|
2925
|
+
console.log(colors.yellow(`${pkgName}@${pkgVersion} not found on npm — installing from local directory.`));
|
|
2926
|
+
console.log(colors.dim(' Use -m "message" to publish this version to npm.'));
|
|
2927
|
+
const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
|
|
2928
|
+
if (localResult.success) {
|
|
2929
|
+
console.log(colors.green(`✓ Installed globally from local: ${pkgName}@${pkgVersion}`));
|
|
2930
|
+
}
|
|
2931
|
+
else {
|
|
2932
|
+
console.error(colors.red(`✗ Local install failed`));
|
|
2933
|
+
console.error(colors.yellow(' Try running manually: npm install -g .'));
|
|
2934
|
+
}
|
|
2844
2935
|
}
|
|
2845
2936
|
}
|
|
2846
2937
|
if (wsl) {
|
|
2847
|
-
|
|
2848
|
-
|
|
2938
|
+
// Check if version is on npm for registry-based WSL install
|
|
2939
|
+
const useLocal = link || (() => {
|
|
2940
|
+
const vc = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
|
|
2941
|
+
shell: process.platform === 'win32',
|
|
2942
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
2943
|
+
encoding: 'utf-8'
|
|
2944
|
+
});
|
|
2945
|
+
return !(vc.status === 0 && vc.stdout?.trim() === pkgVersion);
|
|
2946
|
+
})();
|
|
2947
|
+
const wslArgs = useLocal ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
|
|
2948
|
+
if (!useLocal)
|
|
2849
2949
|
waitForNpmVersion(pkgName, pkgVersion);
|
|
2850
|
-
console.log(`Installing ${pkgName} in WSL${
|
|
2950
|
+
console.log(`Installing ${pkgName} in WSL${useLocal ? ' (local)' : ' from registry'}...`);
|
|
2851
2951
|
const wslInstallResult = runCommand('wsl', wslArgs, { cwd, silent: false, showCommand: true });
|
|
2852
2952
|
if (wslInstallResult.success) {
|
|
2853
2953
|
console.log(colors.green(`✓ Installed in WSL: ${pkgName}@${pkgVersion}`));
|
|
2854
2954
|
}
|
|
2855
2955
|
else {
|
|
2856
2956
|
console.error(colors.red(`✗ WSL install failed`));
|
|
2857
|
-
console.error(colors.yellow(' Try running manually in WSL: npm install -g ' + (
|
|
2957
|
+
console.error(colors.yellow(' Try running manually in WSL: npm install -g ' + (useLocal ? '.' : pkgName)));
|
|
2858
2958
|
}
|
|
2859
2959
|
}
|
|
2860
2960
|
}
|