@@ -11,8 +11,10 @@ import {
11
11
UncachedNpmInfoClient ,
12
12
withNpmCache ,
13
13
CachedNpmInfoClient ,
14
+ max ,
14
15
} from "@definitelytyped/utils" ;
15
16
import { fetchTypesPackageVersionInfo } from "@definitelytyped/retag" ;
17
+ import * as semver from "semver" ;
16
18
import { cacheDirPath } from "./lib/settings" ;
17
19
18
20
if ( ! module . parent ) {
@@ -49,7 +51,7 @@ async function computeAndSaveChangedPackages(
49
51
changedTypings : cp . changedTypings . map (
50
52
( { pkg : { id } , version, latestVersion } ) : ChangedTypingJson => ( { id, version, latestVersion } )
51
53
) ,
52
- changedNotNeededPackages : cp . changedNotNeededPackages . map ( ( p ) => p . name ) ,
54
+ changedNotNeededPackages : cp . changedNotNeededPackages . map ( ( { pkg : { name } , version } ) => ( { name, version } ) ) ,
53
55
} ;
54
56
await writeDataFile ( versionsFilename , json ) ;
55
57
return cp ;
@@ -80,32 +82,54 @@ async function computeChangedPackages(
80
82
} ) ;
81
83
log . info ( "# Computing deprecated packages..." ) ;
82
84
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 ) {
84
87
assertDefined (
85
88
await client . fetchAndCacheNpmInfo ( pkg . libraryName ) ,
86
89
`To deprecate '@types/${ pkg . name } ', '${ pkg . libraryName } ' must exist on npm.`
87
90
) ;
88
91
log . info ( `To be deprecated: ${ pkg . name } ` ) ;
89
- return pkg ;
92
+ return { pkg, version } ;
90
93
}
91
94
return undefined ;
92
95
} ) ;
93
96
return { changedTypings, changedNotNeededPackages } ;
94
97
}
95
98
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 (
97
104
pkg : NotNeededPackage ,
98
105
client : CachedNpmInfoClient ,
99
106
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 ) ) ;
104
111
if ( ! latestVersionInfo || ! latestVersionInfo . deprecated ) {
105
112
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 ) ) ;
107
114
latestVersion = assertDefined ( info . distTags . get ( "latest" ) ) ;
108
115
latestVersionInfo = assertDefined ( info . versions . get ( latestVersion ) ) ;
109
116
}
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 ] ;
111
135
}
0 commit comments