import { normalize , relative } from "path" ; import assert = require ( "assert" ) ; import { readFileSync , writeFileSync } from "fs" ; /**
 * A minimal description for a parsed package.json object.
 */ interface PackageJson { name : string ; version : string ; keywords : string [ ] ; } function main ( ) { const args = process . argv . slice ( 2 ) ; if ( args . length < 3 ) { const thisProgramName = relative ( process . cwd ( ) , __filename ) ; console . log ( "Usage:" ) ; console . log ( `\tnode ${ thisProgramName } <dev|insiders> <package.json location> <file containing version>` ) ; return ; } const tag = args [ 0 ] ; if ( tag !== "dev" && tag !== "insiders" && tag !== "experimental" ) { throw new Error ( `Unexpected tag name '${ tag }'.` ) ; } const packageJsonFilePath = normalize ( args [ 1 ] ) ; const packageJsonValue = JSON . parse ( readFileSync ( packageJsonFilePath ) . toString ( ) ) ; const { majorMinor , patch } = parsePackageJsonVersion ( packageJsonValue . version ) ; const prereleasePatch = getPrereleasePatch ( tag , patch ) ; const tsFilePath = normalize ( args [ 2 ] ) ; const tsFileContents = readFileSync ( tsFilePath ) . toString ( ) ; const modifiedTsFileContents = updateTsFile ( tsFilePath , tsFileContents , majorMinor , patch , prereleasePatch ) ; if ( tsFileContents === modifiedTsFileContents ) { let err = `\n  '${ tsFilePath }' was not updated while configuring for a prerelease publish for '${ tag }'.\n    ` ; err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${ tsFilePath }"'.` ; throw new Error ( err + "\n" ) ; } packageJsonValue . version = `${ majorMinor }.${ prereleasePatch }` ; writeFileSync ( packageJsonFilePath , JSON . stringify ( packageJsonValue , undefined , 4 ) ) ; writeFileSync ( tsFilePath , modifiedTsFileContents ) ; } function updateTsFile ( tsFilePath , tsFileContents , majorMinor , patch , nightlyPatch ) { const majorMinorRgx = /export const versionMajorMinor = "(\d+\.\d+)"/ ; const majorMinorMatch = majorMinorRgx . exec ( tsFileContents ) ; assert ( majorMinorMatch !== null , `The file '${ tsFilePath }' seems to no longer have a string matching '${ majorMinorRgx }'.` ) ; const parsedMajorMinor = majorMinorMatch ! [ 1 ] ; assert ( parsedMajorMinor === majorMinor , `versionMajorMinor does not match. ${ tsFilePath }: '${ parsedMajorMinor }'; package.json: '${ majorMinor }'` ) ; const versionRgx = /export const version(?:: string)? = `\$\{versionMajorMinor\}\.(\d)(-\w+)?`;/ ; const patchMatch = versionRgx . exec ( tsFileContents ) ; assert ( patchMatch !== null , `The file '${ tsFilePath }' seems to no longer have a string matching '${ versionRgx . toString ( ) }'.` ) ; const parsedPatch = patchMatch ! [ 1 ] ; if ( parsedPatch !== patch ) { throw new Error ( `patch does not match. ${ tsFilePath }: '${ parsedPatch }; package.json: '${ patch }'` ) ; } return tsFileContents . replace ( versionRgx , `export const version: string = \`\${versionMajorMinor}.${ nightlyPatch }\`;` ) ; } function parsePackageJsonVersion ( versionString ) { const versionRgx = /(\d+\.\d+)\.(\d+)($|\-)/ ; const match = versionString . match ( versionRgx ) ; assert ( match !== null , "package.json 'version' should match " + versionRgx . toString ( ) ) ; return { majorMinor : match ! [ 1 ] , patch : match ! [ 2 ] } ; } /** e.g. 0-dev.20170707 */ function getPrereleasePatch ( tag , plainPatch ) { const now = new Date ( ) ; const timeStr = now . toISOString ( ) . replace ( /:|T|\.|-/g , "" ) . slice ( 0 , 8 ) ; return `${ plainPatch }-${ tag }.${ timeStr }` ; } main ( ) ;