-
Notifications
You must be signed in to change notification settings - Fork 27.8k
/
Copy pathload-manifest.ts
104 lines (90 loc) · 2.63 KB
/
load-manifest.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
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
import type { DeepReadonly } from '../shared/lib/deep-readonly'
import { readFileSync } from 'fs'
import { runInNewContext } from 'vm'
import { deepFreeze } from '../shared/lib/deep-freeze'
const sharedCache = new Map<string, unknown>()
/**
* Load a manifest file from the file system. Optionally cache the manifest in
* memory to avoid reading the file multiple times using the provided cache or
* defaulting to a shared module cache. The manifest is frozen to prevent
* modifications if it is cached.
*
* @param path the path to the manifest file
* @param shouldCache whether to cache the manifest in memory
* @param cache the cache to use for storing the manifest
* @returns the manifest object
*/
export function loadManifest<T extends object>(
path: string,
shouldCache: false
): T
export function loadManifest<T extends object>(
path: string,
shouldCache?: boolean,
cache?: Map<string, unknown>
): DeepReadonly<T>
export function loadManifest<T extends object>(
path: string,
shouldCache?: true,
cache?: Map<string, unknown>
): DeepReadonly<T>
export function loadManifest<T extends object>(
path: string,
shouldCache: boolean = true,
cache = sharedCache
): T {
const cached = shouldCache && cache.get(path)
if (cached) {
return cached as T
}
let manifest = JSON.parse(readFileSync(path, 'utf8'))
// Freeze the manifest so it cannot be modified if we're caching it.
if (shouldCache) {
manifest = deepFreeze(manifest)
}
if (shouldCache) {
cache.set(path, manifest)
}
return manifest
}
export function evalManifest<T extends object>(
path: string,
shouldCache: false
): T
export function evalManifest<T extends object>(
path: string,
shouldCache?: boolean,
cache?: Map<string, unknown>
): DeepReadonly<T>
export function evalManifest<T extends object>(
path: string,
shouldCache?: true,
cache?: Map<string, unknown>
): DeepReadonly<T>
export function evalManifest<T extends object>(
path: string,
shouldCache: boolean = true,
cache = sharedCache
): T {
const cached = shouldCache && cache.get(path)
if (cached) {
return cached as T
}
const content = readFileSync(path, 'utf8')
if (content.length === 0) {
throw new Error('Manifest file is empty')
}
let contextObject = {}
runInNewContext(content, contextObject)
// Freeze the context object so it cannot be modified if we're caching it.
if (shouldCache) {
contextObject = deepFreeze(contextObject)
}
if (shouldCache) {
cache.set(path, contextObject)
}
return contextObject as T
}
export function clearManifestCache(path: string, cache = sharedCache): boolean {
return cache.delete(path)
}