Skip to content

Commit

Permalink
fix: ๐Ÿ› resolve binaries from current package location and memoize cosโ€ฆ
Browse files Browse the repository at this point in the history
โ€ฆtly operations (#154)

* fix: ๐Ÿ› resolve binaries from current package location

* fix: ๐Ÿ› removed yarn.lock

* fix: ๐Ÿ› removed package-lock
  • Loading branch information
remorses committed Jan 11, 2021
1 parent 6cfff93 commit 8c5ed2a
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 34 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@types/jest": "26.0.19",
"@types/json5": "0.0.30",
"@types/node": "13.13.38",
"@types/pnpapi": "^0.0.1",
"@types/prettier": "2.1.6",
"@types/rimraf": "3.0.0",
"@types/semantic-release": "17.2.0",
Expand Down Expand Up @@ -124,6 +125,7 @@
"fast-glob": "^3.2.2",
"globrex": "^0.1.2",
"json5": "^2.1.1",
"micro-memoize": "^4.0.9",
"npm-run-path": "4.0.1",
"pid-cwd": "^1.2.0",
"ps-list": "^7.0.0",
Expand Down
56 changes: 36 additions & 20 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ export class CommandParser {
if (existsSync(bin)) return bin
}
// Special syntax for pnp binaries. Handles by spawn.ts
if (this.binsPnp.has(name)) return `yarn:${this.binsPnp.get(name)}`
if (this.binsPnp.has(name)) {
return `yarn:${this.binsPnp.get(name)}`
}
}

private isBin(name: string) {
Expand Down
54 changes: 41 additions & 13 deletions src/pnp.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { existsSync, readFileSync } from "fs"
import * as pnpapi from "pnpapi"
import memoize from "micro-memoize"
import path, { resolve } from "path"
import v8 from "v8"
import zlib from "zlib"
Expand All @@ -18,22 +20,46 @@ type InstallState = {
>
}

type PnpAPI = {
resolveRequest: (bin: string, dir: string) => string
type PnpAPI = typeof pnpapi & {
// getDependencyTreeRoots is missing in pnpapi types https://yarnpkg.com/advanced/pnpapi#getdependencytreeroots
getDependencyTreeRoots: () => pnpapi.PhysicalPackageLocator[]
}

export function getBinaries(workspaceRoot: string, packageName: string) {
const binaries = new Map<string, string>()

const getInstallState = memoize((workspaceRoot: string) => {
const serializedState = readFileSync(
resolve(workspaceRoot, ".yarn", "install-state.gz")
)
const installState = v8.deserialize(
const installState: InstallState = v8.deserialize(
zlib.gunzipSync(serializedState)
) as InstallState
)
return installState
})

export function getBinaries(workspaceRoot: string, packageName: string) {
const binaries = new Map<string, string>()
const installState = getInstallState(workspaceRoot)
const hashes = new Set<string>()

const {
resolveRequest,
getPackageInformation,
getDependencyTreeRoots,
} = getPnpApi(workspaceRoot)

let packageLocator = getDependencyTreeRoots().find(
(x) => x.name === packageName
)

if (!packageLocator) {
throw new Error(`Cannot find package locator for ${packageName}`)
}

const packageLocation = getPackageInformation(packageLocator).packageLocation

if (!packageLocation) {
throw new Error(`Cannot find package location for ${packageName}`)
}

for (const p of installState.storedPackages.values()) {
const pkgName = p.scope ? `@${p.scope}/${p.name}` : p.name
if (packageName == pkgName) {
Expand All @@ -44,7 +70,7 @@ export function getBinaries(workspaceRoot: string, packageName: string) {
})
}
}
const { resolveRequest } = getPnpApi(workspaceRoot)

for (const h of hashes) {
const p = installState.storedPackages.get(h)
if (p?.bin.size) {
Expand All @@ -54,9 +80,11 @@ export function getBinaries(workspaceRoot: string, packageName: string) {
const binPath = resolveRequest(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
path.join(pkgName, p.bin.get(b)!),
path.resolve(process.cwd(), "package.json")
path.resolve(packageLocation, "package.json")
)
binaries.set(b, binPath)
if (binPath) {
binaries.set(b, binPath)
}
// eslint-disable-next-line no-empty
} catch {}
})
Expand All @@ -66,8 +94,8 @@ export function getBinaries(workspaceRoot: string, packageName: string) {
return binaries
}

function getPnpApi(workspaceRoot: string): PnpAPI {
const getPnpApi = memoize(function getPnpApi(workspaceRoot: string): PnpAPI {
const jsPath = path.resolve(workspaceRoot, ".pnp.js")
const cjsPath = path.resolve(workspaceRoot, ".pnp.cjs")
return (existsSync(jsPath) ? require(jsPath) : require(cjsPath)) as PnpAPI
}
return existsSync(jsPath) ? require(jsPath) : require(cjsPath)
})

0 comments on commit 8c5ed2a

Please sign in to comment.