-
Notifications
You must be signed in to change notification settings - Fork 308
/
version-indexes.ts
78 lines (68 loc) · 2.77 KB
/
version-indexes.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import * as fs from 'fs-extra'
import * as path from 'path'
import aws from './aws'
import {BuildConfig} from './tarballs'
import {debug as Debug} from './log'
const debug = Debug.new('version-indexes')
interface VersionsObject {
[key: string]: string;
}
const sortVersionsObjectByKeysDesc = (input: VersionsObject, keyLimit?: number): VersionsObject => {
const keys = (Reflect.ownKeys(input).sort((a, b) => {
const splitA = (a as string).split('.').map(part => Number.parseInt(part, 10))
const splitB = (b as string).split('.').map(part => Number.parseInt(part, 10))
// sort by major
if (splitA[0] < splitB[0]) return 1
if (splitA[0] > splitB[0]) return -1
// sort by minor
if (splitA[1] < splitB[1]) return 1
if (splitA[1] > splitB[1]) return -1
// sort by patch
if (splitA[2] < splitB[2]) return 1
if (splitA[2] > splitB[2]) return -1
return 0
}) as string[]).slice(0, keyLimit) // undefined keyLimit returns the entire array
const result: VersionsObject = {}
for (const key of keys) {
result[key] = input[key]
}
return result
}
// appends to an existing file (or writes a new one) with the versions in descending order, with an optional limit from the pjson file
export const appendToIndex = async (input: { version: string; originalUrl: string; filename: string; maxAge: string; s3Config: BuildConfig['s3Config'] }): Promise<void> => {
const {version, originalUrl, filename, maxAge, s3Config} = input
// these checks are both nice for users AND helpful for TS
if (!s3Config.bucket) throw new Error('[package.json].oclif.s3.bucket is required for indexes')
if (!s3Config.host) throw new Error('[package.json].oclif.s3.host is required for indexes')
// json-friendly filenames like sfdx-linux-x64-tar-gz
const jsonFileName = `${filename.replace(/\./g, '-')}.json`
// folder is optional, but honored if present
const key = path.join(s3Config.folder ?? '', 'versions', jsonFileName)
// retrieve existing index file
let existing = {}
try {
existing = JSON.parse((await aws.s3.getObject({
Bucket: s3Config.bucket,
Key: key,
})).Body?.toString() as string)
debug('appending to existing index file')
} catch (error: any) {
debug(`error on ${key}`, error)
}
// appends new version from this promotion if not already present (idempotent)
await fs.writeJSON(jsonFileName, sortVersionsObjectByKeysDesc(
{
...existing,
[version]: originalUrl.replace(s3Config.bucket, s3Config.host),
}, s3Config.indexVersionLimit,
), {spaces: 2})
// put the file back in the same place
await aws.s3.uploadFile(jsonFileName, {
Bucket: s3Config.bucket,
Key: key,
CacheControl: maxAge,
ACL: s3Config.acl || 'public-read',
})
// cleans up local fs
await fs.remove(jsonFileName)
}