@bobfrankston/npmglobalize 1.0.100 → 1.0.102

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.
Files changed (2) hide show
  1. package/lib.js +95 -7
  2. package/package.json +1 -1
package/lib.js CHANGED
@@ -1301,6 +1301,37 @@ const RECOMMENDED_GITIGNORE = [
1301
1301
  '*.ldf',
1302
1302
  '*.ndf'
1303
1303
  ];
1304
+ /** Extensions only recommended for .gitignore when matching files exist in the project */
1305
+ const PRESENCE_ONLY_EXTENSIONS = new Set(['.mdf', '.ldf', '.ndf']);
1306
+ /** Check if any files with the given extension exist in dir (skips node_modules, .git, prev) */
1307
+ function hasFilesWithExtension(dir, ext) {
1308
+ const skip = new Set(['node_modules', '.git', 'prev']);
1309
+ function check(d) {
1310
+ try {
1311
+ for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
1312
+ if (skip.has(entry.name))
1313
+ continue;
1314
+ if (entry.isFile() && entry.name.endsWith(ext))
1315
+ return true;
1316
+ if (entry.isDirectory() && check(path.join(d, entry.name)))
1317
+ return true;
1318
+ }
1319
+ }
1320
+ catch { }
1321
+ return false;
1322
+ }
1323
+ return check(dir);
1324
+ }
1325
+ /** Filter RECOMMENDED_GITIGNORE to skip presence-only patterns when no matching files exist */
1326
+ function getApplicableGitignorePatterns(cwd) {
1327
+ return RECOMMENDED_GITIGNORE.filter(pattern => {
1328
+ const extMatch = pattern.match(/^\*(\.\w+)$/);
1329
+ if (extMatch && PRESENCE_ONLY_EXTENSIONS.has(extMatch[1])) {
1330
+ return hasFilesWithExtension(cwd, extMatch[1]);
1331
+ }
1332
+ return true;
1333
+ });
1334
+ }
1304
1335
  /** Recommended .npmignore patterns */
1305
1336
  const RECOMMENDED_NPMIGNORE = [
1306
1337
  '.git/',
@@ -1341,7 +1372,7 @@ function checkIgnoreFiles(cwd, options) {
1341
1372
  if (fs.existsSync(gitignorePath)) {
1342
1373
  const content = fs.readFileSync(gitignorePath, 'utf-8');
1343
1374
  const lines = content.split('\n').map(l => l.trim());
1344
- for (const pattern of RECOMMENDED_GITIGNORE) {
1375
+ for (const pattern of getApplicableGitignorePatterns(cwd)) {
1345
1376
  if (!lines.some(line => line === pattern || line === pattern.replace('/', ''))) {
1346
1377
  changes.push(` .gitignore missing: ${pattern}`);
1347
1378
  }
@@ -1395,7 +1426,7 @@ function conformIgnoreFiles(cwd) {
1395
1426
  const content = fs.readFileSync(gitignorePath, 'utf-8');
1396
1427
  const lines = new Set(content.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#')));
1397
1428
  let updated = false;
1398
- for (const pattern of RECOMMENDED_GITIGNORE) {
1429
+ for (const pattern of getApplicableGitignorePatterns(cwd)) {
1399
1430
  const normalized = pattern.replace('/', '');
1400
1431
  if (!lines.has(pattern) && !lines.has(normalized)) {
1401
1432
  lines.add(pattern);
@@ -1468,9 +1499,9 @@ function ensureGitignore(cwd) {
1468
1499
  // Update .gitignore if needed
1469
1500
  if (needsUpdate) {
1470
1501
  if (!content || content.trim() === '') {
1471
- // Create new .gitignore from RECOMMENDED_GITIGNORE plus extras
1502
+ // Create new .gitignore from applicable patterns plus extras
1472
1503
  const extras = ['*certs*/', 'configuration.json', 'cruft/', 'prev/', 'tests/'];
1473
- content = [...RECOMMENDED_GITIGNORE, ...extras].join('\n') + '\n';
1504
+ content = [...getApplicableGitignorePatterns(cwd), ...extras].join('\n') + '\n';
1474
1505
  }
1475
1506
  else {
1476
1507
  // Add node_modules to existing .gitignore
@@ -1567,15 +1598,72 @@ export async function initGit(cwd, visibility, dryRun) {
1567
1598
  runCommandOrThrow('git', ['config', 'core.autocrlf', 'false'], { cwd });
1568
1599
  runCommandOrThrow('git', ['config', 'core.eol', 'lf'], { cwd });
1569
1600
  console.log(' ✓ Configured git for LF line endings');
1570
- runCommandOrThrow('git', ['add', '-A'], { cwd });
1601
+ let initAddResult = runCommand('git', ['add', '-A'], { cwd, silent: true });
1602
+ if (!initAddResult.success) {
1603
+ const errText = initAddResult.stderr + initAddResult.output;
1604
+ const deniedFiles = parseDeniedFiles(errText);
1605
+ if (deniedFiles.length > 0) {
1606
+ console.error(colors.red(` git add failed — ${deniedFiles.length} file(s) locked/permission denied:`));
1607
+ for (const f of deniedFiles) {
1608
+ console.error(colors.red(` ${f}`));
1609
+ }
1610
+ const ok = await confirm('Add these files to .gitignore and retry?', true);
1611
+ if (ok) {
1612
+ const gitignorePath = path.join(cwd, '.gitignore');
1613
+ let gitignoreContent = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf-8') : '';
1614
+ if (gitignoreContent && !gitignoreContent.endsWith('\n'))
1615
+ gitignoreContent += '\n';
1616
+ for (const f of deniedFiles) {
1617
+ gitignoreContent += f + '\n';
1618
+ }
1619
+ fs.writeFileSync(gitignorePath, gitignoreContent);
1620
+ console.log(colors.green(' ✓ Updated .gitignore'));
1621
+ initAddResult = runCommand('git', ['add', '-A'], { cwd, silent: true });
1622
+ }
1623
+ if (!initAddResult.success) {
1624
+ console.error(colors.red(' git add still failing. Fix manually and retry.'));
1625
+ return false;
1626
+ }
1627
+ }
1628
+ else {
1629
+ console.error(colors.red(` git add failed: ${errText}`));
1630
+ return false;
1631
+ }
1632
+ }
1571
1633
  // Only commit if there are staged changes (repo may already have commits)
1572
1634
  const staged = spawnSafe('git', ['diff', '--cached', '--quiet'], { cwd });
1573
1635
  if (staged.status !== 0) {
1574
1636
  runCommandOrThrow('git', ['commit', '-m', 'Initial commit'], { cwd });
1575
1637
  }
1576
- // Create GitHub repo
1638
+ // Create GitHub repo (or link to existing one)
1577
1639
  const visFlag = visibility === 'private' ? '--private' : '--public';
1578
- runCommandOrThrow('gh', ['repo', 'create', repoName, visFlag, '--source=.', '--push'], { cwd });
1640
+ const createResult = runCommand('gh', ['repo', 'create', repoName, visFlag, '--source=.', '--push'], { cwd, silent: true });
1641
+ if (!createResult.success) {
1642
+ const errText = createResult.stderr + createResult.output;
1643
+ if (errText.includes('Name already exists')) {
1644
+ // Repo exists on GitHub — look up the owner and add as remote
1645
+ console.log(colors.yellow(` GitHub repo '${repoName}' already exists — linking as remote...`));
1646
+ const whoResult = runCommand('gh', ['api', 'user', '--jq', '.login'], { cwd, silent: true });
1647
+ const ghUser = (whoResult.output || '').trim();
1648
+ if (!ghUser) {
1649
+ console.error(colors.red(' Could not determine GitHub username. Run: gh auth status'));
1650
+ return false;
1651
+ }
1652
+ const remoteUrl = `https://github.com/${ghUser}/${repoName}.git`;
1653
+ const addRemote = runCommand('git', ['remote', 'add', 'origin', remoteUrl], { cwd, silent: true });
1654
+ if (!addRemote.success) {
1655
+ // Remote might already exist with wrong URL
1656
+ runCommand('git', ['remote', 'set-url', 'origin', remoteUrl], { cwd, silent: true });
1657
+ }
1658
+ // Push existing commits
1659
+ runCommand('git', ['push', '-u', 'origin', 'master'], { cwd, silent: true });
1660
+ console.log(colors.green(` ✓ Linked to existing repo: ${remoteUrl}`));
1661
+ }
1662
+ else {
1663
+ console.error(colors.red(`Failed to create GitHub repo: ${errText}`));
1664
+ return false;
1665
+ }
1666
+ }
1579
1667
  // Update package.json with repository field
1580
1668
  try {
1581
1669
  const remoteUrl = execSync('git remote get-url origin', { cwd, encoding: 'utf-8' }).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.100",
3
+ "version": "1.0.102",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",