Last active
June 3, 2026 06:33
-
-
Save coderbyheart/980b245791a834a1e2ef62b22cf79855 to your computer and use it in GitHub Desktop.
Publish a pre-release ("dev") version to NPM.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Publish a pre-release ("dev") version to NPM. | |
| * | |
| * Computes the next dev version as `<next-target>-dev.<n>`, where: | |
| * - <next-target> is the latest published stable version with either the | |
| * patch, the minor, or the major bumped by one and lower components reset | |
| * to 0 (e.g. `14.0.4` → `14.0.5` for a fix bump, `14.0.4` → `14.1.0` for a | |
| * minor bump, or `14.0.4` → `15.0.0` for a major bump). The bump kind is | |
| * controlled by the `--major` and `--fix` flags; the default is a minor | |
| * bump. | |
| * - <n> is one greater than the highest existing dev counter for | |
| * <next-target>, or 1 if no dev release exists yet for it. | |
| * | |
| * The version is written to package.json, `npm publish --tag dev` is run, | |
| * and package.json is restored afterwards. | |
| */ | |
| import { execSync } from 'node:child_process' | |
| import { readFileSync, writeFileSync } from 'node:fs' | |
| import path from 'node:path' | |
| const packageJsonPath = path.join(process.cwd(), 'package.json') | |
| const parseStable = ( | |
| v: string, | |
| ): { major: number; minor: number; patch: number } | null => { | |
| const m = /^(\d+)\.(\d+)\.(\d+)$/.exec(v) | |
| if (m === null) return null | |
| return { | |
| major: parseInt(m[1]!, 10), | |
| minor: parseInt(m[2]!, 10), | |
| patch: parseInt(m[3]!, 10), | |
| } | |
| } | |
| const cmp = ( | |
| a: { major: number; minor: number; patch: number }, | |
| b: { major: number; minor: number; patch: number }, | |
| ): number => a.major - b.major || a.minor - b.minor || a.patch - b.patch | |
| const packageName = '@nrfcloud/billing-service-proto' | |
| const versionsOutput = execSync(`npm view ${packageName} versions --json`, { | |
| encoding: 'utf8', | |
| }) | |
| const versions = JSON.parse(versionsOutput) as string[] | |
| const stableVersions = versions | |
| .map(parseStable) | |
| .filter( | |
| (v): v is { major: number; minor: number; patch: number } => v !== null, | |
| ) | |
| if (stableVersions.length === 0) { | |
| throw new Error(`No stable versions found for ${packageName}`) | |
| } | |
| const latestStable = stableVersions.reduce((a, b) => (cmp(a, b) >= 0 ? a : b)) | |
| const args = process.argv.slice(2) | |
| const bumpMajor = args.includes('--major') | |
| const bumpFix = args.includes('--fix') | |
| if (bumpMajor && bumpFix) { | |
| throw new Error('Cannot use --major and --fix together') | |
| } | |
| const nextTarget = bumpMajor | |
| ? `${latestStable.major + 1}.0.0` | |
| : bumpFix | |
| ? `${latestStable.major}.${latestStable.minor}.${latestStable.patch + 1}` | |
| : `${latestStable.major}.${latestStable.minor + 1}.0` | |
| const devPattern = new RegExp( | |
| `^${nextTarget.replace(/\./g, '\\.')}-dev\\.(\\d+)$`, | |
| ) | |
| const devCounters = versions | |
| .map((v) => devPattern.exec(v)) | |
| .filter((m): m is RegExpExecArray => m !== null) | |
| .map((m) => parseInt(m[1]!, 10)) | |
| const nextDev = (devCounters.length === 0 ? 0 : Math.max(...devCounters)) + 1 | |
| const nextVersion = `${nextTarget}-dev.${nextDev}` | |
| console.log( | |
| `Latest stable: ${latestStable.major}.${latestStable.minor}.${latestStable.patch}`, | |
| ) | |
| console.log(`Publishing pre-release: ${nextVersion}`) | |
| const originalPackageJson = readFileSync(packageJsonPath, 'utf8') | |
| const pkg = JSON.parse(originalPackageJson) as { version: string } | |
| pkg.version = nextVersion | |
| const trailingNewline = originalPackageJson.endsWith('\n') ? '\n' : '' | |
| writeFileSync( | |
| packageJsonPath, | |
| JSON.stringify(pkg, null, 2) + trailingNewline, | |
| 'utf8', | |
| ) | |
| try { | |
| execSync(`npm publish --tag dev`, { | |
| stdio: 'inherit', | |
| cwd: process.cwd(), | |
| }) | |
| } finally { | |
| writeFileSync(packageJsonPath, originalPackageJson, 'utf8') | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment