-
-
Notifications
You must be signed in to change notification settings - Fork 955
/
index.ts
132 lines (126 loc) · 4.6 KB
/
index.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
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
import assertStore from '@pnpm/assert-store'
import { WANTED_LOCKFILE } from '@pnpm/constants'
import { Lockfile, LockfileImporter } from '@pnpm/lockfile-types'
import { Modules, read as readModules } from '@pnpm/modules-yaml'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
import path = require('path')
import exists = require('path-exists')
import readYamlFile from 'read-yaml-file'
import { Test } from 'tape'
import writePkg = require('write-pkg')
import isExecutable from './isExecutable'
export { isExecutable, Modules }
export type RawLockfile = Lockfile & Partial<LockfileImporter>
export interface Project {
requireModule: NodeRequireFunction
has (pkgName: string): Promise<void>
hasNot (pkgName: string): Promise<void>
getStorePath (): Promise<string>
resolve (pkgName: string, version?: string, relativePath?: string): Promise<string>
storeHas (pkgName: string, version?: string): Promise<string>
storeHasNot (pkgName: string, version?: string): Promise<void>
isExecutable (pathToExe: string): Promise<void>
/**
* TODO: Remove the `Required<T>` cast.
*
* https://github.com/microsoft/TypeScript/pull/32695 might help with this.
*/
readCurrentLockfile (): Promise<Required<RawLockfile>>
readModulesManifest (): Promise<Modules | null>
/**
* TODO: Remove the `Required<T>` cast.
*
* https://github.com/microsoft/TypeScript/pull/32695 might help with this.
*/
readLockfile (): Promise<Required<RawLockfile>>
writePackageJson (pkgJson: object): Promise<void>
}
export default (t: Test, projectPath: string, encodedRegistryName?: string): Project => {
const ern = encodedRegistryName || `localhost+${REGISTRY_MOCK_PORT}`
const modules = path.join(projectPath, 'node_modules')
let cachedStore: {
storePath: string;
storeHas (pkgName: string, version?: string | undefined): Promise<void>;
storeHasNot (pkgName: string, version?: string | undefined): Promise<void>;
resolve (pkgName: string, version?: string | undefined, relativePath?: string | undefined): Promise<string>
}
async function getStoreInstance () {
if (!cachedStore) {
const modulesYaml = await readModules(modules)
if (!modulesYaml) {
throw new Error(`Cannot find module store. No .modules.yaml found at "${modules}"`)
}
const storePath = modulesYaml.store
cachedStore = {
storePath,
...assertStore(t, storePath, ern),
}
}
return cachedStore
}
async function getVirtualStoreDir () {
const modulesYaml = await readModules(modules)
if (!modulesYaml) {
return path.join(modules, '.pnpm')
}
return modulesYaml.virtualStoreDir
}
return {
requireModule (pkgName: string) {
return require(path.join(modules, pkgName))
},
async has (pkgName: string) {
t.ok(await exists(path.join(modules, pkgName)), `${pkgName} is in node_modules`)
},
async hasNot (pkgName: string) {
t.notOk(await exists(path.join(modules, pkgName)), `${pkgName} is not in node_modules`)
},
async getStorePath () {
const store = await getStoreInstance()
return store.storePath
},
async resolve (pkgName: string, version?: string, relativePath?: string) {
const store = await getStoreInstance()
return store.resolve(pkgName, version, relativePath)
},
async storeHas (pkgName: string, version?: string) {
const store = await getStoreInstance()
return store.resolve(pkgName, version)
},
async storeHasNot (pkgName: string, version?: string) {
try {
const store = await getStoreInstance()
return store.storeHasNot(pkgName, version)
} catch (err) {
if (err.message.startsWith('Cannot find module store')) {
t.pass(`${pkgName}@${version} is not in store (store does not even exist)`)
return
}
throw err
}
},
isExecutable (pathToExe: string) {
return isExecutable(t, path.join(modules, pathToExe))
},
async readCurrentLockfile () {
try {
return await readYamlFile(path.join(await getVirtualStoreDir(), 'lock.yaml')) // tslint:disable-line
} catch (err) {
if (err.code === 'ENOENT') return null!
throw err
}
},
readModulesManifest: () => readModules(modules),
async readLockfile () {
try {
return await readYamlFile(path.join(projectPath, WANTED_LOCKFILE)) // tslint:disable-line
} catch (err) {
if (err.code === 'ENOENT') return null!
throw err
}
},
async writePackageJson (pkgJson: object) {
await writePkg(projectPath, pkgJson as any) // tslint:disable-line
},
}
}