-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpackages.ts
More file actions
132 lines (119 loc) · 4.58 KB
/
packages.ts
File metadata and controls
132 lines (119 loc) · 4.58 KB
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
* @fileoverview Package metadata, defaults, extensions, and lifecycle helpers.
* Exposes lazily-memoized accessors for package defaults (Node range, Socket
* categories), the pacote cache path, lifecycle script names, and known
* package extensions used during manifest processing.
*/
import pacote from '../external/pacote'
import { packageExtensions as packageExtensionsImport } from '../package-extensions'
import { normalizePath } from '../paths/normalize'
import { lifecycleScriptNames as lifecycleScriptNamesImport } from './lifecycle-script-names'
import { packageDefaultNodeRange as packageDefaultNodeRangeImport } from './package-default-node-range'
import { packageDefaultSocketCategories as packageDefaultSocketCategoriesImport } from './package-default-socket-categories'
import { ArrayFrom, ObjectEntries, ReflectGetPrototypeOf } from '../primordials'
let _lifecycleScriptNames: string[]
let _packageDefaultNodeRange: string | undefined
let _packageDefaultSocketCategories: readonly string[]
let _packageExtensions: Iterable<[string, unknown]>
let _pacoteCachePath: string
let _packumentCache: Map<string, unknown>
// Package constants.
export const PACKAGE = 'package'
export const AT_LATEST = '@latest'
export const LATEST = 'latest'
export const PACKAGE_DEFAULT_VERSION = '1.0.0'
/**
* Clear the packument cache. Useful for long-running processes that want to
* force a re-fetch of registry metadata.
*/
export function clearPackumentCache(): void {
// First-call branch fires only when cache is uninitialized; tests
// exercise the truthy path.
/* c8 ignore next 3 */
if (_packumentCache !== undefined) {
_packumentCache.clear()
}
}
/*@__NO_SIDE_EFFECTS__*/
export function getLifecycleScriptNames(): string[] {
if (_lifecycleScriptNames === undefined) {
// lifecycleScriptNames is imported at the top
_lifecycleScriptNames = ArrayFrom(lifecycleScriptNamesImport)
}
return _lifecycleScriptNames
}
/*@__NO_SIDE_EFFECTS__*/
export function getPackageDefaultNodeRange(): string | undefined {
if (_packageDefaultNodeRange === undefined) {
// packageDefaultNodeRange is imported at the top
_packageDefaultNodeRange = packageDefaultNodeRangeImport
}
return _packageDefaultNodeRange
}
/*@__NO_SIDE_EFFECTS__*/
export function getPackageDefaultSocketCategories() {
if (_packageDefaultSocketCategories === undefined) {
// packageDefaultSocketCategories is imported at the top
_packageDefaultSocketCategories = packageDefaultSocketCategoriesImport
}
return _packageDefaultSocketCategories
}
/*@__NO_SIDE_EFFECTS__*/
export function getPackageExtensions(): Iterable<[string, unknown]> {
if (_packageExtensions === undefined) {
// packageExtensions is imported at the top
_packageExtensions = ObjectEntries(packageExtensionsImport)
}
return _packageExtensions
}
const PACKUMENT_CACHE_MAX = 500
class BoundedPackumentCache extends Map<string, unknown> {
override set(key: string, value: unknown): this {
// LRU touch/eviction: has-existing tested via Wave 4; fill-to-max
// requires 500 distinct keys (impractical in test). The
// oldest!==undefined defensive guard is unreachable when size>=max.
/* c8 ignore start */
if (this.has(key)) {
this.delete(key)
} else if (this.size >= PACKUMENT_CACHE_MAX) {
const oldest = this.keys().next().value
if (oldest !== undefined) {
this.delete(oldest)
}
}
/* c8 ignore stop */
return super.set(key, value)
}
}
/*@__NO_SIDE_EFFECTS__*/
export function getPackumentCache(): Map<string, unknown> {
if (_packumentCache === undefined) {
_packumentCache = new BoundedPackumentCache()
}
return _packumentCache
}
/*@__NO_SIDE_EFFECTS__*/
export function getPacoteCachePath(): string {
if (_pacoteCachePath === undefined) {
try {
// module is imported at the top
const proto = ReflectGetPrototypeOf(
(pacote as { RegistryFetcher: { prototype: object } }).RegistryFetcher
.prototype,
) as { constructor?: new (...args: unknown[]) => { cache: string } }
const PacoteFetcherBase = proto?.constructor
// PacoteFetcherBase fallback fires only when pacote internals
// change; cachePath fallback fires only when constructor returns
// empty cache. Both defensive against pacote API drift.
/* c8 ignore start */
const cachePath = PacoteFetcherBase
? new PacoteFetcherBase(/*dummy package spec*/ 'x', {}).cache
: ''
_pacoteCachePath = cachePath ? normalizePath(cachePath) : ''
/* c8 ignore stop */
} catch {
_pacoteCachePath = ''
}
}
return _pacoteCachePath
}