@@ -11,8 +11,10 @@ import {
1111 UncachedNpmInfoClient ,
1212 withNpmCache ,
1313 CachedNpmInfoClient ,
14+ max ,
1415} from "@definitelytyped/utils" ;
1516import { fetchTypesPackageVersionInfo } from "@definitelytyped/retag" ;
17+ import * as semver from "semver" ;
1618import { cacheDirPath } from "./lib/settings" ;
1719
1820if ( ! module . parent ) {
@@ -49,7 +51,7 @@ async function computeAndSaveChangedPackages(
4951 changedTypings : cp . changedTypings . map (
5052 ( { pkg : { id } , version, latestVersion } ) : ChangedTypingJson => ( { id, version, latestVersion } )
5153 ) ,
52- changedNotNeededPackages : cp . changedNotNeededPackages . map ( ( p ) => p . name ) ,
54+ changedNotNeededPackages : cp . changedNotNeededPackages . map ( ( { pkg : { name } , version } ) => ( { name, version } ) ) ,
5355 } ;
5456 await writeDataFile ( versionsFilename , json ) ;
5557 return cp ;
@@ -80,32 +82,54 @@ async function computeChangedPackages(
8082 } ) ;
8183 log . info ( "# Computing deprecated packages..." ) ;
8284 const changedNotNeededPackages = await mapDefinedAsync ( allPackages . allNotNeeded ( ) , async ( pkg ) => {
83- if ( ! ( await isAlreadyDeprecated ( pkg , client , log ) ) ) {
85+ const version = await fetchIncipientStubVersion ( pkg , client , log ) ;
86+ if ( version ) {
8487 assertDefined (
8588 await client . fetchAndCacheNpmInfo ( pkg . libraryName ) ,
8689 `To deprecate '@types/${ pkg . name } ', '${ pkg . libraryName } ' must exist on npm.`
8790 ) ;
8891 log . info ( `To be deprecated: ${ pkg . name } ` ) ;
89- return pkg ;
92+ return { pkg, version } ;
9093 }
9194 return undefined ;
9295 } ) ;
9396 return { changedTypings, changedNotNeededPackages } ;
9497}
9598
96- async function isAlreadyDeprecated (
99+ /**
100+ * Return the version of the stub @types/package we are about to publish
101+ * and deprecate, if that @typees/package is not already deprecated.
102+ */
103+ async function fetchIncipientStubVersion (
97104 pkg : NotNeededPackage ,
98105 client : CachedNpmInfoClient ,
99106 log : LoggerWithErrors
100- ) : Promise < boolean > {
101- const cachedInfo = client . getNpmInfoFromCache ( pkg . fullEscapedNpmName ) ;
102- let latestVersion = cachedInfo && assertDefined ( cachedInfo . distTags . get ( "latest" ) ) ;
103- let latestVersionInfo = cachedInfo && latestVersion && assertDefined ( cachedInfo . versions . get ( latestVersion ) ) ;
107+ ) : Promise < string | false > {
108+ let info = client . getNpmInfoFromCache ( pkg . fullEscapedNpmName ) ;
109+ let latestVersion = info && assertDefined ( info . distTags . get ( "latest" ) ) ;
110+ let latestVersionInfo = latestVersion && assertDefined ( info ! . versions . get ( latestVersion ) ) ;
104111 if ( ! latestVersionInfo || ! latestVersionInfo . deprecated ) {
105112 log . info ( `Version info not cached for deprecated package ${ pkg . desc } ` ) ;
106- const info = assertDefined ( await client . fetchAndCacheNpmInfo ( pkg . fullEscapedNpmName ) ) ;
113+ info = assertDefined ( await client . fetchAndCacheNpmInfo ( pkg . fullEscapedNpmName ) ) ;
107114 latestVersion = assertDefined ( info . distTags . get ( "latest" ) ) ;
108115 latestVersionInfo = assertDefined ( info . versions . get ( latestVersion ) ) ;
109116 }
110- return ! ! latestVersionInfo . deprecated ;
117+ // When we fail to publish a deprecated package, it leaves behind an entry in the time property.
118+ // So the keys of 'time' give the actual 'latest'.
119+ // If that's not equal to the expected latest, try again by bumping the patch version of the last attempt by 1.
120+ return (
121+ ! latestVersionInfo . deprecated &&
122+ String ( max ( [ pkg . version , semver . inc ( findActualLatest ( info ! . time ) , "patch" ) ! ] , semver . compare ) )
123+ ) ;
124+ }
125+
126+ function findActualLatest ( times : Map < string , string > ) {
127+ const actual = max (
128+ [ ...times ] . filter ( ( [ version ] ) => version !== "modified" && version !== "created" ) ,
129+ ( [ , a ] , [ , b ] ) => ( new Date ( a ) as never ) - ( new Date ( b ) as never )
130+ ) ;
131+ if ( ! actual ) {
132+ throw new Error ( "failed to find actual latest" ) ;
133+ }
134+ return actual [ 0 ] ;
111135}
0 commit comments