@mnci/cli 4.3.0 → 4.3.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/dist/cli.js CHANGED
@@ -859,6 +859,7 @@ var NPM_AUDIT_STEP = `node -e "const cp=require('node:child_process');const r=cp
859
859
  var VERIFY_TARGETS = "lint,typecheck,test,build";
860
860
  var AFFECTED_OR_ALL_GUARD = `node -e "const cp=require('node:child_process');const T='${VERIFY_TARGETS}';const all=()=>process.exit(cp.spawnSync('npx nx run-many -t '+T,{stdio:'inherit',shell:true}).status ?? 1);const ref=process.env.GITHUB_BASE_REF||process.env.SYSTEM_PULLREQUEST_TARGETBRANCH||'';if(!ref){console.log('Not a pull request - verifying EVERY project.');all()}const target=ref.replace('refs/heads/','');const mergeBase=r=>{const o=cp.spawnSync('git',['merge-base',r,'HEAD'],{encoding:'utf8'});return o.status===0?o.stdout.trim():''};let base=mergeBase('origin/'+target);if(!base){console.log('No origin/'+target+' ref - fetching it to resolve a merge-base.');cp.spawnSync('git',['fetch','--no-tags','origin',target],{stdio:'inherit'});base=mergeBase('FETCH_HEAD')}if(!base){console.log('Could not resolve a merge-base with '+target+' - verifying EVERY project.');all()}console.log('Pull request against '+target+' - verifying projects affected since '+base);process.exit(cp.spawnSync('npx nx affected -t '+T+' --base='+base,{stdio:'inherit',shell:true}).status ?? 1)"`;
861
861
  var PACK_APPS_GUARD = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const hasProjectJson=fs.globSync('apps/*/project.json').length>0;const hasInlineNx=fs.globSync('apps/*/package.json').some((f)=>{try{return Boolean(JSON.parse(fs.readFileSync(f,'utf8')).nx)}catch{return false}});const hasCsproj=fs.globSync('apps/*/*.csproj').length>0;if(!hasProjectJson&&!hasInlineNx&&!hasCsproj){console.log('No apps to pack - skipping.');process.exit(0)}process.exit(require('node:child_process').spawnSync('npx nx run-many -t package',{stdio:'inherit',shell:true}).status ?? 1)"`;
862
+ var SHALLOW_CLONE_GUARD = `node -e "const r=require('node:child_process').spawnSync('git',['rev-parse','--is-shallow-repository'],{encoding:'utf8'});if(r.status!==0){console.error('Could not determine whether this checkout has full history (git rev-parse --is-shallow-repository failed) - refusing to release. '+(r.stderr||'').trim());process.exit(1)}if(r.stdout.trim()==='true'){console.error('This checkout is a shallow clone. nx release resolves the current version of each package from its git tag, and silently falls back to the permanently-stale on-disk version when a tag cannot be found - which can propose, and publish, a version DOWNGRADE. Fetch full history before releasing - set fetchDepth (Azure) or fetch-depth (GitHub) to 0.');process.exit(1)}"`;
862
863
  function releaseGuard(pythonPublishEnv, nugetPublishEnv) {
863
864
  return String.raw`node -e "const fs=require('node:fs'),cp=require('node:child_process');const npmCount=fs.globSync('packages/*/package.json').length;const csharpCount=fs.globSync('packages/*/*.csproj').length;const pythonCount=fs.globSync('python-packages/*/pyproject.toml').length;const hasNpm=npmCount>0;const hasPython=pythonCount>0;const hasCsharp=csharpCount>0;if(!hasNpm&&!hasPython&&!hasCsharp){console.log('Nothing to release - skipping.');process.exit(0)}const specifier=process.env.RELEASE_SPECIFIER||'';let releaseCmd='npx nx release --yes';if(specifier){if(!/^(major|minor|patch|\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?)$/.test(specifier)){console.error('RELEASE_SPECIFIER value \''+specifier+'\' is invalid - use major, minor, patch, or an exact version like 1.2.3.');process.exit(1)}const releaseProjectCount=npmCount+csharpCount+pythonCount;if(/^(major|minor|patch)$/.test(specifier)&&releaseProjectCount>1){console.error('RELEASE_SPECIFIER is a keyword (\''+specifier+'\') but this workspace has '+releaseProjectCount+' releasable packages - a keyword under-bumps interdependent packages, because nx computes the dependency-bump pass from a stale cached version. Set RELEASE_SPECIFIER to an exact version instead, or clear it.');process.exit(1)}releaseCmd='npx nx release '+specifier+' --yes'}const env={...process.env};${pythonPublishEnv}${nugetPublishEnv}process.exit(cp.spawnSync(releaseCmd,{stdio:'inherit',shell:true,env}).status ?? 1)"`;
864
865
  }
@@ -1112,6 +1113,17 @@ steps:
1112
1113
  displayName: Tag the run per app (type-name)
1113
1114
  condition: ${onMain}
1114
1115
 
1116
+ # nx release resolves each package's current version from its git tag, and
1117
+ # falls back to the (permanently stale, since git.commit is false) on-disk
1118
+ # version when a tag cannot be resolved \u2014 which happens whenever this
1119
+ # checkout lacks full history. This is currently guaranteed by fetchDepth 0
1120
+ # above plus the explicit fetch below, but neither is expressed as a
1121
+ # dependency anywhere else, so this makes it a hard, loud precondition
1122
+ # instead of a silently wrong version discovered after release.
1123
+ - script: ${SHALLOW_CLONE_GUARD}
1124
+ displayName: Verify this is a full checkout (nx release needs the real tag history)
1125
+ condition: ${onMain}
1126
+
1115
1127
  # Version + tag + publish, in one release, for npm (packages/*), Python
1116
1128
  # (python-packages/*) AND C# (packages/*/*.csproj) \u2014 conventional commits,
1117
1129
  # tag-only push. Portable guard: nx release errors on an empty scope, so
@@ -1326,6 +1338,18 @@ jobs:
1326
1338
  path: dist/drop
1327
1339
  if-no-files-found: ignore
1328
1340
 
1341
+ # nx release resolves each package's current version from its git tag,
1342
+ # and falls back to the (permanently stale, since git.commit is false)
1343
+ # on-disk version when a tag cannot be resolved \u2014 which happens
1344
+ # whenever this checkout lacks full history. This is currently
1345
+ # guaranteed by fetch-depth 0 above plus the explicit fetch below, but
1346
+ # neither is expressed as a dependency anywhere else, so this makes it
1347
+ # a hard, loud precondition instead of a silently wrong version
1348
+ # discovered after release.
1349
+ - run: ${SHALLOW_CLONE_GUARD}
1350
+ name: Verify this is a full checkout (nx release needs the real tag history)
1351
+ if: \${{ ${onMain} }}
1352
+
1329
1353
  # Version + tag + publish, in one release, for npm (packages/*), Python
1330
1354
  # (python-packages/*) AND C# (packages/*/*.csproj) \u2014 conventional
1331
1355
  # commits, tag-only push. Portable guard: nx release errors on an empty
@@ -1717,11 +1741,12 @@ var SOURCEMAP_PATH_TRANSFORM = [
1717
1741
  ].join("\n");
1718
1742
  var DECLARATION_SPECIFIER_PLUGIN_MARKER = "name: 'mnci-normalise-declaration-specifiers'";
1719
1743
  var DECLARATION_SPECIFIER_EXTENSION_MARKER = "bareRelativeSpecifier";
1744
+ var DECLARATION_SPECIFIER_DIRECTORY_MARKER = "resolveSpecifierSuffix";
1720
1745
  var DECLARATION_SPECIFIER_PLUGIN = [
1721
1746
  " {",
1722
1747
  " name: 'mnci-normalise-declaration-specifiers',",
1723
1748
  " writeBundle (outputOptions) {",
1724
- " const { readdirSync, readFileSync, writeFileSync } = require('node:fs')",
1749
+ " const { existsSync, readdirSync, readFileSync, writeFileSync } = require('node:fs')",
1725
1750
  " const { join } = require('node:path')",
1726
1751
  " const dir = outputOptions.dir ?? './dist'",
1727
1752
  " const stub = join(dir, 'index.d.ts')",
@@ -1749,17 +1774,31 @@ var DECLARATION_SPECIFIER_PLUGIN = [
1749
1774
  " }",
1750
1775
  " for (const entry of entries) {",
1751
1776
  " if (!entry.name.endsWith('.d.ts')) continue",
1752
- " const filePath = join(entry.parentPath ?? entry.path, entry.name)",
1777
+ " const from = entry.parentPath ?? entry.path",
1778
+ " const filePath = join(from, entry.name)",
1753
1779
  " let declaration",
1754
1780
  " try {",
1755
1781
  " declaration = readFileSync(filePath, 'utf8')",
1756
1782
  " } catch {",
1757
1783
  " continue",
1758
1784
  " }",
1785
+ " // A bare specifier may name a FILE or a DIRECTORY BARREL - resolved",
1786
+ " // against what rollup actually emitted next to this file, never",
1787
+ " // guessed. A directory needs /index.js, not .js (a file that was",
1788
+ " // never written); anything neither form matches is left alone rather",
1789
+ " // than rewritten to a specifier that cannot resolve.",
1790
+ ` const ${DECLARATION_SPECIFIER_DIRECTORY_MARKER} = (specifier) => {`,
1791
+ " if (hasExtension.test(specifier)) return null",
1792
+ " if (existsSync(join(from, specifier + '.d.ts'))) return specifier + '.js'",
1793
+ " if (existsSync(join(from, specifier, 'index.d.ts'))) return specifier + '/index.js'",
1794
+ " return null",
1795
+ " }",
1759
1796
  " const withExtensions = declaration.replace(",
1760
1797
  ` ${DECLARATION_SPECIFIER_EXTENSION_MARKER},`,
1761
- " (match, space, quote, specifier) =>",
1762
- " hasExtension.test(specifier) ? match : `from${space}${quote}${specifier}.js${quote}`,",
1798
+ " (match, space, quote, specifier) => {",
1799
+ ` const resolved = ${DECLARATION_SPECIFIER_DIRECTORY_MARKER}(specifier)`,
1800
+ " return resolved === null ? match : `from${space}${quote}${resolved}${quote}`",
1801
+ " },",
1763
1802
  " )",
1764
1803
  " if (withExtensions !== declaration) writeFileSync(filePath, withExtensions)",
1765
1804
  " }",
@@ -1818,7 +1857,7 @@ function findEnclosingBraceSpan(text, needle) {
1818
1857
  return void 0;
1819
1858
  }
1820
1859
  function withUpgradedDeclarationSpecifierPlugin(config) {
1821
- if (!config.includes(DECLARATION_SPECIFIER_PLUGIN_MARKER) || config.includes(DECLARATION_SPECIFIER_EXTENSION_MARKER)) {
1860
+ if (!config.includes(DECLARATION_SPECIFIER_PLUGIN_MARKER) || config.includes(DECLARATION_SPECIFIER_DIRECTORY_MARKER)) {
1822
1861
  return config;
1823
1862
  }
1824
1863
  const span = findEnclosingBraceSpan(config, DECLARATION_SPECIFIER_PLUGIN_MARKER);