feat: save the metadata separately from the CAFS (#3578)

ref #2574
This commit is contained in:
Zoltan Kochan
2021-07-04 19:35:53 +03:00
committed by GitHub
parent b3478c756a
commit 691f647137
44 changed files with 320 additions and 157 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/client": minor
---
New config setting added: cacheDir.

View File

@@ -0,0 +1,19 @@
---
"@pnpm/client": major
"@pnpm/default-resolver": major
"@pnpm/npm-resolver": major
"@pnpm/outdated": major
"@pnpm/plugin-commands-audit": major
"@pnpm/plugin-commands-import": major
"@pnpm/plugin-commands-installation": major
"@pnpm/plugin-commands-listing": major
"@pnpm/plugin-commands-outdated": major
"@pnpm/plugin-commands-publishing": major
"@pnpm/plugin-commands-rebuild": major
"@pnpm/plugin-commands-script-runners": major
"@pnpm/plugin-commands-store": major
"@pnpm/store-connection-manager": major
"supi": minor
---
New required option added: cacheDir.

View File

@@ -4,7 +4,7 @@ import createClient, { createResolver } from '@pnpm/client'
test('createClient()', () => {
const client = createClient({
authConfig: { registry: 'https://registry.npmjs.org/' },
storeDir: '',
cacheDir: '',
})
expect(typeof client === 'object').toBeTruthy()
})
@@ -12,7 +12,7 @@ test('createClient()', () => {
test('createResolver()', () => {
const resolver = createResolver({
authConfig: { registry: 'https://registry.npmjs.org/' },
storeDir: '',
cacheDir: '',
})
expect(typeof resolver === 'function').toBeTruthy()
})

View File

@@ -89,6 +89,7 @@ export interface Config {
alwaysAuth?: boolean
// pnpm specific configs
cacheDir: string
storeDir?: string
virtualStoreDir?: string
verifyStoreIntegrity?: boolean

View File

@@ -0,0 +1,20 @@
import os from 'os'
import path from 'path'
export default function getCacheDir (
opts: {
env: NodeJS.ProcessEnv
platform: string
}
) {
if (opts.env.XDG_CACHE_HOME) {
return path.join(opts.env.XDG_CACHE_HOME, 'pnpm')
}
if (opts.platform !== 'win32') {
return path.join(os.homedir(), '.cache/pnpm')
}
if (opts.env.LOCALAPPDATA) {
return path.join(opts.env.LOCALAPPDATA, 'pnpm-cache')
}
return path.join(os.homedir(), '.pnpm-cache')
}

View File

@@ -13,6 +13,7 @@ import realpathMissing from 'realpath-missing'
import whichcb from 'which'
import getScopeRegistries, { normalizeRegistry } from './getScopeRegistries'
import findBestGlobalPrefix from './findBestGlobalPrefix'
import getCacheDir from './getCacheDir'
import {
Config,
ConfigWithDeprecatedSettings,
@@ -358,6 +359,9 @@ export default async (
warnings.push('The "store" setting has been renamed to "store-dir". Please use the new name.')
pnpmConfig.storeDir = pnpmConfig['store']
}
if (!pnpmConfig.cacheDir) {
pnpmConfig.cacheDir = getCacheDir(process)
}
if (pnpmConfig['hoist'] === false) {
delete pnpmConfig.hoistPattern
}

View File

@@ -0,0 +1,26 @@
import os from 'os'
import path from 'path'
import getCacheDir from '../lib/getCacheDir'
test('getCacheDir()', () => {
expect(getCacheDir({
env: {
XDG_CACHE_HOME: '/home/foo/cache',
},
platform: 'linux',
})).toBe(path.join('/home/foo/cache', 'pnpm'))
expect(getCacheDir({
env: {},
platform: 'linux',
})).toBe(path.join(os.homedir(), '.cache/pnpm'))
expect(getCacheDir({
env: {
LOCALAPPDATA: '/localappdata',
},
platform: 'win32',
})).toBe(path.join('/localappdata', 'pnpm-cache'))
expect(getCacheDir({
env: {},
platform: 'win32',
})).toBe(path.join(os.homedir(), '.pnpm-cache'))
})

View File

@@ -5,7 +5,7 @@ import { createFetchFromRegistry } from '@pnpm/fetch'
test('createResolver()', () => {
const getCredentials = () => ({ authHeaderValue: '', alwaysAuth: false })
const resolve = createResolver(createFetchFromRegistry({}), getCredentials, {
storeDir: '.store',
cacheDir: '.cache',
})
expect(typeof resolve).toEqual('function')
})

View File

@@ -1,3 +1,4 @@
import path from 'path'
import createClient from '@pnpm/client'
import { HeadlessOptions } from '@pnpm/headless'
import createStore from '@pnpm/package-store'
@@ -22,7 +23,9 @@ export default async function testDefaults (
fetchOpts?: any, // eslint-disable-line
storeOpts?: any, // eslint-disable-line
): Promise<HeadlessOptions> {
let storeDir = opts?.storeDir ?? tempy.directory()
const tmp = tempy.directory()
let storeDir = opts?.storeDir ?? path.join(tmp, 'store')
const cacheDir = path.join(tmp, 'cache')
const lockfileDir = opts?.lockfileDir ?? process.cwd()
const { include, pendingBuilds, projects, registries } = await readProjectsContext(
[
@@ -37,7 +40,7 @@ export default async function testDefaults (
const { resolve, fetchers } = createClient({
authConfig,
retry: retryOpts,
storeDir,
cacheDir,
...resolveOpts,
...fetchOpts,
})

View File

@@ -54,7 +54,7 @@ const META_DIR = 'metadata'
const FULL_META_DIR = 'metadata-full'
export interface ResolverFactoryOptions {
storeDir: string
cacheDir: string
fullMetadata?: boolean
offline?: boolean
preferOffline?: boolean
@@ -67,8 +67,8 @@ export default function createResolver (
getCredentials: GetCredentials,
opts: ResolverFactoryOptions
) {
if (typeof opts.storeDir !== 'string') { // eslint-disable-line
throw new TypeError('`opts.storeDir` is required and needs to be a string')
if (typeof opts.cacheDir !== 'string') { // eslint-disable-line
throw new TypeError('`opts.cacheDir` is required and needs to be a string')
}
const fetchOpts = {
retry: opts.retry ?? {},
@@ -91,7 +91,7 @@ export default function createResolver (
metaDir: opts.fullMetadata ? FULL_META_DIR : META_DIR,
offline: opts.offline,
preferOffline: opts.preferOffline,
storeDir: opts.storeDir,
cacheDir: opts.cacheDir,
}),
})
}

View File

@@ -57,7 +57,7 @@ export default async (
fetch: (pkgName: string, registry: string, authHeaderValue?: string) => Promise<PackageMeta>
metaDir: string
metaCache: PackageMetaCache
storeDir: string
cacheDir: string
offline?: boolean
preferOffline?: boolean
},
@@ -77,7 +77,7 @@ export default async (
}
const registryName = getRegistryName(opts.registry)
const pkgMirror = path.join(ctx.storeDir, ctx.metaDir, registryName, `${encodePkgName(spec.name)}.json`)
const pkgMirror = path.join(ctx.cacheDir, ctx.metaDir, registryName, `${encodePkgName(spec.name)}.json`)
const limit = metafileOperationLimits[pkgMirror] = metafileOperationLimits[pkgMirror] || pLimit(1)
let metaCachedInStore: PackageMeta | null | undefined

View File

@@ -46,9 +46,9 @@ test('resolveFromNpm()', async () => {
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
registry,
@@ -68,7 +68,7 @@ test('resolveFromNpm()', async () => {
// The resolve function does not wait for the package meta cache file to be saved
// so we must delay for a bit in order to read it
const meta = await retryLoadJsonFile<any>(path.join(storeDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
const meta = await retryLoadJsonFile<any>(path.join(cacheDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
expect(meta.name).toBeTruthy()
expect(meta.versions).toBeTruthy()
expect(meta['dist-tags']).toBeTruthy()
@@ -79,9 +79,9 @@ test('resolveFromNpm() should save metadata to a unique file when the package na
.get('/JSON')
.reply(200, jsonMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'JSON', pref: '1.0.0' }, {
registry,
@@ -92,16 +92,16 @@ test('resolveFromNpm() should save metadata to a unique file when the package na
// The resolve function does not wait for the package meta cache file to be saved
// so we must delay for a bit in order to read it
const meta = await retryLoadJsonFile<any>(path.join(storeDir, 'metadata/registry.npmjs.org/JSON_0ecd11c1d7a287401d148a23bbd7a2f8.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
const meta = await retryLoadJsonFile<any>(path.join(cacheDir, 'metadata/registry.npmjs.org/JSON_0ecd11c1d7a287401d148a23bbd7a2f8.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
expect(meta.name).toBeTruthy()
expect(meta.versions).toBeTruthy()
expect(meta['dist-tags']).toBeTruthy()
})
test('relative workspace protocol is skipped', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ pref: 'workspace:../is-positive' }, {
projectDir: '/home/istvan/src',
@@ -116,9 +116,9 @@ test('dry run', async () => {
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
dryRun: true,
@@ -139,7 +139,7 @@ test('dry run', async () => {
// The resolve function does not wait for the package meta cache file to be saved
// so we must delay for a bit in order to read it
await delay(500)
expect(await exists(path.join(storeDir, resolveResult!.id, '..', 'index.json'))).toBeFalsy()
expect(await exists(path.join(cacheDir, resolveResult!.id, '..', 'index.json'))).toBeFalsy()
})
test('resolve to latest when no pref specified', async () => {
@@ -148,7 +148,7 @@ test('resolve to latest when no pref specified', async () => {
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is-positive' }, {
registry,
@@ -162,7 +162,7 @@ test('resolve to defaultTag when no pref specified', async () => {
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is-positive' }, {
defaultTag: 'stable',
@@ -177,7 +177,7 @@ test('resolve to biggest non-deprecated version that satisfies the range', async
.reply(200, isPositiveMetaWithDeprecated)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: '3' }, {
registry,
@@ -191,7 +191,7 @@ test('resolve to a deprecated version if there are no non-deprecated ones that s
.reply(200, isPositiveMetaWithDeprecated)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: '2' }, {
registry,
@@ -205,7 +205,7 @@ test('can resolve aliased dependency', async () => {
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'positive', pref: 'npm:is-positive@1.0.0' }, {
registry,
@@ -219,7 +219,7 @@ test('can resolve aliased dependency w/o version specifier', async () => {
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'positive', pref: 'npm:is-positive' }, {
registry,
@@ -233,7 +233,7 @@ test('can resolve aliased dependency w/o version specifier to default tag', asyn
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'positive', pref: 'npm:is-positive' }, {
defaultTag: 'stable',
@@ -248,7 +248,7 @@ test('can resolve aliased scoped dependency', async () => {
.reply(200, sindresorhusIsMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is', pref: 'npm:@sindresorhus/is@0.6.0' }, {
registry,
@@ -262,7 +262,7 @@ test('can resolve aliased scoped dependency w/o version specifier', async () =>
.reply(200, sindresorhusIsMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is', pref: 'npm:@sindresorhus/is' }, {
registry,
@@ -276,7 +276,7 @@ test('can resolve package with version prefixed with v', async () => {
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: 'v1.0.0' }, {
registry,
@@ -290,7 +290,7 @@ test('can resolve package version loosely', async () => {
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: '= 1.0.0' }, {
registry,
@@ -307,7 +307,7 @@ test("resolves to latest if it's inside the wanted range. Even if there are newe
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -329,7 +329,7 @@ test("resolves to latest if it's inside the preferred range. Even if there are n
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -354,7 +354,7 @@ test("resolve using the wanted range, when it doesn't intersect with the preferr
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -378,7 +378,7 @@ test("use the preferred version if it's inside the wanted range", async () => {
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -403,7 +403,7 @@ test("ignore the preferred version if it's not inside the wanted range", async (
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -426,7 +426,7 @@ test('use the preferred range if it intersects with the wanted range', async ()
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -451,7 +451,7 @@ test('use the preferred range if it intersects with the wanted range (an array o
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -479,7 +479,7 @@ test("ignore the preferred range if it doesn't intersect with the wanted range",
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -505,7 +505,7 @@ test("use the preferred dist-tag if it's inside the wanted range", async () => {
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -531,7 +531,7 @@ test("ignore the preferred dist-tag if it's not inside the wanted range", async
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -556,7 +556,7 @@ test("prefer a version that is both inside the wanted and preferred ranges. Even
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -571,15 +571,15 @@ test("prefer a version that is both inside the wanted and preferred ranges. Even
})
test('offline resolution fails when package meta not found in the store', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
offline: true,
storeDir,
cacheDir,
})
await expect(resolve({ alias: 'is-positive', pref: '1.0.0' }, { registry })).rejects
.toThrow(
new PnpmError('NO_OFFLINE_META', `Failed to resolve is-positive@1.0.0 in package mirror ${path.join(storeDir, 'metadata/registry.npmjs.org/is-positive.json')}`)
new PnpmError('NO_OFFLINE_META', `Failed to resolve is-positive@1.0.0 in package mirror ${path.join(cacheDir, 'metadata/registry.npmjs.org/is-positive.json')}`)
)
})
@@ -588,12 +588,12 @@ test('offline resolution succeeds when package meta is found in the store', asyn
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
{
const resolve = createResolveFromNpm({
offline: false,
storeDir,
cacheDir,
})
// This request will save the package's meta in the store
@@ -603,7 +603,7 @@ test('offline resolution succeeds when package meta is found in the store', asyn
{
const resolve = createResolveFromNpm({
offline: true,
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, { registry })
@@ -618,7 +618,7 @@ test('prefer offline resolution does not fail when package meta not found in the
const resolve = createResolveFromNpm({
preferOffline: true,
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, { registry })
@@ -633,11 +633,11 @@ test('when prefer offline is used, meta from store is used, where latest might b
'dist-tags': { latest: '3.0.0' },
})
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
{
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
// This request will save the package's meta in the store
@@ -654,7 +654,7 @@ test('when prefer offline is used, meta from store is used, where latest might b
{
const resolve = createResolveFromNpm({
preferOffline: true,
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '^3.0.0' }, { registry })
@@ -672,7 +672,7 @@ test('error is thrown when package is not found in the registry', async () => {
.reply(404, {})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
await expect(resolveFromNpm({ alias: notExistingPackage, pref: '1.0.0' }, { registry })).rejects
.toThrow(
@@ -694,7 +694,7 @@ test('error is thrown when registry not responding', async () => {
const notExistingRegistry = 'http://localhost:4873'
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
retry: { retries: 1 },
})
await expect(resolveFromNpm({ alias: notExistingPackage, pref: '1.0.0' }, { registry: notExistingRegistry })).rejects
@@ -709,7 +709,7 @@ test('extra info is shown if package has valid semver appended', async () => {
.reply(404, {})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
await expect(resolveFromNpm({ alias: notExistingPackage, pref: '1.0.0' }, { registry })).rejects
.toThrow(
@@ -732,7 +732,7 @@ test('error is thrown when there is no package found for the requested version',
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const wantedDependency = { alias: 'is-positive', pref: '1000.0.0' }
await expect(resolveFromNpm(wantedDependency, { registry })).rejects
@@ -750,7 +750,7 @@ test('error is thrown when package needs authorization', async () => {
.reply(403)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
await expect(resolveFromNpm({ alias: 'needs-auth', pref: '*' }, { registry })).rejects
.toThrow(
@@ -773,7 +773,7 @@ test('error is thrown when there is no package found for the requested range', a
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const wantedDependency = { alias: 'is-positive', pref: '^1000.0.0' }
await expect(resolveFromNpm(wantedDependency, { registry })).rejects
@@ -791,7 +791,7 @@ test('error is thrown when there is no package found for the requested tag', asy
.reply(200, isPositiveMeta)
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const wantedDependency = { alias: 'is-positive', pref: 'unknown-tag' }
await expect(resolveFromNpm(wantedDependency, { registry })).rejects
@@ -810,12 +810,12 @@ test('resolveFromNpm() loads full metadata even if non-full metadata is alread c
.get('/is-positive')
.reply(200, isPositiveMetaFull)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
{
const resolve = createResolveFromNpm({
fullMetadata: false,
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
registry,
@@ -826,7 +826,7 @@ test('resolveFromNpm() loads full metadata even if non-full metadata is alread c
{
const resolve = createResolveFromNpm({
fullMetadata: true,
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
registry,
@@ -840,9 +840,9 @@ test('resolve when tarball URL is requested from the registry', async () => {
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: `${registry}is-positive/-/is-positive-1.0.0.tgz` }, {
registry,
@@ -863,7 +863,7 @@ test('resolve when tarball URL is requested from the registry', async () => {
// The resolve function does not wait for the package meta cache file to be saved
// so we must delay for a bit in order to read it
const meta = await retryLoadJsonFile<any>(path.join(storeDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
const meta = await retryLoadJsonFile<any>(path.join(cacheDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
expect(meta.name).toBeTruthy()
expect(meta.versions).toBeTruthy()
expect(meta['dist-tags']).toBeTruthy()
@@ -874,9 +874,9 @@ test('resolve when tarball URL is requested from the registry and alias is not s
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ pref: `${registry}is-positive/-/is-positive-1.0.0.tgz` }, {
registry,
@@ -897,7 +897,7 @@ test('resolve when tarball URL is requested from the registry and alias is not s
// The resolve function does not wait for the package meta cache file to be saved
// so we must delay for a bit in order to read it
const meta = await retryLoadJsonFile<any>(path.join(storeDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
const meta = await retryLoadJsonFile<any>(path.join(cacheDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
expect(meta.name).toBeTruthy()
expect(meta.versions).toBeTruthy()
expect(meta['dist-tags']).toBeTruthy()
@@ -908,9 +908,9 @@ test('resolve from local directory when it matches the latest version of the pac
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
projectDir: '/home/istvan/src',
@@ -945,9 +945,9 @@ test('do not resolve from local directory when alwaysTryWorkspacePackages is fal
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
alwaysTryWorkspacePackages: false,
@@ -980,9 +980,9 @@ test('do not resolve from local directory when alwaysTryWorkspacePackages is fal
})
test('resolve from local directory when alwaysTryWorkspacePackages is false but workspace: is used', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: 'workspace:*' }, {
alwaysTryWorkspacePackages: false,
@@ -1013,9 +1013,9 @@ test('resolve from local directory when alwaysTryWorkspacePackages is false but
})
test('resolve from local directory when alwaysTryWorkspacePackages is false but workspace: is used with a different package name', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'positive', pref: 'workspace:is-positive@*' }, {
alwaysTryWorkspacePackages: false,
@@ -1054,7 +1054,7 @@ test('use version from the registry if it is newer than the local one', async ()
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -1097,7 +1097,7 @@ test('preferWorkspacePackages: use version from the workspace even if there is n
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -1137,7 +1137,7 @@ test('use local version if it is newer than the latest in the registry', async (
})
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
const resolveResult = await resolveFromNpm({
alias: 'is-positive',
@@ -1175,9 +1175,9 @@ test('resolve from local directory when package is not found in the registry', a
.get('/is-positive')
.reply(404, {})
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1' }, {
projectDir: '/home/istvan/src/foo',
@@ -1226,9 +1226,9 @@ test('resolve from local directory when package is not found in the registry and
.get('/is-positive')
.reply(404, {})
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: 'latest' }, {
projectDir: '/home/istvan/src',
@@ -1277,9 +1277,9 @@ test('resolve from local directory when package is not found in the registry and
.get('/is-positive')
.reply(404, {})
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.1.0' }, {
projectDir: '/home/istvan/src/foo',
@@ -1328,9 +1328,9 @@ test('resolve from local directory when the requested version is not found in th
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '100.0.0' }, {
projectDir: '/home/istvan/src/foo',
@@ -1361,9 +1361,9 @@ test('resolve from local directory when the requested version is not found in th
})
test('workspace protocol: resolve from local directory even when it does not match the latest version of the package', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: 'workspace:^3.0.0' }, {
projectDir: '/home/istvan/src',
@@ -1398,9 +1398,9 @@ test('workspace protocol: resolve from local package that has a pre-release vers
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: 'workspace:*' }, {
projectDir: '/home/istvan/src',
@@ -1435,9 +1435,9 @@ test("workspace protocol: don't resolve from local package that has a pre-releas
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '2' }, {
projectDir: '/home/istvan/src',
@@ -1464,9 +1464,9 @@ test("workspace protocol: don't resolve from local package that has a pre-releas
})
test('workspace protocol: resolution fails if there is no matching local package', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const projectDir = '/home/istvan/src'
@@ -1487,9 +1487,9 @@ test('workspace protocol: resolution fails if there is no matching local package
})
test('workspace protocol: resolution fails if there are no local packages', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
let err!: Error
@@ -1508,7 +1508,7 @@ test('workspace protocol: resolution fails if there are no local packages', asyn
test('throws error when package name has "/" but not starts with @scope', async () => {
const resolveFromNpm = createResolveFromNpm({
storeDir: tempy.directory(),
cacheDir: tempy.directory(),
})
await expect(resolveFromNpm({ alias: 'regenerator/runtime' }, { registry })).rejects
.toThrow(
@@ -1521,9 +1521,9 @@ test('resolveFromNpm() should always return the name of the package that is spec
.get('/is-positive')
.reply(200, isPositiveBrokenMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '3.1.0' }, {
registry,
@@ -1543,7 +1543,7 @@ test('resolveFromNpm() should always return the name of the package that is spec
// The resolve function does not wait for the package meta cache file to be saved
// so we must delay for a bit in order to read it
const meta = await retryLoadJsonFile<any>(path.join(storeDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
const meta = await retryLoadJsonFile<any>(path.join(cacheDir, 'metadata/registry.npmjs.org/is-positive.json')) // eslint-disable-line @typescript-eslint/no-explicit-any
expect(meta.name).toBeTruthy()
expect(meta.versions).toBeTruthy()
expect(meta['dist-tags']).toBeTruthy()
@@ -1559,10 +1559,10 @@ test('request to metadata is retried if the received JSON is broken', async () =
.get('/is-positive')
.reply(200, isPositiveMeta)
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
retry: { retries: 1 },
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: '1.0.0' }, {
registry,
@@ -1576,8 +1576,8 @@ test('request to a package with malformed metadata', async () => {
.get('/code-snippet')
.reply(200, loadJsonFile.sync(path.join(__dirname, 'meta/malformed.json')))
const storeDir = tempy.directory()
const resolve = createResolveFromNpm({ storeDir })
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({ cacheDir })
await expect(resolve({ alias: 'code-snippet' }, { registry })).rejects
.toThrow(
@@ -1586,9 +1586,9 @@ test('request to a package with malformed metadata', async () => {
})
test('resolve workspace:^', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: 'workspace:^' }, {
projectDir: '/home/istvan/src',
@@ -1618,9 +1618,9 @@ test('resolve workspace:^', async () => {
})
test('resolve workspace:~', async () => {
const storeDir = tempy.directory()
const cacheDir = tempy.directory()
const resolve = createResolveFromNpm({
storeDir,
cacheDir,
})
const resolveResult = await resolve({ alias: 'is-positive', pref: 'workspace:~' }, {
projectDir: '/home/istvan/src',

View File

@@ -44,7 +44,6 @@
"@pnpm/matcher": "workspace:2.0.0",
"@pnpm/modules-yaml": "workspace:9.0.3",
"@pnpm/pick-registry-for-package": "workspace:2.0.3",
"@pnpm/store-path": "^5.0.0",
"@pnpm/types": "workspace:7.3.0",
"dependency-path": "workspace:8.0.3",
"ramda": "^0.27.1",

View File

@@ -5,7 +5,6 @@ import {
} from '@pnpm/lockfile-file'
import matcher from '@pnpm/matcher'
import { read as readModulesManifest } from '@pnpm/modules-yaml'
import storePath from '@pnpm/store-path'
import {
IncludedDependencies,
ProjectManifest,
@@ -17,10 +16,10 @@ import outdated, { OutdatedPackage } from './outdated'
export default async function outdatedDepsOfProjects (
pkgs: Array<{dir: string, manifest: ProjectManifest}>,
args: string[],
opts: Omit<ManifestGetterOptions, 'fullMetadata' | 'storeDir' | 'lockfileDir'> & {
opts: Omit<ManifestGetterOptions, 'fullMetadata' | 'lockfileDir'> & {
compatible?: boolean
include: IncludedDependencies
} & Partial<Pick<ManifestGetterOptions, 'fullMetadata' | 'storeDir' | 'lockfileDir'>>
} & Partial<Pick<ManifestGetterOptions, 'fullMetadata' | 'lockfileDir'>>
): Promise<OutdatedPackage[][]> {
if (!opts.lockfileDir) {
return unnest(await Promise.all(
@@ -34,12 +33,10 @@ export default async function outdatedDepsOfProjects (
const virtualStoreDir = modules?.virtualStoreDir ?? path.join(lockfileDir, 'node_modules/.pnpm')
const currentLockfile = await readCurrentLockfile(virtualStoreDir, { ignoreIncompatible: false })
const wantedLockfile = await readWantedLockfile(lockfileDir, { ignoreIncompatible: false }) ?? currentLockfile
const storeDir = await storePath(opts.dir, opts.storeDir)
const getLatestManifest = createManifestGetter({
...opts,
fullMetadata: opts.fullMetadata === true,
lockfileDir,
storeDir,
})
return Promise.all(pkgs.map(async ({ dir, manifest }) => {
const match = (args.length > 0) && matcher(args) || undefined

View File

@@ -24,7 +24,7 @@ const authConfig = { registry }
const { resolve, fetchers } = createClient({
authConfig,
storeDir: '.store',
cacheDir: '.store',
})
test('request package', async () => {
@@ -530,7 +530,7 @@ test('fetchPackageToStore() does not cache errors', async () => {
const noRetry = createClient({
authConfig,
retry: { retries: 0 },
storeDir: '.pnpm',
cacheDir: '.pnpm',
})
const storeDir = tempy.directory()

View File

@@ -1,16 +1,18 @@
/// <reference path="../../../typings/index.d.ts"/>
import path from 'path'
import createClient from '@pnpm/client'
import createStore from '@pnpm/package-store'
import tempy from 'tempy'
describe('store.importPackage()', () => {
it('selects import method automatically', async () => {
const storeDir = tempy.directory()
const tmp = tempy.directory()
const storeDir = path.join(tmp, 'store')
const registry = 'https://registry.npmjs.org/'
const authConfig = { registry }
const { resolve, fetchers } = createClient({
authConfig,
storeDir,
cacheDir: path.join(tmp, 'cache'),
})
const storeController = await createStore(resolve, fetchers, {
storeDir,
@@ -39,12 +41,13 @@ describe('store.importPackage()', () => {
})
it('uses copying', async () => {
const storeDir = tempy.directory()
const tmp = tempy.directory()
const storeDir = path.join(tmp, 'store')
const registry = 'https://registry.npmjs.org/'
const authConfig = { registry }
const { resolve, fetchers } = createClient({
authConfig,
storeDir,
cacheDir: path.join(tmp, 'cache'),
})
const storeController = await createStore(resolve, fetchers, {
packageImportMethod: 'copy',

View File

@@ -122,6 +122,17 @@ exports[`audit --audit-level 1`] = `
├─────────────────────┼───────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1678 │
└─────────────────────┴───────────────────────────────────┘
┌─────────────────────┬─────────────────────────────────────────┐
│ high │ Resource exhaustion in socket.io-parser │
├─────────────────────┼─────────────────────────────────────────┤
│ Package │ socket.io-parser │
├─────────────────────┼─────────────────────────────────────────┤
│ Vulnerable versions │ <3.3.2 || =3.4.0 │
├─────────────────────┼─────────────────────────────────────────┤
│ Patched versions │ >=3.3.2 <3.4.0 || >=3.4.1 │
├─────────────────────┼─────────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1763 │
└─────────────────────┴─────────────────────────────────────────┘
┌─────────────────────┬──────────────────────────────────┐
│ moderate │ Prototype Pollution │
├─────────────────────┼──────────────────────────────────┤
@@ -177,8 +188,8 @@ exports[`audit --audit-level 1`] = `
├─────────────────────┼──────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1751 │
└─────────────────────┴──────────────────────────────────────┘
23 vulnerabilities found
Severity: 7 low | 5 moderate | 9 high | 2 critical"
24 vulnerabilities found
Severity: 7 low | 5 moderate | 10 high | 2 critical"
`;
exports[`audit --dev 1`] = `
@@ -330,6 +341,17 @@ exports[`audit 1`] = `
├─────────────────────┼───────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1678 │
└─────────────────────┴───────────────────────────────────┘
┌─────────────────────┬─────────────────────────────────────────┐
│ high │ Resource exhaustion in socket.io-parser │
├─────────────────────┼─────────────────────────────────────────┤
│ Package │ socket.io-parser │
├─────────────────────┼─────────────────────────────────────────┤
│ Vulnerable versions │ <3.3.2 || =3.4.0 │
├─────────────────────┼─────────────────────────────────────────┤
│ Patched versions │ >=3.3.2 <3.4.0 || >=3.4.1 │
├─────────────────────┼─────────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1763 │
└─────────────────────┴─────────────────────────────────────────┘
┌─────────────────────┬──────────────────────────────────┐
│ moderate │ Prototype Pollution │
├─────────────────────┼──────────────────────────────────┤
@@ -451,6 +473,6 @@ exports[`audit 1`] = `
├─────────────────────┼──────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1662 │
└─────────────────────┴──────────────────────────────────────┘
23 vulnerabilities found
Severity: 7 low | 5 moderate | 9 high | 2 critical"
24 vulnerabilities found
Severity: 7 low | 5 moderate | 10 high | 2 critical"
`;

View File

@@ -14,10 +14,12 @@ const ncp = promisify(ncpCB)
const fixtures = path.join(__dirname, '../../../fixtures')
const REGISTRY = `http://localhost:${REGISTRY_MOCK_PORT}`
const TMP = tempy.directory()
const DEFAULT_OPTS = {
alwaysAuth: false,
ca: undefined,
cacheDir: path.join(TMP, 'cache'),
cert: undefined,
fetchRetries: 2,
fetchRetryFactor: 90,
@@ -34,7 +36,7 @@ const DEFAULT_OPTS = {
rawConfig: { registry: REGISTRY },
registries: { default: REGISTRY },
registry: REGISTRY,
storeDir: tempy.directory(),
storeDir: path.join(TMP, 'store'),
strictSsl: false,
userAgent: 'pnpm',
useRunningStoreServer: false,

View File

@@ -7,6 +7,7 @@ import loadJsonFile from 'load-json-file'
import tempy from 'tempy'
const REGISTRY_URL = `http://localhost:${REGISTRY_MOCK_PORT}`
const tmp = tempy.directory()
const DEFAULT_OPTIONS = {
argv: {
@@ -14,6 +15,7 @@ const DEFAULT_OPTIONS = {
},
bail: false,
bin: 'node_modules/.bin',
cacheDir: path.join(tmp, 'cache'),
cliOptions: {},
include: {
dependencies: true,
@@ -28,7 +30,7 @@ const DEFAULT_OPTIONS = {
default: REGISTRY_URL,
},
sort: true,
storeDir: tempy.directory(),
storeDir: path.join(tmp, 'store'),
workspaceConcurrency: 1,
}

View File

@@ -39,6 +39,7 @@ test('fetch dependencies', async () => {
await install.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: true,
storeDir,
@@ -52,6 +53,7 @@ test('fetch dependencies', async () => {
await fetch.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
storeDir,
})
@@ -68,6 +70,7 @@ test('fetch production dependencies', async () => {
const storeDir = path.resolve('store')
await install.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: true,
storeDir,
@@ -81,6 +84,7 @@ test('fetch production dependencies', async () => {
await fetch.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dev: true,
dir: process.cwd(),
storeDir,
@@ -98,6 +102,7 @@ test('fetch only dev dependencies', async () => {
const storeDir = path.resolve('store')
await install.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: true,
storeDir,
@@ -111,6 +116,7 @@ test('fetch only dev dependencies', async () => {
await fetch.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dev: true,
dir: process.cwd(),
storeDir,

View File

@@ -1,9 +1,11 @@
import { add, install } from '@pnpm/plugin-commands-installation'
import prepare from '@pnpm/prepare'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
import path from 'path'
import tempy from 'tempy'
const REGISTRY_URL = `http://localhost:${REGISTRY_MOCK_PORT}`
const TMP = tempy.directory()
const DEFAULT_OPTIONS = {
argv: {
@@ -11,6 +13,7 @@ const DEFAULT_OPTIONS = {
},
bail: false,
bin: 'node_modules/.bin',
cacheDir: path.join(TMP, 'cache'),
cliOptions: {},
include: {
dependencies: true,
@@ -25,7 +28,7 @@ const DEFAULT_OPTIONS = {
default: REGISTRY_URL,
},
sort: true,
storeDir: tempy.directory(),
storeDir: path.join(TMP, 'store'),
workspaceConcurrency: 1,
}

View File

@@ -36,6 +36,7 @@ test('prune removes external link that is not in package.json', async () => {
await link.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
storeDir,
}, ['./local'])
@@ -44,6 +45,7 @@ test('prune removes external link that is not in package.json', async () => {
await prune.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
storeDir,
})
@@ -60,6 +62,7 @@ test('prune removes dev dependencies', async () => {
await install.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: true,
storeDir,
@@ -67,6 +70,7 @@ test('prune removes dev dependencies', async () => {
await prune.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dev: false,
dir: process.cwd(),
storeDir,

View File

@@ -57,6 +57,7 @@ test('interactively update', async () => {
const storeDir = path.resolve('pnpm-store')
await add.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: true,
save: false,
@@ -75,6 +76,7 @@ test('interactively update', async () => {
// t.comment('update to compatible versions')
await update.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
interactive: true,
linkWorkspacePackages: true,
@@ -113,6 +115,7 @@ test('interactively update', async () => {
prompt.mockClear()
await update.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
interactive: true,
latest: true,
@@ -179,6 +182,7 @@ test('interactive update of dev dependencies only', async () => {
const { allProjects, selectedProjectsGraph } = await readProjects(process.cwd(), [])
await install.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
allProjects,
dir: process.cwd(),
linkWorkspacePackages: true,
@@ -190,6 +194,7 @@ test('interactive update of dev dependencies only', async () => {
})
await update.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
allProjects,
cliOptions: {
dev: true,

View File

@@ -10,6 +10,7 @@ export const DEFAULT_OPTS = {
bail: true,
bin: 'node_modules/.bin',
ca: undefined,
cacheDir: '../cache',
cert: undefined,
cliOptions: {},
fetchRetries: 2,

View File

@@ -38,6 +38,7 @@ test('recursive list', async () => {
await install.handler({
...DEFAULT_OPTS,
allProjects,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
recursive: true,
selectedProjectsGraph,
@@ -99,6 +100,7 @@ test('recursive list with shared-workspace-lockfile', async () => {
await install.handler({
...DEFAULT_OPTS,
allProjects,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
recursive: true,
selectedProjectsGraph,
@@ -163,6 +165,7 @@ test('recursive list --filter', async () => {
await install.handler({
...DEFAULT_OPTS,
...await readProjects(process.cwd(), []),
cacheDir: path.resolve('cache'),
dir: process.cwd(),
recursive: true,
workspaceDir: process.cwd(),
@@ -216,6 +219,7 @@ test('recursive list --filter link-workspace-packages=false', async () => {
await install.handler({
...DEFAULT_OPTS,
...await readProjects(process.cwd(), [], { linkWorkspacePackages: false }),
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: false,
recursive: true,

View File

@@ -125,6 +125,7 @@ export type OutdatedCommandOptions = {
| 'allProjects'
| 'alwaysAuth'
| 'ca'
| 'cacheDir'
| 'cert'
| 'dev'
| 'dir'
@@ -148,7 +149,6 @@ export type OutdatedCommandOptions = {
| 'rawConfig'
| 'registries'
| 'selectedProjectsGraph'
| 'storeDir'
| 'strictSsl'
| 'tag'
| 'userAgent'

View File

@@ -20,6 +20,7 @@ const REGISTRY_URL = `http://localhost:${REGISTRY_MOCK_PORT}`
const OUTDATED_OPTIONS = {
alwaysAuth: false,
cacheDir: 'cache',
fetchRetries: 1,
fetchRetryFactor: 1,
fetchRetryMaxtimeout: 60,

View File

@@ -10,6 +10,7 @@ export const DEFAULT_OPTS = {
bail: false,
bin: 'node_modules/.bin',
ca: undefined,
cacheDir: '../cache',
cert: undefined,
cliOptions: {},
fetchRetries: 2,

View File

@@ -60,7 +60,6 @@
"@pnpm/resolver-base": "workspace:8.0.3",
"@pnpm/run-npm": "workspace:3.1.0",
"@pnpm/sort-packages": "workspace:2.1.0",
"@pnpm/store-path": "^5.0.0",
"@pnpm/types": "workspace:7.3.0",
"@zkochan/rimraf": "^2.1.1",
"cp-file": "^9.0.0",

View File

@@ -5,7 +5,6 @@ import logger from '@pnpm/logger'
import pickRegistryForPackage from '@pnpm/pick-registry-for-package'
import { ResolveFunction } from '@pnpm/resolver-base'
import sortPackages from '@pnpm/sort-packages'
import storePath from '@pnpm/store-path'
import { Registries } from '@pnpm/types'
import pFilter from 'p-filter'
import pick from 'ramda/src/pick'
@@ -13,6 +12,7 @@ import writeJsonFile from 'write-json-file'
import { handler as publish } from './publish'
export type PublishRecursiveOpts = Required<Pick<Config,
| 'cacheDir'
| 'cliOptions'
| 'dir'
| 'rawConfig'
@@ -40,7 +40,6 @@ Partial<Pick<Config,
| 'npmPath'
| 'offline'
| 'selectedProjectsGraph'
| 'storeDir'
| 'strictSsl'
| 'userAgent'
| 'verifyStoreIntegrity'
@@ -56,7 +55,6 @@ export default async function (
opts: PublishRecursiveOpts & Required<Pick<Config, 'selectedProjectsGraph'>>
) {
const pkgs = Object.values(opts.selectedProjectsGraph).map((wsPkg) => wsPkg.package)
const storeDir = await storePath(opts.workspaceDir, opts.storeDir)
const resolve = createResolver({
...opts,
authConfig: opts.rawConfig,
@@ -66,7 +64,6 @@ export default async function (
minTimeout: opts.fetchRetryMintimeout,
retries: opts.fetchRetries,
},
storeDir,
timeout: opts.fetchTimeout,
}) as unknown as ResolveFunction
const pkgsToPublish = await pFilter(pkgs, async (pkg) => {

View File

@@ -38,7 +38,7 @@ export const DEFAULT_OPTS = {
registries: { default: REGISTRY },
registry: REGISTRY,
sort: true,
storeDir: '../store',
cacheDir: '../cache',
strictSsl: false,
userAgent: 'pnpm',
useRunningStoreServer: false,

View File

@@ -15,6 +15,7 @@ const pnpmBin = path.join(__dirname, '../../pnpm/bin/pnpm.cjs')
test('rebuilds dependencies', async () => {
const project = prepareEmpty()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [
@@ -38,6 +39,7 @@ test('rebuilds dependencies', async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: false,
storeDir,
@@ -69,6 +71,7 @@ test('rebuilds dependencies', async () => {
test('rebuild does not fail when a linked package is present', async () => {
prepareEmpty()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await copyFixture('local-pkg', path.resolve('..', 'local-pkg'))
@@ -86,6 +89,7 @@ test('rebuild does not fail when a linked package is present', async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: false,
storeDir,
@@ -96,6 +100,7 @@ test('rebuild does not fail when a linked package is present', async () => {
test('rebuilds specific dependencies', async () => {
const project = prepareEmpty()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [
pnpmBin,
@@ -112,6 +117,7 @@ test('rebuilds specific dependencies', async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: false,
storeDir,
@@ -129,6 +135,7 @@ test('rebuilds specific dependencies', async () => {
test('rebuild with pending option', async () => {
const project = prepareEmpty()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [
pnpmBin,
@@ -165,6 +172,7 @@ test('rebuild with pending option', async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: true,
storeDir,
@@ -193,6 +201,7 @@ test('rebuild with pending option', async () => {
test('rebuild dependencies in correct order', async () => {
const project = prepareEmpty()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [
@@ -215,6 +224,7 @@ test('rebuild dependencies in correct order', async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: false,
storeDir,
@@ -229,6 +239,7 @@ test('rebuild dependencies in correct order', async () => {
test('rebuild links bins', async () => {
const project = prepareEmpty()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [
@@ -252,6 +263,7 @@ test('rebuild links bins', async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: true,
storeDir,
@@ -272,6 +284,7 @@ test(`rebuild should not fail on incomplete ${WANTED_LOCKFILE}`, async () => {
'not-compatible-with-any-os': '1.0.0',
},
})
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [
@@ -288,6 +301,7 @@ test(`rebuild should not fail on incomplete ${WANTED_LOCKFILE}`, async () => {
await rebuild.handler({
...DEFAULT_OPTS,
cacheDir,
dir: process.cwd(),
pending: true,
reporter,

View File

@@ -9,6 +9,7 @@ export const DEFAULT_OPTS = {
},
bail: false,
ca: undefined,
cacheDir: '../cache',
cert: undefined,
cliOptions: {},
fetchRetries: 2,

View File

@@ -7,6 +7,7 @@ export const DEFAULT_OPTS = {
},
bail: false,
ca: undefined,
cacheDir: '../cache',
cert: undefined,
cliOptions: {},
extraBinPaths: [],

View File

@@ -10,9 +10,11 @@ const STORE_VERSION = 'v3'
test('pnpm store add express@4.16.3', async () => {
tempDir()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: `http://localhost:${REGISTRY_MOCK_PORT}/`,
@@ -28,9 +30,11 @@ test('pnpm store add express@4.16.3', async () => {
test('pnpm store add scoped package that uses not the standard registry', async () => {
tempDir()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: 'https://registry.npmjs.org/',
@@ -50,11 +54,13 @@ test('should fail if some packages can not be added', async () => {
tempDir()
fs.mkdirSync('_')
process.chdir('_')
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('pnpm-store')
let thrown = false
try {
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: 'https://registry.npmjs.org/',

View File

@@ -1,4 +1,5 @@
import os from 'os'
import path from 'path'
import { store } from '@pnpm/plugin-commands-store'
import prepare from '@pnpm/prepare'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
@@ -9,6 +10,7 @@ test('CLI prints the current store path', async () => {
prepare()
const candidateStorePath = await store.handler({
cacheDir: path.resolve('cache'),
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,

View File

@@ -17,6 +17,7 @@ const pnpmBin = path.join(__dirname, '../../pnpm/bin/pnpm.cjs')
test('remove unreferenced packages', async () => {
const project = prepare()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [pnpmBin, 'add', 'is-negative@2.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
@@ -26,6 +27,7 @@ test('remove unreferenced packages', async () => {
const reporter = sinon.spy()
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,
@@ -44,6 +46,7 @@ test('remove unreferenced packages', async () => {
reporter.resetHistory()
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,
@@ -61,6 +64,7 @@ test('remove unreferenced packages', async () => {
test.skip('remove packages that are used by project that no longer exist', async () => {
prepare()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store', STORE_VERSION)
const { cafsHas, cafsHasNot } = assertStore(storeDir)
@@ -72,6 +76,7 @@ test.skip('remove packages that are used by project that no longer exist', async
const reporter = sinon.spy()
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,
@@ -91,6 +96,7 @@ test.skip('remove packages that are used by project that no longer exist', async
test('keep dependencies used by others', async () => {
const project = prepare()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [pnpmBin, 'add', 'camelcase-keys@3.0.0', '--store-dir', storeDir, '--registry', REGISTRY])
await execa('node', [pnpmBin, 'add', 'hastscript@3.0.0', '--save-dev', '--store-dir', storeDir, '--registry', REGISTRY])
@@ -111,6 +117,7 @@ test('keep dependencies used by others', async () => {
Object.entries(lockfile.packages ?? {}).forEach(([depPath, dep]) => expect(dep.dev).toBeTruthy())
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,
@@ -126,11 +133,13 @@ test('keep dependencies used by others', async () => {
test('keep dependency used by package', async () => {
const project = prepare()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [pnpmBin, 'add', 'is-not-positive@1.0.0', 'is-positive@3.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
await execa('node', [pnpmBin, 'remove', 'is-not-positive', '--store-dir', storeDir], { env: { npm_config_registry: REGISTRY } })
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,
@@ -144,11 +153,13 @@ test('keep dependency used by package', async () => {
test('prune will skip scanning non-directory in storeDir', async () => {
prepare()
const cacheDir = path.resolve('cache')
const storeDir = path.resolve('store')
await execa('node', [pnpmBin, 'add', 'is-not-positive@1.0.0', 'is-positive@3.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
fs.writeFileSync(path.join(storeDir, STORE_VERSION, 'files/.DS_store'), 'foobar')
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,

View File

@@ -12,7 +12,9 @@ const pnpmBin = path.join(__dirname, '../../pnpm/bin/pnpm.cjs')
test('CLI fails when store status finds modified packages', async () => {
prepare()
const storeDir = tempy.directory()
const tmp = tempy.directory()
const cacheDir = path.join(tmp, 'cache')
const storeDir = path.join(tmp, 'store')
await execa('node', [pnpmBin, 'add', 'is-positive@3.1.0', '--store-dir', storeDir, '--registry', REGISTRY, '--verify-store-integrity'])
@@ -21,6 +23,7 @@ test('CLI fails when store status finds modified packages', async () => {
let err!: PnpmError
try {
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,
@@ -38,7 +41,9 @@ test('CLI fails when store status finds modified packages', async () => {
test('CLI does not fail when store status does not find modified packages', async () => {
prepare()
const storeDir = tempy.directory()
const tmp = tempy.directory()
const cacheDir = path.join(tmp, 'cache')
const storeDir = path.join(tmp, 'store')
await execa('node', [
pnpmBin,
@@ -58,6 +63,7 @@ test('CLI does not fail when store status does not find modified packages', asyn
await execa('node', [pnpmBin, 'add', 'not-compatible-with-any-os', '--save-optional', '--store-dir', storeDir, '--registry', REGISTRY, '--verify-store-integrity'])
await store.handler({
cacheDir,
dir: process.cwd(),
rawConfig: {
registry: REGISTRY,

View File

@@ -4,7 +4,6 @@ import packageManager from '@pnpm/cli-meta'
import { Config } from '@pnpm/config'
import { createResolver } from '@pnpm/client'
import pickRegistryForPackage from '@pnpm/pick-registry-for-package'
import storePath from '@pnpm/store-path'
import { updateCheckLogger } from '@pnpm/core-loggers'
import loadJsonFile from 'load-json-file'
import writeJsonFile from 'write-json-file'
@@ -27,14 +26,12 @@ export default async function (config: Config) {
(Date.now() - new Date(state.lastUpdateCheck).valueOf()) < UPDATE_CHECK_FREQUENCY
) return
const storeDir = await storePath(config.dir, config.storeDir)
const resolve = createResolver({
...config,
authConfig: config.rawConfig,
retry: {
retries: 0,
},
storeDir,
})
const resolution = await resolve({ alias: packageManager.name, pref: 'latest' }, {
lockfileDir: config.lockfileDir ?? config.dir,

View File

@@ -13,13 +13,14 @@ import isPortReachable from 'is-port-reachable'
const registry = 'https://registry.npmjs.org/'
async function createStoreController (storeDir?: string) {
const tmp = tempy.directory()
if (!storeDir) {
storeDir = tempy.directory()
storeDir = path.join(tmp, 'store')
}
const authConfig = { registry }
const { resolve, fetchers } = createClient({
authConfig,
storeDir,
cacheDir: path.join(tmp, 'cache'),
})
return createStore(resolve, fetchers, {
networkConcurrency: 1,

View File

@@ -12,7 +12,7 @@ type CreateResolverOptions = Pick<Config,
| 'offline'
| 'rawConfig'
| 'verifyStoreIntegrity'
> & Required<Pick<Config, 'storeDir'>>
> & Required<Pick<Config, 'cacheDir' | 'storeDir'>>
export type CreateNewStoreControllerOptions = CreateResolverOptions & Pick<Config,
| 'ca'
@@ -41,6 +41,7 @@ export default async (
const { resolve, fetchers } = createClient({
authConfig: opts.rawConfig,
ca: opts.ca,
cacheDir: opts.cacheDir,
cert: opts.cert,
fullMetadata: false,
httpProxy: opts.httpProxy,
@@ -56,7 +57,6 @@ export default async (
minTimeout: opts.fetchRetryMintimeout,
retries: opts.fetchRetries,
},
storeDir: opts.storeDir,
strictSsl: opts.strictSsl ?? true,
timeout: opts.fetchTimeout,
userAgent: opts.userAgent,

View File

@@ -20,9 +20,9 @@ test('install with lockfileOnly = true', async () => {
const { cafsHas } = assertStore(opts.storeDir)
await cafsHas('pkg-with-1-dep', '100.0.0')
expect(await exists(path.join(opts.storeDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/pkg-with-1-dep.json`))).toBeTruthy()
expect(await exists(path.join(opts.cacheDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/pkg-with-1-dep.json`))).toBeTruthy()
await cafsHas('dep-of-pkg-with-1-dep', '100.1.0')
expect(await exists(path.join(opts.storeDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/dep-of-pkg-with-1-dep.json`))).toBeTruthy()
expect(await exists(path.join(opts.cacheDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/dep-of-pkg-with-1-dep.json`))).toBeTruthy()
await project.hasNot('pkg-with-1-dep')
expect(manifest.dependencies!['pkg-with-1-dep']).toBeTruthy()
@@ -39,9 +39,9 @@ test('install with lockfileOnly = true', async () => {
await install(manifest, opts)
await cafsHas('pkg-with-1-dep', '100.0.0')
expect(await exists(path.join(opts.storeDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/pkg-with-1-dep.json`))).toBeTruthy()
expect(await exists(path.join(opts.cacheDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/pkg-with-1-dep.json`))).toBeTruthy()
await cafsHas('dep-of-pkg-with-1-dep', '100.1.0')
expect(await exists(path.join(opts.storeDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/dep-of-pkg-with-1-dep.json`))).toBeTruthy()
expect(await exists(path.join(opts.cacheDir, `metadata/localhost+${REGISTRY_MOCK_PORT}/dep-of-pkg-with-1-dep.json`))).toBeTruthy()
await project.hasNot('pkg-with-1-dep')
expect(await project.readCurrentLockfile()).toBeFalsy()

View File

@@ -28,22 +28,24 @@ export default async function testDefaults<T> (
): Promise<
InstallOptions &
{
cacheDir: string
registries: Registries
storeController: StoreController
storeDir: string
} &
T
> {
let storeDir = opts?.storeDir ?? path.resolve('.store')
storeDir = await storePath(opts?.prefix ?? process.cwd(), storeDir)
const authConfig = { registry }
const cacheDir = path.resolve('cache')
const { resolve, fetchers } = createClient({
authConfig,
retry: retryOpts,
storeDir,
cacheDir,
...resolveOpts,
...fetchOpts,
})
let storeDir = opts?.storeDir ?? path.resolve('.store')
storeDir = await storePath(opts?.prefix ?? process.cwd(), storeDir)
const storeController = await createStore(
resolve,
fetchers,
@@ -55,6 +57,7 @@ export default async function testDefaults<T> (
}
)
const result = {
cacheDir,
registries: {
default: registry,
},
@@ -64,6 +67,7 @@ export default async function testDefaults<T> (
} as (
InstallOptions &
{
cacheDir: string
registries: Registries
storeController: StoreController
storeDir: string

4
pnpm-lock.yaml generated
View File

@@ -1473,7 +1473,6 @@ importers:
'@pnpm/modules-yaml': workspace:9.0.3
'@pnpm/outdated': 'link:'
'@pnpm/pick-registry-for-package': workspace:2.0.3
'@pnpm/store-path': ^5.0.0
'@pnpm/types': workspace:7.3.0
'@types/ramda': 0.27.39
'@types/semver': ^7.3.4
@@ -1491,7 +1490,6 @@ importers:
'@pnpm/matcher': link:../matcher
'@pnpm/modules-yaml': link:../modules-yaml
'@pnpm/pick-registry-for-package': link:../pick-registry-for-package
'@pnpm/store-path': 5.0.0
'@pnpm/types': link:../types
dependency-path: link:../dependency-path
ramda: 0.27.1
@@ -2063,7 +2061,6 @@ importers:
'@pnpm/resolver-base': workspace:8.0.3
'@pnpm/run-npm': workspace:3.1.0
'@pnpm/sort-packages': workspace:2.1.0
'@pnpm/store-path': ^5.0.0
'@pnpm/types': workspace:7.3.0
'@types/cross-spawn': ^6.0.2
'@types/proxyquire': ^1.3.28
@@ -2097,7 +2094,6 @@ importers:
'@pnpm/resolver-base': link:../resolver-base
'@pnpm/run-npm': link:../run-npm
'@pnpm/sort-packages': link:../sort-packages
'@pnpm/store-path': 5.0.0
'@pnpm/types': link:../types
'@zkochan/rimraf': 2.1.1
cp-file: 9.1.0