@vltpkg/package-info
Advanced tools
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import type { PickManifestOptions } from '@vltpkg/pick-manifest'; | ||
| import type { RegistryClientOptions, RegistryClientRequestOptions } from '@vltpkg/registry-client'; | ||
| import { RegistryClient } from '@vltpkg/registry-client'; | ||
| import type { SpecOptions } from '@vltpkg/spec'; | ||
| import { Spec } from '@vltpkg/spec'; | ||
| import { Pool } from '@vltpkg/tar'; | ||
| import type { Integrity, Manifest, Packument } from '@vltpkg/types'; | ||
| import { Monorepo } from '@vltpkg/workspaces'; | ||
| export declare const delimiter = "\u00B7"; | ||
| export type Resolution = { | ||
| resolved: string; | ||
| integrity?: Integrity; | ||
| signatures?: Exclude<Manifest['dist'], undefined>['signatures']; | ||
| spec: Spec; | ||
| }; | ||
| export type PackageInfoClientOptions = RegistryClientOptions & SpecOptions & { | ||
| /** root of the project. Defaults to process.cwd() */ | ||
| projectRoot?: string; | ||
| /** PackageJson object */ | ||
| packageJson?: PackageJson; | ||
| monorepo?: Monorepo; | ||
| /** workspace groups to load, irrelevant if Monorepo provided */ | ||
| 'workspace-group'?: string[]; | ||
| /** workspace paths to load, irrelevant if Monorepo provided */ | ||
| workspace?: string[]; | ||
| }; | ||
| export type PackageInfoClientRequestOptions = PickManifestOptions & RegistryClientRequestOptions & { | ||
| /** dir to resolve `file://` specifiers against. Defaults to projectRoot. */ | ||
| from?: string; | ||
| }; | ||
| export type PackageInfoClientExtractOptions = PackageInfoClientRequestOptions & { | ||
| integrity?: Integrity; | ||
| resolved?: string; | ||
| }; | ||
| export declare class PackageInfoClient { | ||
| #private; | ||
| options: PackageInfoClientOptions; | ||
| packageJson: PackageJson; | ||
| monorepo?: Monorepo; | ||
| get registryClient(): RegistryClient; | ||
| get tarPool(): Pool; | ||
| constructor(options?: PackageInfoClientOptions); | ||
| extract(spec: Spec | string, target: string, options?: PackageInfoClientExtractOptions): Promise<Resolution>; | ||
| /** | ||
| * Conditionally return the path to the manifest cache file. The logic | ||
| * to determine if caching should be skipped aligns with `pickManifest` | ||
| * and is used to avoid caching manifest results that can be variable. | ||
| */ | ||
| _manifestCachePath(spec: Spec, options: PackageInfoClientRequestOptions): string | undefined; | ||
| tarball(spec: Spec | string, options?: PackageInfoClientExtractOptions): Promise<Buffer>; | ||
| manifest(spec: Spec | string, options?: PackageInfoClientRequestOptions): Promise<Manifest | import("@vltpkg/types").Override<Manifest, import("@vltpkg/types").NormalizedFields>>; | ||
| packument(spec: Spec | string, options?: PackageInfoClientRequestOptions): Promise<Packument>; | ||
| resolve(spec: Spec | string, options?: PackageInfoClientRequestOptions): Promise<Resolution>; | ||
| } | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,OAAO,KAAK,EACV,qBAAqB,EACrB,4BAA4B,EAC7B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EAEV,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAsB7C,eAAO,MAAM,SAAS,WAAM,CAAA;AAE5B,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,YAAY,CAAC,CAAA;IAC/D,IAAI,EAAE,IAAI,CAAA;CACX,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,GAC1D,WAAW,GAAG;IACZ,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yBAAyB;IACzB,WAAW,CAAC,EAAE,WAAW,CAAA;IAEzB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAEnB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE5B,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAEH,MAAM,MAAM,+BAA+B,GAAG,mBAAmB,GAC/D,4BAA4B,GAAG;IAC7B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAEH,MAAM,MAAM,+BAA+B,GACzC,+BAA+B,GAAG;IAChC,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAKH,qBAAa,iBAAiB;;IAI5B,OAAO,EAAE,wBAAwB,CAAA;IAEjC,WAAW,EAAE,WAAW,CAAA;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAKnB,IAAI,cAAc,mBAKjB;IAED,IAAI,OAAO,SAGV;gBAEW,OAAO,GAAE,wBAA6B;IAuB5C,OAAO,CACX,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,UAAU,CAAC;IAmOtB;;;;OAIG;IACH,kBAAkB,CAChB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACvC,MAAM,GAAG,SAAS;IAwDf,OAAO,CACX,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,MAAM,CAAC;IAsIZ,QAAQ,CACZ,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC;IAwLzC,SAAS,CACb,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,SAAS,CAAC;IA8Df,OAAO,CACX,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,UAAU,CAAC;CAsJvB"} |
+666
| import { error } from '@vltpkg/error-cause'; | ||
| import { clone, resolve as gitResolve, revs } from '@vltpkg/git'; | ||
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import { pickManifest } from '@vltpkg/pick-manifest'; | ||
| import { RegistryClient } from '@vltpkg/registry-client'; | ||
| import { Spec } from '@vltpkg/spec'; | ||
| import { Pool } from '@vltpkg/tar'; | ||
| import { asPackument, isIntegrity } from '@vltpkg/types'; | ||
| import ssri from 'ssri'; | ||
| import { Monorepo } from '@vltpkg/workspaces'; | ||
| import { XDG } from '@vltpkg/xdg'; | ||
| import { randomBytes } from 'node:crypto'; | ||
| import { mkdir, readFile, rm, stat, symlink, unlink, writeFile, } from 'node:fs/promises'; | ||
| import { basename, dirname, resolve as pathResolve, relative, } from 'node:path'; | ||
| import { create as tarC } from 'tar'; | ||
| import { rename } from "./rename.js"; | ||
| const xdg = new XDG('vlt'); | ||
| export const delimiter = '·'; | ||
| // the maximum duration of a manifest cache file | ||
| const manifestCacheMaxAge = 5 * 60 * 1000; | ||
| export class PackageInfoClient { | ||
| #registryClient; | ||
| #projectRoot; | ||
| #tarPool; | ||
| options; | ||
| #resolutions = new Map(); | ||
| packageJson; | ||
| monorepo; | ||
| #trustedIntegrities = new Map(); | ||
| #manifestCacheMinAge = Date.now() - manifestCacheMaxAge; | ||
| #cachePath; | ||
| get registryClient() { | ||
| if (!this.#registryClient) { | ||
| this.#registryClient = new RegistryClient(this.options); | ||
| } | ||
| return this.#registryClient; | ||
| } | ||
| get tarPool() { | ||
| if (!this.#tarPool) | ||
| this.#tarPool = new Pool(); | ||
| return this.#tarPool; | ||
| } | ||
| constructor(options = {}) { | ||
| this.options = options; | ||
| this.#projectRoot = options.projectRoot || process.cwd(); | ||
| this.packageJson = options.packageJson ?? new PackageJson(); | ||
| const wsLoad = { | ||
| ...(options.workspace?.length && { paths: options.workspace }), | ||
| ...(options['workspace-group']?.length && { | ||
| groups: options['workspace-group'], | ||
| }), | ||
| }; | ||
| this.monorepo = | ||
| options.monorepo ?? | ||
| Monorepo.maybeLoad(this.#projectRoot, { | ||
| load: wsLoad, | ||
| packageJson: this.packageJson, | ||
| }); | ||
| this.#cachePath = options.cache ?? xdg.cache(); | ||
| // optionally create its cache directory if it doesn't exist | ||
| void mkdir(pathResolve(this.#cachePath, 'package-info'), { | ||
| recursive: true, | ||
| }).catch(() => { }); | ||
| } | ||
| async extract(spec, target, options = {}) { | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const { from = this.#projectRoot, integrity, resolved } = options; | ||
| const f = spec.final; | ||
| const r = integrity && resolved ? | ||
| { resolved, integrity, spec } | ||
| : await this.resolve(spec, options); | ||
| switch (f.type) { | ||
| case 'git': { | ||
| const { gitRemote, gitCommittish, remoteURL, gitSelectorParsed, } = f; | ||
| if (!remoteURL) { | ||
| /* c8 ignore start - Impossible, would throw on the resolve */ | ||
| if (!gitRemote) | ||
| throw this.#resolveError(spec, options, 'no remote on git: specifier'); | ||
| /* c8 ignore stop */ | ||
| const { path } = gitSelectorParsed ?? {}; | ||
| if (path !== undefined) { | ||
| // use obvious name because it's in node_modules | ||
| const tmp = pathResolve(dirname(target), `.TEMP.${basename(target)}-${randomBytes(6).toString('hex')}`); | ||
| await clone(gitRemote, gitCommittish, tmp, { spec }); | ||
| const src = pathResolve(tmp, path); | ||
| await rename(src, target); | ||
| // intentionally not awaited | ||
| void rm(tmp, { recursive: true, force: true }); | ||
| } | ||
| else { | ||
| await clone(gitRemote, gitCommittish, target, { spec }); | ||
| // intentionally not awaited | ||
| void rm(target + '/.git', { recursive: true }); | ||
| } | ||
| return r; | ||
| } | ||
| // fallthrough if a remote tarball url present | ||
| } | ||
| case 'registry': { | ||
| const trustIntegrity = this.#trustedIntegrities.get(r.resolved) === r.integrity; | ||
| const response = await this.registryClient.request(r.resolved, { | ||
| integrity: r.integrity, | ||
| trustIntegrity, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch tarball', { | ||
| url: r.resolved, | ||
| response, | ||
| }); | ||
| } | ||
| // if it's not trusted already, but valid, start trusting | ||
| if (!trustIntegrity && | ||
| response.checkIntegrity({ spec, url: resolved })) { | ||
| this.#trustedIntegrities.set(r.resolved, response.integrity); | ||
| } | ||
| try { | ||
| await this.tarPool.unpack(response.buffer(), target); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(spec, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| return r; | ||
| } | ||
| case 'remote': { | ||
| const response = await this.registryClient.request(r.resolved); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch remote tarball', { | ||
| url: r.resolved, | ||
| response, | ||
| }); | ||
| } | ||
| const buf = response.buffer(); | ||
| // Compute integrity for remote/git-with-tarball deps | ||
| const computed = ssri | ||
| .fromData(buf, { algorithms: ['sha512'] }) | ||
| .toString(); | ||
| if (r.integrity && r.integrity !== computed) { | ||
| throw error('Integrity check failure', { | ||
| code: 'EINTEGRITY', | ||
| spec, | ||
| url: r.resolved, | ||
| wanted: r.integrity, | ||
| found: computed, | ||
| }); | ||
| } | ||
| r.integrity = computed; | ||
| try { | ||
| await this.tarPool.unpack(buf, target); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(spec, options, 'remote tar unpack failed', { cause: er }); | ||
| } | ||
| return r; | ||
| } | ||
| case 'file': { | ||
| // if it's a directory, then "extract" means "symlink" | ||
| const { file } = f; | ||
| /* c8 ignore start - asserted in resolve() */ | ||
| if (file === undefined) | ||
| throw this.#resolveError(spec, options, 'no file path'); | ||
| /* c8 ignore stop */ | ||
| const path = pathResolve(from, file); | ||
| const st = await stat(path); | ||
| if (st.isFile()) { | ||
| try { | ||
| await this.tarPool.unpack(await this.tarball(spec, options), target); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(spec, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| } | ||
| else if (st.isDirectory()) { | ||
| const rel = relative(dirname(target), path); | ||
| await symlink(rel, target, 'dir'); | ||
| /* c8 ignore start */ | ||
| } | ||
| else { | ||
| throw this.#resolveError(spec, options, 'file: specifier does not resolve to directory or tarball'); | ||
| } | ||
| /* c8 ignore stop */ | ||
| return r; | ||
| } | ||
| case 'workspace': { | ||
| const ws = this.#getWS(spec, options); | ||
| const rel = relative(dirname(target), ws.fullpath); | ||
| await symlink(rel, target, 'dir'); | ||
| return r; | ||
| } | ||
| } | ||
| } | ||
| #getWS(spec, options) { | ||
| const { workspace } = spec; | ||
| /* c8 ignore start - asserted in resolve() */ | ||
| if (workspace === undefined) | ||
| throw this.#resolveError(spec, options, 'no workspace ID'); | ||
| /* c8 ignore stop */ | ||
| if (!this.monorepo) { | ||
| throw this.#resolveError(spec, options, 'Not in a monorepo, cannot resolve workspace spec'); | ||
| } | ||
| const ws = this.monorepo.get(workspace); | ||
| if (!ws) { | ||
| throw this.#resolveError(spec, options, 'workspace not found', { | ||
| wanted: workspace, | ||
| }); | ||
| } | ||
| return ws; | ||
| } | ||
| /** | ||
| * Return the manifest cache key for a spec and the current options. | ||
| */ | ||
| #manifestCacheKey(spec, options) { | ||
| let extra = ''; | ||
| if (options['node-version']) { | ||
| extra += `${delimiter}node-version:${options['node-version']}`; | ||
| } | ||
| if (options.os) { | ||
| extra += `${delimiter}os:${options.os}`; | ||
| } | ||
| if (options.arch) { | ||
| extra += `${delimiter}arch:${options.arch}`; | ||
| } | ||
| return encodeURIComponent(`${spec.registry}${delimiter}${spec}${extra}`); | ||
| } | ||
| /** | ||
| * Conditionally return the path to the manifest cache file. The logic | ||
| * to determine if caching should be skipped aligns with `pickManifest` | ||
| * and is used to avoid caching manifest results that can be variable. | ||
| */ | ||
| _manifestCachePath(spec, options) { | ||
| if (options.before) { | ||
| return; | ||
| } | ||
| // if the final resolved spec is either a dist tag or something that | ||
| // matches any range (such as a semver range of `*` or empty string) | ||
| // then we skip caching | ||
| const f = spec.final; | ||
| if (f.distTag || f.range?.isAny) { | ||
| return; | ||
| } | ||
| const key = this.#manifestCacheKey(f, options); | ||
| return pathResolve(this.#cachePath, 'package-info', key); | ||
| } | ||
| async #registryManifestRequest(spec, options) { | ||
| const { registry, name, registrySpec } = spec.final; | ||
| /* c8 ignore start */ | ||
| if (!spec.range?.isSingle || !registrySpec) { | ||
| throw this.#resolveError(spec, options, 'failed to request manifest', { spec }); | ||
| } | ||
| /* c8 ignore stop */ | ||
| const possibleLeadingChars = ['=', '^', '~', 'v']; | ||
| const hasLeadingRange = possibleLeadingChars.some(char => registrySpec.startsWith(char)); | ||
| const version = hasLeadingRange ? registrySpec.slice(1) : registrySpec; | ||
| const pakuURL = new URL(`${name}/${version}`, registry); | ||
| const response = await this.registryClient.request(pakuURL, { | ||
| headers: { | ||
| accept: 'application/json', | ||
| }, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch manifest', { | ||
| url: pakuURL, | ||
| response, | ||
| }); | ||
| } | ||
| return response.json(); | ||
| } | ||
| async tarball(spec, options = {}) { | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| case 'registry': { | ||
| const { dist } = await this.manifest(spec, options); | ||
| if (!dist) | ||
| throw this.#resolveError(spec, options, 'no dist object found in manifest'); | ||
| const { tarball, integrity } = dist; | ||
| if (!tarball) { | ||
| throw this.#resolveError(spec, options, 'no tarball found in manifest.dist'); | ||
| } | ||
| const trustIntegrity = this.#trustedIntegrities.get(tarball) === integrity; | ||
| const response = await this.registryClient.request(tarball, { | ||
| ...options, | ||
| integrity, | ||
| trustIntegrity, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch tarball', { response, url: tarball }); | ||
| } | ||
| // if we don't already trust it, but it's valid, start trusting it | ||
| if (!trustIntegrity && | ||
| response.checkIntegrity({ spec, url: tarball })) { | ||
| this.#trustedIntegrities.set(tarball, response.integrity); | ||
| } | ||
| return response.buffer(); | ||
| } | ||
| case 'git': { | ||
| const { remoteURL, gitRemote, gitCommittish, gitSelectorParsed, } = f; | ||
| const s = spec; | ||
| if (!remoteURL) { | ||
| if (!gitRemote) { | ||
| throw this.#resolveError(spec, options, 'no remote on git: specifier'); | ||
| } | ||
| const { path } = gitSelectorParsed ?? {}; | ||
| return await this.#tmpdir(async (dir) => { | ||
| await clone(gitRemote, gitCommittish, dir + '/package', { | ||
| spec: s, | ||
| }); | ||
| let cwd = dir; | ||
| if (path !== undefined) { | ||
| const src = pathResolve(dir, 'package', path); | ||
| cwd = dirname(src); | ||
| const pkg = pathResolve(cwd, 'package'); | ||
| if (src !== pkg) { | ||
| const rand = randomBytes(6).toString('hex'); | ||
| // faster than deleting | ||
| await rename(pkg, pkg + rand).catch(() => { }); | ||
| await rename(src, pkg); | ||
| } | ||
| } | ||
| return tarC({ cwd, gzip: true }, ['package']).concat(); | ||
| }); | ||
| } | ||
| // fallthrough if remoteURL set | ||
| } | ||
| case 'remote': { | ||
| const { remoteURL } = f; | ||
| if (!remoteURL) { | ||
| throw this.#resolveError(spec, options); | ||
| } | ||
| const response = await this.registryClient.request(remoteURL); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch URL', { response, url: remoteURL }); | ||
| } | ||
| return response.buffer(); | ||
| } | ||
| case 'file': { | ||
| const { file } = f; | ||
| if (file === undefined) | ||
| throw this.#resolveError(spec, options, 'no file path'); | ||
| const { from = this.#projectRoot } = options; | ||
| const path = pathResolve(from, file); | ||
| const st = await stat(path); | ||
| if (st.isDirectory()) { | ||
| const p = dirname(path); | ||
| const b = basename(path); | ||
| // TODO: Pack properly, ignore stuff, bundleDeps, etc | ||
| return tarC({ cwd: p, gzip: true }, [b]).concat(); | ||
| } | ||
| return readFile(path); | ||
| } | ||
| case 'workspace': { | ||
| // TODO: Pack properly, ignore stuff, bundleDeps, etc | ||
| const ws = this.#getWS(spec, options); | ||
| const p = dirname(ws.fullpath); | ||
| const b = basename(ws.fullpath); | ||
| return tarC({ cwd: p, gzip: true }, [b]).concat(); | ||
| } | ||
| } | ||
| } | ||
| async manifest(spec, options = {}) { | ||
| const { from = this.#projectRoot } = options; | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| case 'registry': { | ||
| // Check if manifest is cached, if so just return it earlier | ||
| const cachePath = this._manifestCachePath(spec, options); | ||
| if (cachePath) { | ||
| try { | ||
| // Cache file exists, read and return it | ||
| const cached = await readFile(cachePath, 'utf8'); | ||
| const json = JSON.parse(cached); | ||
| // retrieve timestamp to check if cache is still valid | ||
| const timestamp = json.__VLT_MANIFEST_CACHE_TIMESTAMP; | ||
| delete json.__VLT_MANIFEST_CACHE_TIMESTAMP; | ||
| // removes the cache file if older than its maximum age | ||
| if (timestamp != null && | ||
| timestamp < this.#manifestCacheMinAge) { | ||
| void unlink(cachePath).catch(() => { }); | ||
| throw new Error('manifest cache expired'); | ||
| } | ||
| return json; | ||
| } | ||
| catch { | ||
| // Cache miss, fetch from packument | ||
| } | ||
| } | ||
| const mani = spec.range?.isSingle ? | ||
| await this.#registryManifestRequest(spec, options) | ||
| : pickManifest(await this.packument(f, options), spec, options); | ||
| if (!mani) | ||
| throw this.#resolveError(spec, options); | ||
| const { integrity, tarball } = mani.dist ?? /* c8 ignore next */ {}; | ||
| if (isIntegrity(integrity) && tarball) { | ||
| const registryOrigin = new URL(String(f.registry)).origin; | ||
| const tgzOrigin = new URL(tarball).origin; | ||
| // if it comes from the same origin, trust the integrity | ||
| if (tgzOrigin === registryOrigin) { | ||
| this.#trustedIntegrities.set(tarball, integrity); | ||
| } | ||
| } | ||
| // Cache the manifest data | ||
| if (cachePath) { | ||
| const json = JSON.stringify({ | ||
| ...mani, | ||
| // append a timestamp to the manifest so that we can quickly | ||
| // check if the cache is still valid when loading it | ||
| __VLT_MANIFEST_CACHE_TIMESTAMP: Date.now(), | ||
| }); | ||
| void writeFile(cachePath, json, 'utf8').catch((err) => { | ||
| // in case the cache directory doesn't exist | ||
| // just create it and retry | ||
| if (err instanceof Error && | ||
| 'code' in err && | ||
| err.code === 'ENOENT') { | ||
| void mkdir(dirname(cachePath), { | ||
| recursive: true, | ||
| }).then(() => { | ||
| void writeFile(cachePath, json, 'utf8'); | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| return mani; | ||
| } | ||
| case 'git': { | ||
| const { gitRemote, gitCommittish, remoteURL, gitSelectorParsed, } = f; | ||
| if (!remoteURL) { | ||
| const s = spec; | ||
| if (!gitRemote) | ||
| throw this.#resolveError(spec, options, 'no git remote'); | ||
| return await this.#tmpdir(async (dir) => { | ||
| await clone(gitRemote, gitCommittish, dir, { spec: s }); | ||
| const { path } = gitSelectorParsed ?? {}; | ||
| const pkgDir = path !== undefined ? pathResolve(dir, path) : dir; | ||
| return this.packageJson.read(pkgDir); | ||
| }); | ||
| } | ||
| // fallthrough to remote | ||
| } | ||
| case 'remote': { | ||
| const { remoteURL } = f; | ||
| if (!remoteURL) { | ||
| throw this.#resolveError(spec, options, 'no remoteURL on remote specifier'); | ||
| } | ||
| const s = spec; | ||
| return await this.#tmpdir(async (dir) => { | ||
| const response = await this.registryClient.request(remoteURL); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(s, options, 'failed to fetch URL', { response, url: remoteURL }); | ||
| } | ||
| const buf = response.buffer(); | ||
| // Compute integrity for remote/git-with-tarball deps | ||
| const computed = ssri | ||
| .fromData(buf, { algorithms: ['sha512'] }) | ||
| .toString(); | ||
| try { | ||
| await this.tarPool.unpack(buf, dir); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(s, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| // return manifest with computed integrity | ||
| const mani = this.packageJson.read(dir); | ||
| mani.dist = { integrity: computed }; | ||
| return mani; | ||
| }); | ||
| } | ||
| case 'file': { | ||
| const { file } = f; | ||
| if (file === undefined) | ||
| throw this.#resolveError(spec, options, 'no file path'); | ||
| const path = pathResolve(from, file); | ||
| const st = await stat(path); | ||
| if (st.isDirectory()) { | ||
| return this.packageJson.read(path); | ||
| } | ||
| const s = spec; | ||
| return await this.#tmpdir(async (dir) => { | ||
| try { | ||
| await this.tarPool.unpack(await readFile(path), dir); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(s, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| return this.packageJson.read(dir); | ||
| }); | ||
| } | ||
| case 'workspace': { | ||
| return this.#getWS(spec, options).manifest; | ||
| } | ||
| } | ||
| } | ||
| async packument(spec, options = {}) { | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| // RevDoc is the equivalent of a packument for a git repo | ||
| case 'git': { | ||
| const { gitRemote } = f; | ||
| if (!gitRemote) { | ||
| throw this.#resolveError(spec, options, 'git remote could not be determined'); | ||
| } | ||
| const revDoc = await revs(gitRemote, { | ||
| cwd: this.options.projectRoot, | ||
| }); | ||
| if (!revDoc) | ||
| throw this.#resolveError(spec, options); | ||
| return asPackument(revDoc); | ||
| } | ||
| // these are all faked packuments | ||
| case 'file': | ||
| case 'workspace': | ||
| case 'remote': { | ||
| const manifest = await this.manifest(f, options); | ||
| return { | ||
| name: manifest.name ?? '', | ||
| 'dist-tags': { | ||
| latest: manifest.version ?? '', | ||
| }, | ||
| versions: { | ||
| [manifest.version ?? '']: manifest, | ||
| }, | ||
| }; | ||
| } | ||
| case 'registry': { | ||
| const { registry, name } = f; | ||
| const pakuURL = new URL(name, registry); | ||
| const response = await this.registryClient.request(pakuURL, { | ||
| headers: { | ||
| accept: 'application/json', | ||
| }, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch packument', { | ||
| url: pakuURL, | ||
| response, | ||
| }); | ||
| } | ||
| return response.json(); | ||
| } | ||
| } | ||
| } | ||
| async resolve(spec, options = {}) { | ||
| const memoKey = String(spec); | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const memo = this.#resolutions.get(memoKey); | ||
| if (memo) | ||
| return memo; | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| case 'file': { | ||
| const { file } = f; | ||
| if (!file || !f.file) { | ||
| throw this.#resolveError(spec, options, 'no path on file: specifier'); | ||
| } | ||
| const { from = this.#projectRoot } = options; | ||
| const resolved = pathResolve(from, f.file); | ||
| const r = { resolved, spec }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| case 'remote': { | ||
| const { remoteURL } = f; | ||
| if (!remoteURL) | ||
| throw this.#resolveError(spec, options, 'no URL in remote specifier'); | ||
| const r = { resolved: remoteURL, spec }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| case 'workspace': { | ||
| const ws = this.#getWS(spec, options); | ||
| return { | ||
| resolved: ws.fullpath, | ||
| spec, | ||
| }; | ||
| } | ||
| case 'registry': { | ||
| const mani = await this.manifest(spec, options); | ||
| if (mani.dist) { | ||
| const { integrity, tarball, signatures } = mani.dist; | ||
| if (tarball) { | ||
| const r = { | ||
| resolved: tarball, | ||
| integrity, | ||
| signatures, | ||
| spec, | ||
| }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| } | ||
| throw this.#resolveError(spec, options); | ||
| } | ||
| case 'git': { | ||
| const { gitRemote, remoteURL, gitSelectorParsed } = f; | ||
| if (remoteURL && gitSelectorParsed?.path === undefined) { | ||
| // known git host with a tarball download endpoint | ||
| const r = { resolved: remoteURL, spec }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| if (!gitRemote) { | ||
| throw this.#resolveError(spec, options, 'no remote on git specifier'); | ||
| } | ||
| const rev = await gitResolve(gitRemote, f.gitCommittish, { | ||
| spec, | ||
| }); | ||
| if (rev) { | ||
| const r = { | ||
| resolved: `${gitRemote}#${rev.sha}`, | ||
| spec, | ||
| }; | ||
| if (gitSelectorParsed) { | ||
| r.resolved += Object.entries(gitSelectorParsed) | ||
| .filter(([_, v]) => v) | ||
| .map(([k, v]) => `::${k}:${v}`) | ||
| .join(''); | ||
| } | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| // have to actually clone somewhere | ||
| const s = spec; | ||
| return this.#tmpdir(async (tmpdir) => { | ||
| const sha = await clone(gitRemote, s.gitCommittish, tmpdir, { | ||
| spec: s, | ||
| }); | ||
| const r = { | ||
| resolved: `${gitRemote}#${sha}`, | ||
| spec: s, | ||
| }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| async #tmpdir(fn) { | ||
| const p = `package-info/${randomBytes(6).toString('hex')}`; | ||
| const dir = xdg.runtime(p); | ||
| try { | ||
| return await fn(dir); | ||
| } | ||
| finally { | ||
| // intentionally do not await | ||
| void rm(dir, { recursive: true, force: true }); | ||
| } | ||
| } | ||
| // error resolving | ||
| #resolveError(spec, options = {}, message = 'Could not resolve', extra = {}) { | ||
| const { from = this.#projectRoot } = options; | ||
| const er = error(message, { | ||
| code: 'ERESOLVE', | ||
| spec, | ||
| from, | ||
| ...extra, | ||
| }, this.#resolveError); | ||
| return er; | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorCauseOptions } from '@vltpkg/error-cause'\nimport { error } from '@vltpkg/error-cause'\nimport { clone, resolve as gitResolve, revs } from '@vltpkg/git'\nimport { PackageJson } from '@vltpkg/package-json'\nimport type { PickManifestOptions } from '@vltpkg/pick-manifest'\nimport { pickManifest } from '@vltpkg/pick-manifest'\nimport type {\n RegistryClientOptions,\n RegistryClientRequestOptions,\n} from '@vltpkg/registry-client'\nimport { RegistryClient } from '@vltpkg/registry-client'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { Spec } from '@vltpkg/spec'\nimport { Pool } from '@vltpkg/tar'\nimport type {\n Integrity,\n Manifest,\n Packument,\n ManifestRegistry,\n} from '@vltpkg/types'\nimport { asPackument, isIntegrity } from '@vltpkg/types'\nimport ssri from 'ssri'\nimport { Monorepo } from '@vltpkg/workspaces'\nimport { XDG } from '@vltpkg/xdg'\nimport { randomBytes } from 'node:crypto'\nimport {\n mkdir,\n readFile,\n rm,\n stat,\n symlink,\n unlink,\n writeFile,\n} from 'node:fs/promises'\nimport {\n basename,\n dirname,\n resolve as pathResolve,\n relative,\n} from 'node:path'\nimport { create as tarC } from 'tar'\nimport { rename } from './rename.ts'\n\nconst xdg = new XDG('vlt')\nexport const delimiter = '·'\n\nexport type Resolution = {\n resolved: string\n integrity?: Integrity\n signatures?: Exclude<Manifest['dist'], undefined>['signatures']\n spec: Spec\n}\n\nexport type PackageInfoClientOptions = RegistryClientOptions &\n SpecOptions & {\n /** root of the project. Defaults to process.cwd() */\n projectRoot?: string\n /** PackageJson object */\n packageJson?: PackageJson\n\n monorepo?: Monorepo\n\n /** workspace groups to load, irrelevant if Monorepo provided */\n 'workspace-group'?: string[]\n\n /** workspace paths to load, irrelevant if Monorepo provided */\n workspace?: string[]\n }\n\nexport type PackageInfoClientRequestOptions = PickManifestOptions &\n RegistryClientRequestOptions & {\n /** dir to resolve `file://` specifiers against. Defaults to projectRoot. */\n from?: string\n }\n\nexport type PackageInfoClientExtractOptions =\n PackageInfoClientRequestOptions & {\n integrity?: Integrity\n resolved?: string\n }\n\n// the maximum duration of a manifest cache file\nconst manifestCacheMaxAge = 5 * 60 * 1000\n\nexport class PackageInfoClient {\n #registryClient?: RegistryClient\n #projectRoot: string\n #tarPool?: Pool\n options: PackageInfoClientOptions\n #resolutions = new Map<string, Resolution>()\n packageJson: PackageJson\n monorepo?: Monorepo\n #trustedIntegrities = new Map<string, Integrity>()\n #manifestCacheMinAge = Date.now() - manifestCacheMaxAge\n #cachePath: string\n\n get registryClient() {\n if (!this.#registryClient) {\n this.#registryClient = new RegistryClient(this.options)\n }\n return this.#registryClient\n }\n\n get tarPool() {\n if (!this.#tarPool) this.#tarPool = new Pool()\n return this.#tarPool\n }\n\n constructor(options: PackageInfoClientOptions = {}) {\n this.options = options\n this.#projectRoot = options.projectRoot || process.cwd()\n this.packageJson = options.packageJson ?? new PackageJson()\n const wsLoad = {\n ...(options.workspace?.length && { paths: options.workspace }),\n ...(options['workspace-group']?.length && {\n groups: options['workspace-group'],\n }),\n }\n this.monorepo =\n options.monorepo ??\n Monorepo.maybeLoad(this.#projectRoot, {\n load: wsLoad,\n packageJson: this.packageJson,\n })\n this.#cachePath = options.cache ?? xdg.cache()\n // optionally create its cache directory if it doesn't exist\n void mkdir(pathResolve(this.#cachePath, 'package-info'), {\n recursive: true,\n }).catch(() => {})\n }\n\n async extract(\n spec: Spec | string,\n target: string,\n options: PackageInfoClientExtractOptions = {},\n ): Promise<Resolution> {\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const { from = this.#projectRoot, integrity, resolved } = options\n const f = spec.final\n const r =\n integrity && resolved ?\n { resolved, integrity, spec }\n : await this.resolve(spec, options)\n\n switch (f.type) {\n case 'git': {\n const {\n gitRemote,\n gitCommittish,\n remoteURL,\n gitSelectorParsed,\n } = f\n if (!remoteURL) {\n /* c8 ignore start - Impossible, would throw on the resolve */\n if (!gitRemote)\n throw this.#resolveError(\n spec,\n options,\n 'no remote on git: specifier',\n )\n /* c8 ignore stop */\n const { path } = gitSelectorParsed ?? {}\n if (path !== undefined) {\n // use obvious name because it's in node_modules\n const tmp = pathResolve(\n dirname(target),\n `.TEMP.${basename(target)}-${randomBytes(6).toString('hex')}`,\n )\n await clone(gitRemote, gitCommittish, tmp, { spec })\n const src = pathResolve(tmp, path)\n await rename(src, target)\n // intentionally not awaited\n void rm(tmp, { recursive: true, force: true })\n } else {\n await clone(gitRemote, gitCommittish, target, { spec })\n // intentionally not awaited\n void rm(target + '/.git', { recursive: true })\n }\n return r\n }\n // fallthrough if a remote tarball url present\n }\n\n case 'registry': {\n const trustIntegrity =\n this.#trustedIntegrities.get(r.resolved) === r.integrity\n\n const response = await this.registryClient.request(\n r.resolved,\n {\n integrity: r.integrity,\n trustIntegrity,\n },\n )\n\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch tarball',\n {\n url: r.resolved,\n response,\n },\n )\n }\n\n // if it's not trusted already, but valid, start trusting\n if (\n !trustIntegrity &&\n response.checkIntegrity({ spec, url: resolved })\n ) {\n this.#trustedIntegrities.set(r.resolved, response.integrity)\n }\n\n try {\n await this.tarPool.unpack(response.buffer(), target)\n } catch (er) {\n throw this.#resolveError(\n spec,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n return r\n }\n\n case 'remote': {\n const response = await this.registryClient.request(r.resolved)\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch remote tarball',\n {\n url: r.resolved,\n response,\n },\n )\n }\n\n const buf = response.buffer()\n\n // Compute integrity for remote/git-with-tarball deps\n const computed = ssri\n .fromData(buf, { algorithms: ['sha512'] })\n .toString()\n if (r.integrity && r.integrity !== computed) {\n throw error('Integrity check failure', {\n code: 'EINTEGRITY',\n spec,\n url: r.resolved,\n wanted: r.integrity,\n found: computed,\n })\n }\n r.integrity = computed as Integrity\n\n try {\n await this.tarPool.unpack(buf, target)\n } catch (er) {\n throw this.#resolveError(\n spec,\n options,\n 'remote tar unpack failed',\n { cause: er },\n )\n }\n return r\n }\n case 'file': {\n // if it's a directory, then \"extract\" means \"symlink\"\n const { file } = f\n /* c8 ignore start - asserted in resolve() */\n if (file === undefined)\n throw this.#resolveError(spec, options, 'no file path')\n /* c8 ignore stop */\n const path = pathResolve(from, file)\n const st = await stat(path)\n if (st.isFile()) {\n try {\n await this.tarPool.unpack(\n await this.tarball(spec, options),\n target,\n )\n } catch (er) {\n throw this.#resolveError(\n spec,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n } else if (st.isDirectory()) {\n const rel = relative(dirname(target), path)\n await symlink(rel, target, 'dir')\n /* c8 ignore start */\n } else {\n throw this.#resolveError(\n spec,\n options,\n 'file: specifier does not resolve to directory or tarball',\n )\n }\n /* c8 ignore stop */\n return r\n }\n case 'workspace': {\n const ws = this.#getWS(spec, options)\n const rel = relative(dirname(target), ws.fullpath)\n await symlink(rel, target, 'dir')\n return r\n }\n }\n }\n\n #getWS(spec: Spec, options: PackageInfoClientRequestOptions) {\n const { workspace } = spec\n /* c8 ignore start - asserted in resolve() */\n if (workspace === undefined)\n throw this.#resolveError(spec, options, 'no workspace ID')\n /* c8 ignore stop */\n if (!this.monorepo) {\n throw this.#resolveError(\n spec,\n options,\n 'Not in a monorepo, cannot resolve workspace spec',\n )\n }\n const ws = this.monorepo.get(workspace)\n if (!ws) {\n throw this.#resolveError(spec, options, 'workspace not found', {\n wanted: workspace,\n })\n }\n return ws\n }\n\n /**\n * Return the manifest cache key for a spec and the current options.\n */\n #manifestCacheKey(\n spec: Spec,\n options: PackageInfoClientRequestOptions,\n ): string {\n let extra = ''\n if (options['node-version']) {\n extra += `${delimiter}node-version:${options['node-version']}`\n }\n if (options.os) {\n extra += `${delimiter}os:${options.os}`\n }\n if (options.arch) {\n extra += `${delimiter}arch:${options.arch}`\n }\n return encodeURIComponent(\n `${spec.registry}${delimiter}${spec}${extra}`,\n )\n }\n\n /**\n * Conditionally return the path to the manifest cache file. The logic\n * to determine if caching should be skipped aligns with `pickManifest`\n * and is used to avoid caching manifest results that can be variable.\n */\n _manifestCachePath(\n spec: Spec,\n options: PackageInfoClientRequestOptions,\n ): string | undefined {\n if (options.before) {\n return\n }\n // if the final resolved spec is either a dist tag or something that\n // matches any range (such as a semver range of `*` or empty string)\n // then we skip caching\n const f = spec.final\n if (f.distTag || f.range?.isAny) {\n return\n }\n const key = this.#manifestCacheKey(f, options)\n return pathResolve(this.#cachePath, 'package-info', key)\n }\n\n async #registryManifestRequest(\n spec: Spec,\n options: PackageInfoClientRequestOptions,\n ): Promise<ManifestRegistry> {\n const { registry, name, registrySpec } = spec.final\n /* c8 ignore start */\n if (!spec.range?.isSingle || !registrySpec) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to request manifest',\n { spec },\n )\n }\n /* c8 ignore stop */\n const possibleLeadingChars = ['=', '^', '~', 'v']\n const hasLeadingRange = possibleLeadingChars.some(char =>\n registrySpec.startsWith(char),\n )\n const version =\n hasLeadingRange ? registrySpec.slice(1) : registrySpec\n const pakuURL = new URL(`${name}/${version}`, registry)\n const response = await this.registryClient.request(pakuURL, {\n headers: {\n accept: 'application/json',\n },\n })\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch manifest',\n {\n url: pakuURL,\n response,\n },\n )\n }\n return response.json() as ManifestRegistry\n }\n\n async tarball(\n spec: Spec | string,\n options: PackageInfoClientExtractOptions = {},\n ): Promise<Buffer> {\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const f = spec.final\n\n switch (f.type) {\n case 'registry': {\n const { dist } = await this.manifest(spec, options)\n if (!dist)\n throw this.#resolveError(\n spec,\n options,\n 'no dist object found in manifest',\n )\n\n const { tarball, integrity } = dist\n if (!tarball) {\n throw this.#resolveError(\n spec,\n options,\n 'no tarball found in manifest.dist',\n )\n }\n\n const trustIntegrity =\n this.#trustedIntegrities.get(tarball) === integrity\n\n const response = await this.registryClient.request(tarball, {\n ...options,\n integrity,\n trustIntegrity,\n })\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch tarball',\n { response, url: tarball },\n )\n }\n\n // if we don't already trust it, but it's valid, start trusting it\n if (\n !trustIntegrity &&\n response.checkIntegrity({ spec, url: tarball })\n ) {\n this.#trustedIntegrities.set(tarball, response.integrity)\n }\n\n return response.buffer()\n }\n\n case 'git': {\n const {\n remoteURL,\n gitRemote,\n gitCommittish,\n gitSelectorParsed,\n } = f\n const s: Spec = spec\n if (!remoteURL) {\n if (!gitRemote) {\n throw this.#resolveError(\n spec,\n options,\n 'no remote on git: specifier',\n )\n }\n const { path } = gitSelectorParsed ?? {}\n return await this.#tmpdir(async dir => {\n await clone(gitRemote, gitCommittish, dir + '/package', {\n spec: s,\n })\n let cwd = dir\n if (path !== undefined) {\n const src = pathResolve(dir, 'package', path)\n cwd = dirname(src)\n const pkg = pathResolve(cwd, 'package')\n if (src !== pkg) {\n const rand = randomBytes(6).toString('hex')\n // faster than deleting\n await rename(pkg, pkg + rand).catch(() => {})\n await rename(src, pkg)\n }\n }\n return tarC({ cwd, gzip: true }, ['package']).concat()\n })\n }\n // fallthrough if remoteURL set\n }\n\n case 'remote': {\n const { remoteURL } = f\n if (!remoteURL) {\n throw this.#resolveError(spec, options)\n }\n const response = await this.registryClient.request(remoteURL)\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch URL',\n { response, url: remoteURL },\n )\n }\n return response.buffer()\n }\n\n case 'file': {\n const { file } = f\n if (file === undefined)\n throw this.#resolveError(spec, options, 'no file path')\n const { from = this.#projectRoot } = options\n const path = pathResolve(from, file)\n const st = await stat(path)\n if (st.isDirectory()) {\n const p = dirname(path)\n const b = basename(path)\n // TODO: Pack properly, ignore stuff, bundleDeps, etc\n return tarC({ cwd: p, gzip: true }, [b]).concat()\n }\n return readFile(path)\n }\n\n case 'workspace': {\n // TODO: Pack properly, ignore stuff, bundleDeps, etc\n const ws = this.#getWS(spec, options)\n const p = dirname(ws.fullpath)\n const b = basename(ws.fullpath)\n return tarC({ cwd: p, gzip: true }, [b]).concat()\n }\n }\n }\n\n async manifest(\n spec: Spec | string,\n options: PackageInfoClientRequestOptions = {},\n ) {\n const { from = this.#projectRoot } = options\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const f = spec.final\n\n switch (f.type) {\n case 'registry': {\n // Check if manifest is cached, if so just return it earlier\n const cachePath = this._manifestCachePath(spec, options)\n if (cachePath) {\n try {\n // Cache file exists, read and return it\n const cached = await readFile(cachePath, 'utf8')\n const json = JSON.parse(cached) as Manifest & {\n __VLT_MANIFEST_CACHE_TIMESTAMP?: number\n }\n // retrieve timestamp to check if cache is still valid\n const timestamp = json.__VLT_MANIFEST_CACHE_TIMESTAMP\n delete json.__VLT_MANIFEST_CACHE_TIMESTAMP\n // removes the cache file if older than its maximum age\n if (\n timestamp != null &&\n timestamp < this.#manifestCacheMinAge\n ) {\n void unlink(cachePath).catch(() => {})\n throw new Error('manifest cache expired')\n }\n return json\n } catch {\n // Cache miss, fetch from packument\n }\n }\n\n const mani =\n spec.range?.isSingle ?\n await this.#registryManifestRequest(spec, options)\n : pickManifest(\n await this.packument(f, options),\n spec,\n options,\n )\n if (!mani) throw this.#resolveError(spec, options)\n const { integrity, tarball } =\n mani.dist ?? /* c8 ignore next */ {}\n if (isIntegrity(integrity) && tarball) {\n const registryOrigin = new URL(String(f.registry)).origin\n const tgzOrigin = new URL(tarball).origin\n // if it comes from the same origin, trust the integrity\n if (tgzOrigin === registryOrigin) {\n this.#trustedIntegrities.set(tarball, integrity)\n }\n }\n\n // Cache the manifest data\n if (cachePath) {\n const json = JSON.stringify({\n ...mani,\n // append a timestamp to the manifest so that we can quickly\n // check if the cache is still valid when loading it\n __VLT_MANIFEST_CACHE_TIMESTAMP: Date.now(),\n })\n void writeFile(cachePath, json, 'utf8').catch(\n (err: unknown) => {\n // in case the cache directory doesn't exist\n // just create it and retry\n if (\n err instanceof Error &&\n 'code' in err &&\n err.code === 'ENOENT'\n ) {\n void mkdir(dirname(cachePath), {\n recursive: true,\n }).then(() => {\n void writeFile(cachePath, json, 'utf8')\n })\n }\n },\n )\n }\n\n return mani\n }\n\n case 'git': {\n const {\n gitRemote,\n gitCommittish,\n remoteURL,\n gitSelectorParsed,\n } = f\n if (!remoteURL) {\n const s = spec\n if (!gitRemote)\n throw this.#resolveError(spec, options, 'no git remote')\n return await this.#tmpdir(async dir => {\n await clone(gitRemote, gitCommittish, dir, { spec: s })\n const { path } = gitSelectorParsed ?? {}\n const pkgDir =\n path !== undefined ? pathResolve(dir, path) : dir\n return this.packageJson.read(pkgDir)\n })\n }\n // fallthrough to remote\n }\n\n case 'remote': {\n const { remoteURL } = f\n if (!remoteURL) {\n throw this.#resolveError(\n spec,\n options,\n 'no remoteURL on remote specifier',\n )\n }\n const s = spec\n return await this.#tmpdir(async dir => {\n const response =\n await this.registryClient.request(remoteURL)\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n s,\n options,\n 'failed to fetch URL',\n { response, url: remoteURL },\n )\n }\n const buf = response.buffer()\n\n // Compute integrity for remote/git-with-tarball deps\n const computed = ssri\n .fromData(buf, { algorithms: ['sha512'] })\n .toString()\n\n try {\n await this.tarPool.unpack(buf, dir)\n } catch (er) {\n throw this.#resolveError(\n s,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n\n // return manifest with computed integrity\n const mani = this.packageJson.read(dir)\n mani.dist = { integrity: computed as Integrity }\n return mani\n })\n }\n\n case 'file': {\n const { file } = f\n if (file === undefined)\n throw this.#resolveError(spec, options, 'no file path')\n const path = pathResolve(from, file)\n const st = await stat(path)\n if (st.isDirectory()) {\n return this.packageJson.read(path)\n }\n const s = spec\n return await this.#tmpdir(async dir => {\n try {\n await this.tarPool.unpack(await readFile(path), dir)\n } catch (er) {\n throw this.#resolveError(\n s,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n return this.packageJson.read(dir)\n })\n }\n\n case 'workspace': {\n return this.#getWS(spec, options).manifest\n }\n }\n }\n\n async packument(\n spec: Spec | string,\n options: PackageInfoClientRequestOptions = {},\n ): Promise<Packument> {\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const f = spec.final\n switch (f.type) {\n // RevDoc is the equivalent of a packument for a git repo\n case 'git': {\n const { gitRemote } = f\n if (!gitRemote) {\n throw this.#resolveError(\n spec,\n options,\n 'git remote could not be determined',\n )\n }\n const revDoc = await revs(gitRemote, {\n cwd: this.options.projectRoot,\n })\n if (!revDoc) throw this.#resolveError(spec, options)\n return asPackument(revDoc)\n }\n\n // these are all faked packuments\n case 'file':\n case 'workspace':\n case 'remote': {\n const manifest = await this.manifest(f, options)\n return {\n name: manifest.name ?? '',\n 'dist-tags': {\n latest: manifest.version ?? '',\n },\n versions: {\n [manifest.version ?? '']: manifest as Manifest,\n },\n }\n }\n\n case 'registry': {\n const { registry, name } = f\n const pakuURL = new URL(name, registry)\n const response = await this.registryClient.request(pakuURL, {\n headers: {\n accept: 'application/json',\n },\n })\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch packument',\n {\n url: pakuURL,\n response,\n },\n )\n }\n return response.json() as Packument\n }\n }\n }\n\n async resolve(\n spec: Spec | string,\n options: PackageInfoClientRequestOptions = {},\n ): Promise<Resolution> {\n const memoKey = String(spec)\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n\n const memo = this.#resolutions.get(memoKey)\n if (memo) return memo\n const f = spec.final\n\n switch (f.type) {\n case 'file': {\n const { file } = f\n if (!file || !f.file) {\n throw this.#resolveError(\n spec,\n options,\n 'no path on file: specifier',\n )\n }\n const { from = this.#projectRoot } = options\n const resolved = pathResolve(from, f.file)\n const r = { resolved, spec }\n this.#resolutions.set(memoKey, r)\n return r\n }\n\n case 'remote': {\n const { remoteURL } = f\n if (!remoteURL)\n throw this.#resolveError(\n spec,\n options,\n 'no URL in remote specifier',\n )\n const r = { resolved: remoteURL, spec }\n this.#resolutions.set(memoKey, r)\n return r\n }\n\n case 'workspace': {\n const ws = this.#getWS(spec, options)\n return {\n resolved: ws.fullpath,\n spec,\n }\n }\n\n case 'registry': {\n const mani = await this.manifest(spec, options)\n if (mani.dist) {\n const { integrity, tarball, signatures } = mani.dist\n if (tarball) {\n const r = {\n resolved: tarball,\n integrity,\n signatures,\n spec,\n }\n this.#resolutions.set(memoKey, r)\n return r\n }\n }\n throw this.#resolveError(spec, options)\n }\n\n case 'git': {\n const { gitRemote, remoteURL, gitSelectorParsed } = f\n if (remoteURL && gitSelectorParsed?.path === undefined) {\n // known git host with a tarball download endpoint\n const r = { resolved: remoteURL, spec }\n this.#resolutions.set(memoKey, r)\n return r\n }\n if (!gitRemote) {\n throw this.#resolveError(\n spec,\n options,\n 'no remote on git specifier',\n )\n }\n const rev = await gitResolve(gitRemote, f.gitCommittish, {\n spec,\n })\n if (rev) {\n const r = {\n resolved: `${gitRemote}#${rev.sha}`,\n spec,\n }\n if (gitSelectorParsed) {\n r.resolved += Object.entries(gitSelectorParsed)\n .filter(([_, v]) => v)\n .map(([k, v]) => `::${k}:${v}`)\n .join('')\n }\n this.#resolutions.set(memoKey, r)\n return r\n }\n // have to actually clone somewhere\n const s: Spec = spec\n return this.#tmpdir(async tmpdir => {\n const sha = await clone(\n gitRemote,\n s.gitCommittish,\n tmpdir,\n {\n spec: s,\n },\n )\n const r = {\n resolved: `${gitRemote}#${sha}`,\n spec: s,\n }\n this.#resolutions.set(memoKey, r)\n return r\n })\n }\n }\n }\n\n async #tmpdir<T>(fn: (dir: string) => Promise<T>): Promise<T> {\n const p = `package-info/${randomBytes(6).toString('hex')}`\n const dir = xdg.runtime(p)\n try {\n return await fn(dir)\n } finally {\n // intentionally do not await\n void rm(dir, { recursive: true, force: true })\n }\n }\n\n // error resolving\n #resolveError(\n spec?: Spec,\n options: PackageInfoClientRequestOptions = {},\n message = 'Could not resolve',\n extra: ErrorCauseOptions = {},\n ) {\n const { from = this.#projectRoot } = options\n const er = error(\n message,\n {\n code: 'ERESOLVE',\n spec,\n from,\n ...extra,\n },\n this.#resolveError,\n )\n return er\n }\n}\n"]} |
| import { rename as fsRename } from 'node:fs/promises'; | ||
| export declare const rename: typeof fsRename; | ||
| //# sourceMappingURL=rename.d.ts.map |
| {"version":3,"file":"rename.d.ts","sourceRoot":"","sources":["../src/rename.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAM,MAAM,kBAAkB,CAAA;AACzD,eAAO,MAAM,MAAM,iBAqBhB,CAAA"} |
| /** | ||
| * On posix systems, rename is atomic and will clobber anything in its way | ||
| * However, on Windows, it can fail with the rather unhelpful EPERM error if | ||
| * the target directory is not removed in time or is currently in use. | ||
| * | ||
| * While true atomic semantics is not available on Windows in this case, we can | ||
| * at least implement the posix overwrite semantics by explicitly removing the | ||
| * target when this error occurs. | ||
| * | ||
| * This is only relevant when renaming *directories*, since files will | ||
| * generally not raise problems. When/if we rename directories outside of | ||
| * package-info, this can be moved to its own shared module. | ||
| * @module | ||
| */ | ||
| const { platform } = process; | ||
| import { rename as fsRename, rm } from 'node:fs/promises'; | ||
| export const rename = platform !== 'win32' ? fsRename : (async function (oldPath, newPath) { | ||
| let retries = 3; | ||
| const retry = async (er) => { | ||
| if (retries > 0 && | ||
| er.code === 'EPERM') { | ||
| retries--; | ||
| await rm(newPath, { recursive: true, force: true }); | ||
| return fsRename(oldPath, newPath).then(() => { }, retry); | ||
| } | ||
| else { | ||
| throw er; | ||
| } | ||
| }; | ||
| return fsRename(oldPath, newPath).then(() => { }, retry); | ||
| }); | ||
| //# sourceMappingURL=rename.js.map |
| {"version":3,"file":"rename.js","sourceRoot":"","sources":["../src/rename.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;AAE5B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AACzD,MAAM,CAAC,MAAM,MAAM,GACjB,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAChC,KAAK,WACH,OAAiB,EACjB,OAAiB;IAEjB,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,MAAM,KAAK,GAAG,KAAK,EAAE,EAAW,EAAiB,EAAE;QACjD,IACE,OAAO,GAAG,CAAC;YACV,EAA4B,CAAC,IAAI,KAAK,OAAO,EAC9C,CAAC;YACD,OAAO,EAAE,CAAA;YACT,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACnD,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,CAAC,CAAA;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAA;QACV,CAAC;IACH,CAAC,CAAA;IACD,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,CAAC,CAAA;AACzD,CAAC,CACF,CAAA","sourcesContent":["/**\n * On posix systems, rename is atomic and will clobber anything in its way\n * However, on Windows, it can fail with the rather unhelpful EPERM error if\n * the target directory is not removed in time or is currently in use.\n *\n * While true atomic semantics is not available on Windows in this case, we can\n * at least implement the posix overwrite semantics by explicitly removing the\n * target when this error occurs.\n *\n * This is only relevant when renaming *directories*, since files will\n * generally not raise problems. When/if we rename directories outside of\n * package-info, this can be moved to its own shared module.\n * @module\n */\nconst { platform } = process\nimport type { PathLike } from 'node:fs'\nimport { rename as fsRename, rm } from 'node:fs/promises'\nexport const rename =\n platform !== 'win32' ? fsRename : (\n async function (\n oldPath: PathLike,\n newPath: PathLike,\n ): Promise<void> {\n let retries = 3\n const retry = async (er: unknown): Promise<void> => {\n if (\n retries > 0 &&\n (er as NodeJS.ErrnoException).code === 'EPERM'\n ) {\n retries--\n await rm(newPath, { recursive: true, force: true })\n return fsRename(oldPath, newPath).then(() => {}, retry)\n } else {\n throw er\n }\n }\n return fsRename(oldPath, newPath).then(() => {}, retry)\n }\n )\n"]} |
+15
-29
| { | ||
| "name": "@vltpkg/package-info", | ||
| "description": "Resolve and fetch package metadata and tarballs", | ||
| "version": "1.0.0-rc.10", | ||
| "version": "1.0.0-rc.11", | ||
| "repository": { | ||
@@ -11,26 +11,15 @@ "type": "git", | ||
| "author": "vlt technology inc. <support@vlt.sh> (http://vlt.sh)", | ||
| "tshy": { | ||
| "selfLink": false, | ||
| "liveDev": true, | ||
| "dialects": [ | ||
| "esm" | ||
| ], | ||
| "exports": { | ||
| "./package.json": "./package.json", | ||
| ".": "./src/index.ts" | ||
| } | ||
| }, | ||
| "dependencies": { | ||
| "ssri": "^13.0.0", | ||
| "tar": "^7.5.2", | ||
| "@vltpkg/error-cause": "1.0.0-rc.10", | ||
| "@vltpkg/git": "1.0.0-rc.10", | ||
| "@vltpkg/pick-manifest": "1.0.0-rc.10", | ||
| "@vltpkg/package-json": "1.0.0-rc.10", | ||
| "@vltpkg/registry-client": "1.0.0-rc.10", | ||
| "@vltpkg/spec": "1.0.0-rc.10", | ||
| "@vltpkg/types": "1.0.0-rc.10", | ||
| "@vltpkg/tar": "1.0.0-rc.10", | ||
| "@vltpkg/xdg": "1.0.0-rc.10", | ||
| "@vltpkg/workspaces": "1.0.0-rc.10" | ||
| "@vltpkg/git": "1.0.0-rc.11", | ||
| "@vltpkg/error-cause": "1.0.0-rc.11", | ||
| "@vltpkg/package-json": "1.0.0-rc.11", | ||
| "@vltpkg/pick-manifest": "1.0.0-rc.11", | ||
| "@vltpkg/spec": "1.0.0-rc.11", | ||
| "@vltpkg/tar": "1.0.0-rc.11", | ||
| "@vltpkg/registry-client": "1.0.0-rc.11", | ||
| "@vltpkg/types": "1.0.0-rc.11", | ||
| "@vltpkg/xdg": "1.0.0-rc.11", | ||
| "@vltpkg/workspaces": "1.0.0-rc.11" | ||
| }, | ||
@@ -45,3 +34,2 @@ "devDependencies": { | ||
| "tap": "^21.5.0", | ||
| "tshy": "^3.1.0", | ||
| "typedoc": "~0.27.9", | ||
@@ -51,4 +39,4 @@ "typescript": "5.7.3", | ||
| "@vltpkg/benchmark": "0.0.0", | ||
| "@vltpkg/cache-unzip": "1.0.0-rc.10", | ||
| "@vltpkg/vlt-json": "1.0.0-rc.10" | ||
| "@vltpkg/cache-unzip": "1.0.0-rc.11", | ||
| "@vltpkg/vlt-json": "1.0.0-rc.11" | ||
| }, | ||
@@ -63,3 +51,3 @@ "license": "BSD-2-Clause-Patent", | ||
| "prettier": "../../.prettierrc.js", | ||
| "module": "./dist/esm/index.js", | ||
| "module": "./dist/index.js", | ||
| "type": "module", | ||
@@ -70,4 +58,3 @@ "exports": { | ||
| "import": { | ||
| "types": "./dist/esm/index.d.ts", | ||
| "default": "./dist/esm/index.js" | ||
| "default": "./dist/index.js" | ||
| } | ||
@@ -88,5 +75,4 @@ } | ||
| "posttest": "tsc --noEmit", | ||
| "tshy": "tshy", | ||
| "typecheck": "tsc --noEmit" | ||
| } | ||
| } |
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import type { PickManifestOptions } from '@vltpkg/pick-manifest'; | ||
| import type { RegistryClientOptions, RegistryClientRequestOptions } from '@vltpkg/registry-client'; | ||
| import { RegistryClient } from '@vltpkg/registry-client'; | ||
| import type { SpecOptions } from '@vltpkg/spec'; | ||
| import { Spec } from '@vltpkg/spec'; | ||
| import { Pool } from '@vltpkg/tar'; | ||
| import type { Integrity, Manifest, Packument } from '@vltpkg/types'; | ||
| import { Monorepo } from '@vltpkg/workspaces'; | ||
| export declare const delimiter = "\u00B7"; | ||
| export type Resolution = { | ||
| resolved: string; | ||
| integrity?: Integrity; | ||
| signatures?: Exclude<Manifest['dist'], undefined>['signatures']; | ||
| spec: Spec; | ||
| }; | ||
| export type PackageInfoClientOptions = RegistryClientOptions & SpecOptions & { | ||
| /** root of the project. Defaults to process.cwd() */ | ||
| projectRoot?: string; | ||
| /** PackageJson object */ | ||
| packageJson?: PackageJson; | ||
| monorepo?: Monorepo; | ||
| /** workspace groups to load, irrelevant if Monorepo provided */ | ||
| 'workspace-group'?: string[]; | ||
| /** workspace paths to load, irrelevant if Monorepo provided */ | ||
| workspace?: string[]; | ||
| }; | ||
| export type PackageInfoClientRequestOptions = PickManifestOptions & RegistryClientRequestOptions & { | ||
| /** dir to resolve `file://` specifiers against. Defaults to projectRoot. */ | ||
| from?: string; | ||
| }; | ||
| export type PackageInfoClientExtractOptions = PackageInfoClientRequestOptions & { | ||
| integrity?: Integrity; | ||
| resolved?: string; | ||
| }; | ||
| export declare class PackageInfoClient { | ||
| #private; | ||
| options: PackageInfoClientOptions; | ||
| packageJson: PackageJson; | ||
| monorepo?: Monorepo; | ||
| get registryClient(): RegistryClient; | ||
| get tarPool(): Pool; | ||
| constructor(options?: PackageInfoClientOptions); | ||
| extract(spec: Spec | string, target: string, options?: PackageInfoClientExtractOptions): Promise<Resolution>; | ||
| /** | ||
| * Conditionally return the path to the manifest cache file. The logic | ||
| * to determine if caching should be skipped aligns with `pickManifest` | ||
| * and is used to avoid caching manifest results that can be variable. | ||
| */ | ||
| _manifestCachePath(spec: Spec, options: PackageInfoClientRequestOptions): string | undefined; | ||
| tarball(spec: Spec | string, options?: PackageInfoClientExtractOptions): Promise<Buffer>; | ||
| manifest(spec: Spec | string, options?: PackageInfoClientRequestOptions): Promise<Manifest | import("@vltpkg/types").Override<Manifest, import("@vltpkg/types").NormalizedFields>>; | ||
| packument(spec: Spec | string, options?: PackageInfoClientRequestOptions): Promise<Packument>; | ||
| resolve(spec: Spec | string, options?: PackageInfoClientRequestOptions): Promise<Resolution>; | ||
| } | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,OAAO,KAAK,EACV,qBAAqB,EACrB,4BAA4B,EAC7B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EAEV,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAsB7C,eAAO,MAAM,SAAS,WAAM,CAAA;AAE5B,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,YAAY,CAAC,CAAA;IAC/D,IAAI,EAAE,IAAI,CAAA;CACX,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,GAC1D,WAAW,GAAG;IACZ,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yBAAyB;IACzB,WAAW,CAAC,EAAE,WAAW,CAAA;IAEzB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAEnB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE5B,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAEH,MAAM,MAAM,+BAA+B,GAAG,mBAAmB,GAC/D,4BAA4B,GAAG;IAC7B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAEH,MAAM,MAAM,+BAA+B,GACzC,+BAA+B,GAAG;IAChC,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAKH,qBAAa,iBAAiB;;IAI5B,OAAO,EAAE,wBAAwB,CAAA;IAEjC,WAAW,EAAE,WAAW,CAAA;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAKnB,IAAI,cAAc,mBAKjB;IAED,IAAI,OAAO,SAGV;gBAEW,OAAO,GAAE,wBAA6B;IAuB5C,OAAO,CACX,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,UAAU,CAAC;IAmOtB;;;;OAIG;IACH,kBAAkB,CAChB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,+BAA+B,GACvC,MAAM,GAAG,SAAS;IAwDf,OAAO,CACX,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,MAAM,CAAC;IAsIZ,QAAQ,CACZ,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC;IAwLzC,SAAS,CACb,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,SAAS,CAAC;IA8Df,OAAO,CACX,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,UAAU,CAAC;CAsJvB"} |
| import { error } from '@vltpkg/error-cause'; | ||
| import { clone, resolve as gitResolve, revs } from '@vltpkg/git'; | ||
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import { pickManifest } from '@vltpkg/pick-manifest'; | ||
| import { RegistryClient } from '@vltpkg/registry-client'; | ||
| import { Spec } from '@vltpkg/spec'; | ||
| import { Pool } from '@vltpkg/tar'; | ||
| import { asPackument, isIntegrity } from '@vltpkg/types'; | ||
| import ssri from 'ssri'; | ||
| import { Monorepo } from '@vltpkg/workspaces'; | ||
| import { XDG } from '@vltpkg/xdg'; | ||
| import { randomBytes } from 'node:crypto'; | ||
| import { mkdir, readFile, rm, stat, symlink, unlink, writeFile, } from 'node:fs/promises'; | ||
| import { basename, dirname, resolve as pathResolve, relative, } from 'node:path'; | ||
| import { create as tarC } from 'tar'; | ||
| import { rename } from "./rename.js"; | ||
| const xdg = new XDG('vlt'); | ||
| export const delimiter = '·'; | ||
| // the maximum duration of a manifest cache file | ||
| const manifestCacheMaxAge = 5 * 60 * 1000; | ||
| export class PackageInfoClient { | ||
| #registryClient; | ||
| #projectRoot; | ||
| #tarPool; | ||
| options; | ||
| #resolutions = new Map(); | ||
| packageJson; | ||
| monorepo; | ||
| #trustedIntegrities = new Map(); | ||
| #manifestCacheMinAge = Date.now() - manifestCacheMaxAge; | ||
| #cachePath; | ||
| get registryClient() { | ||
| if (!this.#registryClient) { | ||
| this.#registryClient = new RegistryClient(this.options); | ||
| } | ||
| return this.#registryClient; | ||
| } | ||
| get tarPool() { | ||
| if (!this.#tarPool) | ||
| this.#tarPool = new Pool(); | ||
| return this.#tarPool; | ||
| } | ||
| constructor(options = {}) { | ||
| this.options = options; | ||
| this.#projectRoot = options.projectRoot || process.cwd(); | ||
| this.packageJson = options.packageJson ?? new PackageJson(); | ||
| const wsLoad = { | ||
| ...(options.workspace?.length && { paths: options.workspace }), | ||
| ...(options['workspace-group']?.length && { | ||
| groups: options['workspace-group'], | ||
| }), | ||
| }; | ||
| this.monorepo = | ||
| options.monorepo ?? | ||
| Monorepo.maybeLoad(this.#projectRoot, { | ||
| load: wsLoad, | ||
| packageJson: this.packageJson, | ||
| }); | ||
| this.#cachePath = options.cache ?? xdg.cache(); | ||
| // optionally create its cache directory if it doesn't exist | ||
| void mkdir(pathResolve(this.#cachePath, 'package-info'), { | ||
| recursive: true, | ||
| }).catch(() => { }); | ||
| } | ||
| async extract(spec, target, options = {}) { | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const { from = this.#projectRoot, integrity, resolved } = options; | ||
| const f = spec.final; | ||
| const r = integrity && resolved ? | ||
| { resolved, integrity, spec } | ||
| : await this.resolve(spec, options); | ||
| switch (f.type) { | ||
| case 'git': { | ||
| const { gitRemote, gitCommittish, remoteURL, gitSelectorParsed, } = f; | ||
| if (!remoteURL) { | ||
| /* c8 ignore start - Impossible, would throw on the resolve */ | ||
| if (!gitRemote) | ||
| throw this.#resolveError(spec, options, 'no remote on git: specifier'); | ||
| /* c8 ignore stop */ | ||
| const { path } = gitSelectorParsed ?? {}; | ||
| if (path !== undefined) { | ||
| // use obvious name because it's in node_modules | ||
| const tmp = pathResolve(dirname(target), `.TEMP.${basename(target)}-${randomBytes(6).toString('hex')}`); | ||
| await clone(gitRemote, gitCommittish, tmp, { spec }); | ||
| const src = pathResolve(tmp, path); | ||
| await rename(src, target); | ||
| // intentionally not awaited | ||
| void rm(tmp, { recursive: true, force: true }); | ||
| } | ||
| else { | ||
| await clone(gitRemote, gitCommittish, target, { spec }); | ||
| // intentionally not awaited | ||
| void rm(target + '/.git', { recursive: true }); | ||
| } | ||
| return r; | ||
| } | ||
| // fallthrough if a remote tarball url present | ||
| } | ||
| case 'registry': { | ||
| const trustIntegrity = this.#trustedIntegrities.get(r.resolved) === r.integrity; | ||
| const response = await this.registryClient.request(r.resolved, { | ||
| integrity: r.integrity, | ||
| trustIntegrity, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch tarball', { | ||
| url: r.resolved, | ||
| response, | ||
| }); | ||
| } | ||
| // if it's not trusted already, but valid, start trusting | ||
| if (!trustIntegrity && | ||
| response.checkIntegrity({ spec, url: resolved })) { | ||
| this.#trustedIntegrities.set(r.resolved, response.integrity); | ||
| } | ||
| try { | ||
| await this.tarPool.unpack(response.buffer(), target); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(spec, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| return r; | ||
| } | ||
| case 'remote': { | ||
| const response = await this.registryClient.request(r.resolved); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch remote tarball', { | ||
| url: r.resolved, | ||
| response, | ||
| }); | ||
| } | ||
| const buf = response.buffer(); | ||
| // Compute integrity for remote/git-with-tarball deps | ||
| const computed = ssri | ||
| .fromData(buf, { algorithms: ['sha512'] }) | ||
| .toString(); | ||
| if (r.integrity && r.integrity !== computed) { | ||
| throw error('Integrity check failure', { | ||
| code: 'EINTEGRITY', | ||
| spec, | ||
| url: r.resolved, | ||
| wanted: r.integrity, | ||
| found: computed, | ||
| }); | ||
| } | ||
| r.integrity = computed; | ||
| try { | ||
| await this.tarPool.unpack(buf, target); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(spec, options, 'remote tar unpack failed', { cause: er }); | ||
| } | ||
| return r; | ||
| } | ||
| case 'file': { | ||
| // if it's a directory, then "extract" means "symlink" | ||
| const { file } = f; | ||
| /* c8 ignore start - asserted in resolve() */ | ||
| if (file === undefined) | ||
| throw this.#resolveError(spec, options, 'no file path'); | ||
| /* c8 ignore stop */ | ||
| const path = pathResolve(from, file); | ||
| const st = await stat(path); | ||
| if (st.isFile()) { | ||
| try { | ||
| await this.tarPool.unpack(await this.tarball(spec, options), target); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(spec, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| } | ||
| else if (st.isDirectory()) { | ||
| const rel = relative(dirname(target), path); | ||
| await symlink(rel, target, 'dir'); | ||
| /* c8 ignore start */ | ||
| } | ||
| else { | ||
| throw this.#resolveError(spec, options, 'file: specifier does not resolve to directory or tarball'); | ||
| } | ||
| /* c8 ignore stop */ | ||
| return r; | ||
| } | ||
| case 'workspace': { | ||
| const ws = this.#getWS(spec, options); | ||
| const rel = relative(dirname(target), ws.fullpath); | ||
| await symlink(rel, target, 'dir'); | ||
| return r; | ||
| } | ||
| } | ||
| } | ||
| #getWS(spec, options) { | ||
| const { workspace } = spec; | ||
| /* c8 ignore start - asserted in resolve() */ | ||
| if (workspace === undefined) | ||
| throw this.#resolveError(spec, options, 'no workspace ID'); | ||
| /* c8 ignore stop */ | ||
| if (!this.monorepo) { | ||
| throw this.#resolveError(spec, options, 'Not in a monorepo, cannot resolve workspace spec'); | ||
| } | ||
| const ws = this.monorepo.get(workspace); | ||
| if (!ws) { | ||
| throw this.#resolveError(spec, options, 'workspace not found', { | ||
| wanted: workspace, | ||
| }); | ||
| } | ||
| return ws; | ||
| } | ||
| /** | ||
| * Return the manifest cache key for a spec and the current options. | ||
| */ | ||
| #manifestCacheKey(spec, options) { | ||
| let extra = ''; | ||
| if (options['node-version']) { | ||
| extra += `${delimiter}node-version:${options['node-version']}`; | ||
| } | ||
| if (options.os) { | ||
| extra += `${delimiter}os:${options.os}`; | ||
| } | ||
| if (options.arch) { | ||
| extra += `${delimiter}arch:${options.arch}`; | ||
| } | ||
| return encodeURIComponent(`${spec.registry}${delimiter}${spec}${extra}`); | ||
| } | ||
| /** | ||
| * Conditionally return the path to the manifest cache file. The logic | ||
| * to determine if caching should be skipped aligns with `pickManifest` | ||
| * and is used to avoid caching manifest results that can be variable. | ||
| */ | ||
| _manifestCachePath(spec, options) { | ||
| if (options.before) { | ||
| return; | ||
| } | ||
| // if the final resolved spec is either a dist tag or something that | ||
| // matches any range (such as a semver range of `*` or empty string) | ||
| // then we skip caching | ||
| const f = spec.final; | ||
| if (f.distTag || f.range?.isAny) { | ||
| return; | ||
| } | ||
| const key = this.#manifestCacheKey(f, options); | ||
| return pathResolve(this.#cachePath, 'package-info', key); | ||
| } | ||
| async #registryManifestRequest(spec, options) { | ||
| const { registry, name, registrySpec } = spec.final; | ||
| /* c8 ignore start */ | ||
| if (!spec.range?.isSingle || !registrySpec) { | ||
| throw this.#resolveError(spec, options, 'failed to request manifest', { spec }); | ||
| } | ||
| /* c8 ignore stop */ | ||
| const possibleLeadingChars = ['=', '^', '~', 'v']; | ||
| const hasLeadingRange = possibleLeadingChars.some(char => registrySpec.startsWith(char)); | ||
| const version = hasLeadingRange ? registrySpec.slice(1) : registrySpec; | ||
| const pakuURL = new URL(`${name}/${version}`, registry); | ||
| const response = await this.registryClient.request(pakuURL, { | ||
| headers: { | ||
| accept: 'application/json', | ||
| }, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch manifest', { | ||
| url: pakuURL, | ||
| response, | ||
| }); | ||
| } | ||
| return response.json(); | ||
| } | ||
| async tarball(spec, options = {}) { | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| case 'registry': { | ||
| const { dist } = await this.manifest(spec, options); | ||
| if (!dist) | ||
| throw this.#resolveError(spec, options, 'no dist object found in manifest'); | ||
| const { tarball, integrity } = dist; | ||
| if (!tarball) { | ||
| throw this.#resolveError(spec, options, 'no tarball found in manifest.dist'); | ||
| } | ||
| const trustIntegrity = this.#trustedIntegrities.get(tarball) === integrity; | ||
| const response = await this.registryClient.request(tarball, { | ||
| ...options, | ||
| integrity, | ||
| trustIntegrity, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch tarball', { response, url: tarball }); | ||
| } | ||
| // if we don't already trust it, but it's valid, start trusting it | ||
| if (!trustIntegrity && | ||
| response.checkIntegrity({ spec, url: tarball })) { | ||
| this.#trustedIntegrities.set(tarball, response.integrity); | ||
| } | ||
| return response.buffer(); | ||
| } | ||
| case 'git': { | ||
| const { remoteURL, gitRemote, gitCommittish, gitSelectorParsed, } = f; | ||
| const s = spec; | ||
| if (!remoteURL) { | ||
| if (!gitRemote) { | ||
| throw this.#resolveError(spec, options, 'no remote on git: specifier'); | ||
| } | ||
| const { path } = gitSelectorParsed ?? {}; | ||
| return await this.#tmpdir(async (dir) => { | ||
| await clone(gitRemote, gitCommittish, dir + '/package', { | ||
| spec: s, | ||
| }); | ||
| let cwd = dir; | ||
| if (path !== undefined) { | ||
| const src = pathResolve(dir, 'package', path); | ||
| cwd = dirname(src); | ||
| const pkg = pathResolve(cwd, 'package'); | ||
| if (src !== pkg) { | ||
| const rand = randomBytes(6).toString('hex'); | ||
| // faster than deleting | ||
| await rename(pkg, pkg + rand).catch(() => { }); | ||
| await rename(src, pkg); | ||
| } | ||
| } | ||
| return tarC({ cwd, gzip: true }, ['package']).concat(); | ||
| }); | ||
| } | ||
| // fallthrough if remoteURL set | ||
| } | ||
| case 'remote': { | ||
| const { remoteURL } = f; | ||
| if (!remoteURL) { | ||
| throw this.#resolveError(spec, options); | ||
| } | ||
| const response = await this.registryClient.request(remoteURL); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch URL', { response, url: remoteURL }); | ||
| } | ||
| return response.buffer(); | ||
| } | ||
| case 'file': { | ||
| const { file } = f; | ||
| if (file === undefined) | ||
| throw this.#resolveError(spec, options, 'no file path'); | ||
| const { from = this.#projectRoot } = options; | ||
| const path = pathResolve(from, file); | ||
| const st = await stat(path); | ||
| if (st.isDirectory()) { | ||
| const p = dirname(path); | ||
| const b = basename(path); | ||
| // TODO: Pack properly, ignore stuff, bundleDeps, etc | ||
| return tarC({ cwd: p, gzip: true }, [b]).concat(); | ||
| } | ||
| return readFile(path); | ||
| } | ||
| case 'workspace': { | ||
| // TODO: Pack properly, ignore stuff, bundleDeps, etc | ||
| const ws = this.#getWS(spec, options); | ||
| const p = dirname(ws.fullpath); | ||
| const b = basename(ws.fullpath); | ||
| return tarC({ cwd: p, gzip: true }, [b]).concat(); | ||
| } | ||
| } | ||
| } | ||
| async manifest(spec, options = {}) { | ||
| const { from = this.#projectRoot } = options; | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| case 'registry': { | ||
| // Check if manifest is cached, if so just return it earlier | ||
| const cachePath = this._manifestCachePath(spec, options); | ||
| if (cachePath) { | ||
| try { | ||
| // Cache file exists, read and return it | ||
| const cached = await readFile(cachePath, 'utf8'); | ||
| const json = JSON.parse(cached); | ||
| // retrieve timestamp to check if cache is still valid | ||
| const timestamp = json.__VLT_MANIFEST_CACHE_TIMESTAMP; | ||
| delete json.__VLT_MANIFEST_CACHE_TIMESTAMP; | ||
| // removes the cache file if older than its maximum age | ||
| if (timestamp != null && | ||
| timestamp < this.#manifestCacheMinAge) { | ||
| void unlink(cachePath).catch(() => { }); | ||
| throw new Error('manifest cache expired'); | ||
| } | ||
| return json; | ||
| } | ||
| catch { | ||
| // Cache miss, fetch from packument | ||
| } | ||
| } | ||
| const mani = spec.range?.isSingle ? | ||
| await this.#registryManifestRequest(spec, options) | ||
| : pickManifest(await this.packument(f, options), spec, options); | ||
| if (!mani) | ||
| throw this.#resolveError(spec, options); | ||
| const { integrity, tarball } = mani.dist ?? /* c8 ignore next */ {}; | ||
| if (isIntegrity(integrity) && tarball) { | ||
| const registryOrigin = new URL(String(f.registry)).origin; | ||
| const tgzOrigin = new URL(tarball).origin; | ||
| // if it comes from the same origin, trust the integrity | ||
| if (tgzOrigin === registryOrigin) { | ||
| this.#trustedIntegrities.set(tarball, integrity); | ||
| } | ||
| } | ||
| // Cache the manifest data | ||
| if (cachePath) { | ||
| const json = JSON.stringify({ | ||
| ...mani, | ||
| // append a timestamp to the manifest so that we can quickly | ||
| // check if the cache is still valid when loading it | ||
| __VLT_MANIFEST_CACHE_TIMESTAMP: Date.now(), | ||
| }); | ||
| void writeFile(cachePath, json, 'utf8').catch((err) => { | ||
| // in case the cache directory doesn't exist | ||
| // just create it and retry | ||
| if (err instanceof Error && | ||
| 'code' in err && | ||
| err.code === 'ENOENT') { | ||
| void mkdir(dirname(cachePath), { | ||
| recursive: true, | ||
| }).then(() => { | ||
| void writeFile(cachePath, json, 'utf8'); | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| return mani; | ||
| } | ||
| case 'git': { | ||
| const { gitRemote, gitCommittish, remoteURL, gitSelectorParsed, } = f; | ||
| if (!remoteURL) { | ||
| const s = spec; | ||
| if (!gitRemote) | ||
| throw this.#resolveError(spec, options, 'no git remote'); | ||
| return await this.#tmpdir(async (dir) => { | ||
| await clone(gitRemote, gitCommittish, dir, { spec: s }); | ||
| const { path } = gitSelectorParsed ?? {}; | ||
| const pkgDir = path !== undefined ? pathResolve(dir, path) : dir; | ||
| return this.packageJson.read(pkgDir); | ||
| }); | ||
| } | ||
| // fallthrough to remote | ||
| } | ||
| case 'remote': { | ||
| const { remoteURL } = f; | ||
| if (!remoteURL) { | ||
| throw this.#resolveError(spec, options, 'no remoteURL on remote specifier'); | ||
| } | ||
| const s = spec; | ||
| return await this.#tmpdir(async (dir) => { | ||
| const response = await this.registryClient.request(remoteURL); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(s, options, 'failed to fetch URL', { response, url: remoteURL }); | ||
| } | ||
| const buf = response.buffer(); | ||
| // Compute integrity for remote/git-with-tarball deps | ||
| const computed = ssri | ||
| .fromData(buf, { algorithms: ['sha512'] }) | ||
| .toString(); | ||
| try { | ||
| await this.tarPool.unpack(buf, dir); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(s, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| // return manifest with computed integrity | ||
| const mani = this.packageJson.read(dir); | ||
| mani.dist = { integrity: computed }; | ||
| return mani; | ||
| }); | ||
| } | ||
| case 'file': { | ||
| const { file } = f; | ||
| if (file === undefined) | ||
| throw this.#resolveError(spec, options, 'no file path'); | ||
| const path = pathResolve(from, file); | ||
| const st = await stat(path); | ||
| if (st.isDirectory()) { | ||
| return this.packageJson.read(path); | ||
| } | ||
| const s = spec; | ||
| return await this.#tmpdir(async (dir) => { | ||
| try { | ||
| await this.tarPool.unpack(await readFile(path), dir); | ||
| } | ||
| catch (er) { | ||
| throw this.#resolveError(s, options, 'tar unpack failed', { cause: er }); | ||
| } | ||
| return this.packageJson.read(dir); | ||
| }); | ||
| } | ||
| case 'workspace': { | ||
| return this.#getWS(spec, options).manifest; | ||
| } | ||
| } | ||
| } | ||
| async packument(spec, options = {}) { | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| // RevDoc is the equivalent of a packument for a git repo | ||
| case 'git': { | ||
| const { gitRemote } = f; | ||
| if (!gitRemote) { | ||
| throw this.#resolveError(spec, options, 'git remote could not be determined'); | ||
| } | ||
| const revDoc = await revs(gitRemote, { | ||
| cwd: this.options.projectRoot, | ||
| }); | ||
| if (!revDoc) | ||
| throw this.#resolveError(spec, options); | ||
| return asPackument(revDoc); | ||
| } | ||
| // these are all faked packuments | ||
| case 'file': | ||
| case 'workspace': | ||
| case 'remote': { | ||
| const manifest = await this.manifest(f, options); | ||
| return { | ||
| name: manifest.name ?? '', | ||
| 'dist-tags': { | ||
| latest: manifest.version ?? '', | ||
| }, | ||
| versions: { | ||
| [manifest.version ?? '']: manifest, | ||
| }, | ||
| }; | ||
| } | ||
| case 'registry': { | ||
| const { registry, name } = f; | ||
| const pakuURL = new URL(name, registry); | ||
| const response = await this.registryClient.request(pakuURL, { | ||
| headers: { | ||
| accept: 'application/json', | ||
| }, | ||
| }); | ||
| if (response.statusCode !== 200) { | ||
| throw this.#resolveError(spec, options, 'failed to fetch packument', { | ||
| url: pakuURL, | ||
| response, | ||
| }); | ||
| } | ||
| return response.json(); | ||
| } | ||
| } | ||
| } | ||
| async resolve(spec, options = {}) { | ||
| const memoKey = String(spec); | ||
| if (typeof spec === 'string') | ||
| spec = Spec.parse(spec, this.options); | ||
| const memo = this.#resolutions.get(memoKey); | ||
| if (memo) | ||
| return memo; | ||
| const f = spec.final; | ||
| switch (f.type) { | ||
| case 'file': { | ||
| const { file } = f; | ||
| if (!file || !f.file) { | ||
| throw this.#resolveError(spec, options, 'no path on file: specifier'); | ||
| } | ||
| const { from = this.#projectRoot } = options; | ||
| const resolved = pathResolve(from, f.file); | ||
| const r = { resolved, spec }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| case 'remote': { | ||
| const { remoteURL } = f; | ||
| if (!remoteURL) | ||
| throw this.#resolveError(spec, options, 'no URL in remote specifier'); | ||
| const r = { resolved: remoteURL, spec }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| case 'workspace': { | ||
| const ws = this.#getWS(spec, options); | ||
| return { | ||
| resolved: ws.fullpath, | ||
| spec, | ||
| }; | ||
| } | ||
| case 'registry': { | ||
| const mani = await this.manifest(spec, options); | ||
| if (mani.dist) { | ||
| const { integrity, tarball, signatures } = mani.dist; | ||
| if (tarball) { | ||
| const r = { | ||
| resolved: tarball, | ||
| integrity, | ||
| signatures, | ||
| spec, | ||
| }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| } | ||
| throw this.#resolveError(spec, options); | ||
| } | ||
| case 'git': { | ||
| const { gitRemote, remoteURL, gitSelectorParsed } = f; | ||
| if (remoteURL && gitSelectorParsed?.path === undefined) { | ||
| // known git host with a tarball download endpoint | ||
| const r = { resolved: remoteURL, spec }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| if (!gitRemote) { | ||
| throw this.#resolveError(spec, options, 'no remote on git specifier'); | ||
| } | ||
| const rev = await gitResolve(gitRemote, f.gitCommittish, { | ||
| spec, | ||
| }); | ||
| if (rev) { | ||
| const r = { | ||
| resolved: `${gitRemote}#${rev.sha}`, | ||
| spec, | ||
| }; | ||
| if (gitSelectorParsed) { | ||
| r.resolved += Object.entries(gitSelectorParsed) | ||
| .filter(([_, v]) => v) | ||
| .map(([k, v]) => `::${k}:${v}`) | ||
| .join(''); | ||
| } | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| } | ||
| // have to actually clone somewhere | ||
| const s = spec; | ||
| return this.#tmpdir(async (tmpdir) => { | ||
| const sha = await clone(gitRemote, s.gitCommittish, tmpdir, { | ||
| spec: s, | ||
| }); | ||
| const r = { | ||
| resolved: `${gitRemote}#${sha}`, | ||
| spec: s, | ||
| }; | ||
| this.#resolutions.set(memoKey, r); | ||
| return r; | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| async #tmpdir(fn) { | ||
| const p = `package-info/${randomBytes(6).toString('hex')}`; | ||
| const dir = xdg.runtime(p); | ||
| try { | ||
| return await fn(dir); | ||
| } | ||
| finally { | ||
| // intentionally do not await | ||
| void rm(dir, { recursive: true, force: true }); | ||
| } | ||
| } | ||
| // error resolving | ||
| #resolveError(spec, options = {}, message = 'Could not resolve', extra = {}) { | ||
| const { from = this.#projectRoot } = options; | ||
| const er = error(message, { | ||
| code: 'ERESOLVE', | ||
| spec, | ||
| from, | ||
| ...extra, | ||
| }, this.#resolveError); | ||
| return er; | ||
| } | ||
| } | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorCauseOptions } from '@vltpkg/error-cause'\nimport { error } from '@vltpkg/error-cause'\nimport { clone, resolve as gitResolve, revs } from '@vltpkg/git'\nimport { PackageJson } from '@vltpkg/package-json'\nimport type { PickManifestOptions } from '@vltpkg/pick-manifest'\nimport { pickManifest } from '@vltpkg/pick-manifest'\nimport type {\n RegistryClientOptions,\n RegistryClientRequestOptions,\n} from '@vltpkg/registry-client'\nimport { RegistryClient } from '@vltpkg/registry-client'\nimport type { SpecOptions } from '@vltpkg/spec'\nimport { Spec } from '@vltpkg/spec'\nimport { Pool } from '@vltpkg/tar'\nimport type {\n Integrity,\n Manifest,\n Packument,\n ManifestRegistry,\n} from '@vltpkg/types'\nimport { asPackument, isIntegrity } from '@vltpkg/types'\nimport ssri from 'ssri'\nimport { Monorepo } from '@vltpkg/workspaces'\nimport { XDG } from '@vltpkg/xdg'\nimport { randomBytes } from 'node:crypto'\nimport {\n mkdir,\n readFile,\n rm,\n stat,\n symlink,\n unlink,\n writeFile,\n} from 'node:fs/promises'\nimport {\n basename,\n dirname,\n resolve as pathResolve,\n relative,\n} from 'node:path'\nimport { create as tarC } from 'tar'\nimport { rename } from './rename.ts'\n\nconst xdg = new XDG('vlt')\nexport const delimiter = '·'\n\nexport type Resolution = {\n resolved: string\n integrity?: Integrity\n signatures?: Exclude<Manifest['dist'], undefined>['signatures']\n spec: Spec\n}\n\nexport type PackageInfoClientOptions = RegistryClientOptions &\n SpecOptions & {\n /** root of the project. Defaults to process.cwd() */\n projectRoot?: string\n /** PackageJson object */\n packageJson?: PackageJson\n\n monorepo?: Monorepo\n\n /** workspace groups to load, irrelevant if Monorepo provided */\n 'workspace-group'?: string[]\n\n /** workspace paths to load, irrelevant if Monorepo provided */\n workspace?: string[]\n }\n\nexport type PackageInfoClientRequestOptions = PickManifestOptions &\n RegistryClientRequestOptions & {\n /** dir to resolve `file://` specifiers against. Defaults to projectRoot. */\n from?: string\n }\n\nexport type PackageInfoClientExtractOptions =\n PackageInfoClientRequestOptions & {\n integrity?: Integrity\n resolved?: string\n }\n\n// the maximum duration of a manifest cache file\nconst manifestCacheMaxAge = 5 * 60 * 1000\n\nexport class PackageInfoClient {\n #registryClient?: RegistryClient\n #projectRoot: string\n #tarPool?: Pool\n options: PackageInfoClientOptions\n #resolutions = new Map<string, Resolution>()\n packageJson: PackageJson\n monorepo?: Monorepo\n #trustedIntegrities = new Map<string, Integrity>()\n #manifestCacheMinAge = Date.now() - manifestCacheMaxAge\n #cachePath: string\n\n get registryClient() {\n if (!this.#registryClient) {\n this.#registryClient = new RegistryClient(this.options)\n }\n return this.#registryClient\n }\n\n get tarPool() {\n if (!this.#tarPool) this.#tarPool = new Pool()\n return this.#tarPool\n }\n\n constructor(options: PackageInfoClientOptions = {}) {\n this.options = options\n this.#projectRoot = options.projectRoot || process.cwd()\n this.packageJson = options.packageJson ?? new PackageJson()\n const wsLoad = {\n ...(options.workspace?.length && { paths: options.workspace }),\n ...(options['workspace-group']?.length && {\n groups: options['workspace-group'],\n }),\n }\n this.monorepo =\n options.monorepo ??\n Monorepo.maybeLoad(this.#projectRoot, {\n load: wsLoad,\n packageJson: this.packageJson,\n })\n this.#cachePath = options.cache ?? xdg.cache()\n // optionally create its cache directory if it doesn't exist\n void mkdir(pathResolve(this.#cachePath, 'package-info'), {\n recursive: true,\n }).catch(() => {})\n }\n\n async extract(\n spec: Spec | string,\n target: string,\n options: PackageInfoClientExtractOptions = {},\n ): Promise<Resolution> {\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const { from = this.#projectRoot, integrity, resolved } = options\n const f = spec.final\n const r =\n integrity && resolved ?\n { resolved, integrity, spec }\n : await this.resolve(spec, options)\n\n switch (f.type) {\n case 'git': {\n const {\n gitRemote,\n gitCommittish,\n remoteURL,\n gitSelectorParsed,\n } = f\n if (!remoteURL) {\n /* c8 ignore start - Impossible, would throw on the resolve */\n if (!gitRemote)\n throw this.#resolveError(\n spec,\n options,\n 'no remote on git: specifier',\n )\n /* c8 ignore stop */\n const { path } = gitSelectorParsed ?? {}\n if (path !== undefined) {\n // use obvious name because it's in node_modules\n const tmp = pathResolve(\n dirname(target),\n `.TEMP.${basename(target)}-${randomBytes(6).toString('hex')}`,\n )\n await clone(gitRemote, gitCommittish, tmp, { spec })\n const src = pathResolve(tmp, path)\n await rename(src, target)\n // intentionally not awaited\n void rm(tmp, { recursive: true, force: true })\n } else {\n await clone(gitRemote, gitCommittish, target, { spec })\n // intentionally not awaited\n void rm(target + '/.git', { recursive: true })\n }\n return r\n }\n // fallthrough if a remote tarball url present\n }\n\n case 'registry': {\n const trustIntegrity =\n this.#trustedIntegrities.get(r.resolved) === r.integrity\n\n const response = await this.registryClient.request(\n r.resolved,\n {\n integrity: r.integrity,\n trustIntegrity,\n },\n )\n\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch tarball',\n {\n url: r.resolved,\n response,\n },\n )\n }\n\n // if it's not trusted already, but valid, start trusting\n if (\n !trustIntegrity &&\n response.checkIntegrity({ spec, url: resolved })\n ) {\n this.#trustedIntegrities.set(r.resolved, response.integrity)\n }\n\n try {\n await this.tarPool.unpack(response.buffer(), target)\n } catch (er) {\n throw this.#resolveError(\n spec,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n return r\n }\n\n case 'remote': {\n const response = await this.registryClient.request(r.resolved)\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch remote tarball',\n {\n url: r.resolved,\n response,\n },\n )\n }\n\n const buf = response.buffer()\n\n // Compute integrity for remote/git-with-tarball deps\n const computed = ssri\n .fromData(buf, { algorithms: ['sha512'] })\n .toString()\n if (r.integrity && r.integrity !== computed) {\n throw error('Integrity check failure', {\n code: 'EINTEGRITY',\n spec,\n url: r.resolved,\n wanted: r.integrity,\n found: computed,\n })\n }\n r.integrity = computed as Integrity\n\n try {\n await this.tarPool.unpack(buf, target)\n } catch (er) {\n throw this.#resolveError(\n spec,\n options,\n 'remote tar unpack failed',\n { cause: er },\n )\n }\n return r\n }\n case 'file': {\n // if it's a directory, then \"extract\" means \"symlink\"\n const { file } = f\n /* c8 ignore start - asserted in resolve() */\n if (file === undefined)\n throw this.#resolveError(spec, options, 'no file path')\n /* c8 ignore stop */\n const path = pathResolve(from, file)\n const st = await stat(path)\n if (st.isFile()) {\n try {\n await this.tarPool.unpack(\n await this.tarball(spec, options),\n target,\n )\n } catch (er) {\n throw this.#resolveError(\n spec,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n } else if (st.isDirectory()) {\n const rel = relative(dirname(target), path)\n await symlink(rel, target, 'dir')\n /* c8 ignore start */\n } else {\n throw this.#resolveError(\n spec,\n options,\n 'file: specifier does not resolve to directory or tarball',\n )\n }\n /* c8 ignore stop */\n return r\n }\n case 'workspace': {\n const ws = this.#getWS(spec, options)\n const rel = relative(dirname(target), ws.fullpath)\n await symlink(rel, target, 'dir')\n return r\n }\n }\n }\n\n #getWS(spec: Spec, options: PackageInfoClientRequestOptions) {\n const { workspace } = spec\n /* c8 ignore start - asserted in resolve() */\n if (workspace === undefined)\n throw this.#resolveError(spec, options, 'no workspace ID')\n /* c8 ignore stop */\n if (!this.monorepo) {\n throw this.#resolveError(\n spec,\n options,\n 'Not in a monorepo, cannot resolve workspace spec',\n )\n }\n const ws = this.monorepo.get(workspace)\n if (!ws) {\n throw this.#resolveError(spec, options, 'workspace not found', {\n wanted: workspace,\n })\n }\n return ws\n }\n\n /**\n * Return the manifest cache key for a spec and the current options.\n */\n #manifestCacheKey(\n spec: Spec,\n options: PackageInfoClientRequestOptions,\n ): string {\n let extra = ''\n if (options['node-version']) {\n extra += `${delimiter}node-version:${options['node-version']}`\n }\n if (options.os) {\n extra += `${delimiter}os:${options.os}`\n }\n if (options.arch) {\n extra += `${delimiter}arch:${options.arch}`\n }\n return encodeURIComponent(\n `${spec.registry}${delimiter}${spec}${extra}`,\n )\n }\n\n /**\n * Conditionally return the path to the manifest cache file. The logic\n * to determine if caching should be skipped aligns with `pickManifest`\n * and is used to avoid caching manifest results that can be variable.\n */\n _manifestCachePath(\n spec: Spec,\n options: PackageInfoClientRequestOptions,\n ): string | undefined {\n if (options.before) {\n return\n }\n // if the final resolved spec is either a dist tag or something that\n // matches any range (such as a semver range of `*` or empty string)\n // then we skip caching\n const f = spec.final\n if (f.distTag || f.range?.isAny) {\n return\n }\n const key = this.#manifestCacheKey(f, options)\n return pathResolve(this.#cachePath, 'package-info', key)\n }\n\n async #registryManifestRequest(\n spec: Spec,\n options: PackageInfoClientRequestOptions,\n ): Promise<ManifestRegistry> {\n const { registry, name, registrySpec } = spec.final\n /* c8 ignore start */\n if (!spec.range?.isSingle || !registrySpec) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to request manifest',\n { spec },\n )\n }\n /* c8 ignore stop */\n const possibleLeadingChars = ['=', '^', '~', 'v']\n const hasLeadingRange = possibleLeadingChars.some(char =>\n registrySpec.startsWith(char),\n )\n const version =\n hasLeadingRange ? registrySpec.slice(1) : registrySpec\n const pakuURL = new URL(`${name}/${version}`, registry)\n const response = await this.registryClient.request(pakuURL, {\n headers: {\n accept: 'application/json',\n },\n })\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch manifest',\n {\n url: pakuURL,\n response,\n },\n )\n }\n return response.json() as ManifestRegistry\n }\n\n async tarball(\n spec: Spec | string,\n options: PackageInfoClientExtractOptions = {},\n ): Promise<Buffer> {\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const f = spec.final\n\n switch (f.type) {\n case 'registry': {\n const { dist } = await this.manifest(spec, options)\n if (!dist)\n throw this.#resolveError(\n spec,\n options,\n 'no dist object found in manifest',\n )\n\n const { tarball, integrity } = dist\n if (!tarball) {\n throw this.#resolveError(\n spec,\n options,\n 'no tarball found in manifest.dist',\n )\n }\n\n const trustIntegrity =\n this.#trustedIntegrities.get(tarball) === integrity\n\n const response = await this.registryClient.request(tarball, {\n ...options,\n integrity,\n trustIntegrity,\n })\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch tarball',\n { response, url: tarball },\n )\n }\n\n // if we don't already trust it, but it's valid, start trusting it\n if (\n !trustIntegrity &&\n response.checkIntegrity({ spec, url: tarball })\n ) {\n this.#trustedIntegrities.set(tarball, response.integrity)\n }\n\n return response.buffer()\n }\n\n case 'git': {\n const {\n remoteURL,\n gitRemote,\n gitCommittish,\n gitSelectorParsed,\n } = f\n const s: Spec = spec\n if (!remoteURL) {\n if (!gitRemote) {\n throw this.#resolveError(\n spec,\n options,\n 'no remote on git: specifier',\n )\n }\n const { path } = gitSelectorParsed ?? {}\n return await this.#tmpdir(async dir => {\n await clone(gitRemote, gitCommittish, dir + '/package', {\n spec: s,\n })\n let cwd = dir\n if (path !== undefined) {\n const src = pathResolve(dir, 'package', path)\n cwd = dirname(src)\n const pkg = pathResolve(cwd, 'package')\n if (src !== pkg) {\n const rand = randomBytes(6).toString('hex')\n // faster than deleting\n await rename(pkg, pkg + rand).catch(() => {})\n await rename(src, pkg)\n }\n }\n return tarC({ cwd, gzip: true }, ['package']).concat()\n })\n }\n // fallthrough if remoteURL set\n }\n\n case 'remote': {\n const { remoteURL } = f\n if (!remoteURL) {\n throw this.#resolveError(spec, options)\n }\n const response = await this.registryClient.request(remoteURL)\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch URL',\n { response, url: remoteURL },\n )\n }\n return response.buffer()\n }\n\n case 'file': {\n const { file } = f\n if (file === undefined)\n throw this.#resolveError(spec, options, 'no file path')\n const { from = this.#projectRoot } = options\n const path = pathResolve(from, file)\n const st = await stat(path)\n if (st.isDirectory()) {\n const p = dirname(path)\n const b = basename(path)\n // TODO: Pack properly, ignore stuff, bundleDeps, etc\n return tarC({ cwd: p, gzip: true }, [b]).concat()\n }\n return readFile(path)\n }\n\n case 'workspace': {\n // TODO: Pack properly, ignore stuff, bundleDeps, etc\n const ws = this.#getWS(spec, options)\n const p = dirname(ws.fullpath)\n const b = basename(ws.fullpath)\n return tarC({ cwd: p, gzip: true }, [b]).concat()\n }\n }\n }\n\n async manifest(\n spec: Spec | string,\n options: PackageInfoClientRequestOptions = {},\n ) {\n const { from = this.#projectRoot } = options\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const f = spec.final\n\n switch (f.type) {\n case 'registry': {\n // Check if manifest is cached, if so just return it earlier\n const cachePath = this._manifestCachePath(spec, options)\n if (cachePath) {\n try {\n // Cache file exists, read and return it\n const cached = await readFile(cachePath, 'utf8')\n const json = JSON.parse(cached) as Manifest & {\n __VLT_MANIFEST_CACHE_TIMESTAMP?: number\n }\n // retrieve timestamp to check if cache is still valid\n const timestamp = json.__VLT_MANIFEST_CACHE_TIMESTAMP\n delete json.__VLT_MANIFEST_CACHE_TIMESTAMP\n // removes the cache file if older than its maximum age\n if (\n timestamp != null &&\n timestamp < this.#manifestCacheMinAge\n ) {\n void unlink(cachePath).catch(() => {})\n throw new Error('manifest cache expired')\n }\n return json\n } catch {\n // Cache miss, fetch from packument\n }\n }\n\n const mani =\n spec.range?.isSingle ?\n await this.#registryManifestRequest(spec, options)\n : pickManifest(\n await this.packument(f, options),\n spec,\n options,\n )\n if (!mani) throw this.#resolveError(spec, options)\n const { integrity, tarball } =\n mani.dist ?? /* c8 ignore next */ {}\n if (isIntegrity(integrity) && tarball) {\n const registryOrigin = new URL(String(f.registry)).origin\n const tgzOrigin = new URL(tarball).origin\n // if it comes from the same origin, trust the integrity\n if (tgzOrigin === registryOrigin) {\n this.#trustedIntegrities.set(tarball, integrity)\n }\n }\n\n // Cache the manifest data\n if (cachePath) {\n const json = JSON.stringify({\n ...mani,\n // append a timestamp to the manifest so that we can quickly\n // check if the cache is still valid when loading it\n __VLT_MANIFEST_CACHE_TIMESTAMP: Date.now(),\n })\n void writeFile(cachePath, json, 'utf8').catch(\n (err: unknown) => {\n // in case the cache directory doesn't exist\n // just create it and retry\n if (\n err instanceof Error &&\n 'code' in err &&\n err.code === 'ENOENT'\n ) {\n void mkdir(dirname(cachePath), {\n recursive: true,\n }).then(() => {\n void writeFile(cachePath, json, 'utf8')\n })\n }\n },\n )\n }\n\n return mani\n }\n\n case 'git': {\n const {\n gitRemote,\n gitCommittish,\n remoteURL,\n gitSelectorParsed,\n } = f\n if (!remoteURL) {\n const s = spec\n if (!gitRemote)\n throw this.#resolveError(spec, options, 'no git remote')\n return await this.#tmpdir(async dir => {\n await clone(gitRemote, gitCommittish, dir, { spec: s })\n const { path } = gitSelectorParsed ?? {}\n const pkgDir =\n path !== undefined ? pathResolve(dir, path) : dir\n return this.packageJson.read(pkgDir)\n })\n }\n // fallthrough to remote\n }\n\n case 'remote': {\n const { remoteURL } = f\n if (!remoteURL) {\n throw this.#resolveError(\n spec,\n options,\n 'no remoteURL on remote specifier',\n )\n }\n const s = spec\n return await this.#tmpdir(async dir => {\n const response =\n await this.registryClient.request(remoteURL)\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n s,\n options,\n 'failed to fetch URL',\n { response, url: remoteURL },\n )\n }\n const buf = response.buffer()\n\n // Compute integrity for remote/git-with-tarball deps\n const computed = ssri\n .fromData(buf, { algorithms: ['sha512'] })\n .toString()\n\n try {\n await this.tarPool.unpack(buf, dir)\n } catch (er) {\n throw this.#resolveError(\n s,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n\n // return manifest with computed integrity\n const mani = this.packageJson.read(dir)\n mani.dist = { integrity: computed as Integrity }\n return mani\n })\n }\n\n case 'file': {\n const { file } = f\n if (file === undefined)\n throw this.#resolveError(spec, options, 'no file path')\n const path = pathResolve(from, file)\n const st = await stat(path)\n if (st.isDirectory()) {\n return this.packageJson.read(path)\n }\n const s = spec\n return await this.#tmpdir(async dir => {\n try {\n await this.tarPool.unpack(await readFile(path), dir)\n } catch (er) {\n throw this.#resolveError(\n s,\n options,\n 'tar unpack failed',\n { cause: er },\n )\n }\n return this.packageJson.read(dir)\n })\n }\n\n case 'workspace': {\n return this.#getWS(spec, options).manifest\n }\n }\n }\n\n async packument(\n spec: Spec | string,\n options: PackageInfoClientRequestOptions = {},\n ): Promise<Packument> {\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n const f = spec.final\n switch (f.type) {\n // RevDoc is the equivalent of a packument for a git repo\n case 'git': {\n const { gitRemote } = f\n if (!gitRemote) {\n throw this.#resolveError(\n spec,\n options,\n 'git remote could not be determined',\n )\n }\n const revDoc = await revs(gitRemote, {\n cwd: this.options.projectRoot,\n })\n if (!revDoc) throw this.#resolveError(spec, options)\n return asPackument(revDoc)\n }\n\n // these are all faked packuments\n case 'file':\n case 'workspace':\n case 'remote': {\n const manifest = await this.manifest(f, options)\n return {\n name: manifest.name ?? '',\n 'dist-tags': {\n latest: manifest.version ?? '',\n },\n versions: {\n [manifest.version ?? '']: manifest as Manifest,\n },\n }\n }\n\n case 'registry': {\n const { registry, name } = f\n const pakuURL = new URL(name, registry)\n const response = await this.registryClient.request(pakuURL, {\n headers: {\n accept: 'application/json',\n },\n })\n if (response.statusCode !== 200) {\n throw this.#resolveError(\n spec,\n options,\n 'failed to fetch packument',\n {\n url: pakuURL,\n response,\n },\n )\n }\n return response.json() as Packument\n }\n }\n }\n\n async resolve(\n spec: Spec | string,\n options: PackageInfoClientRequestOptions = {},\n ): Promise<Resolution> {\n const memoKey = String(spec)\n if (typeof spec === 'string')\n spec = Spec.parse(spec, this.options)\n\n const memo = this.#resolutions.get(memoKey)\n if (memo) return memo\n const f = spec.final\n\n switch (f.type) {\n case 'file': {\n const { file } = f\n if (!file || !f.file) {\n throw this.#resolveError(\n spec,\n options,\n 'no path on file: specifier',\n )\n }\n const { from = this.#projectRoot } = options\n const resolved = pathResolve(from, f.file)\n const r = { resolved, spec }\n this.#resolutions.set(memoKey, r)\n return r\n }\n\n case 'remote': {\n const { remoteURL } = f\n if (!remoteURL)\n throw this.#resolveError(\n spec,\n options,\n 'no URL in remote specifier',\n )\n const r = { resolved: remoteURL, spec }\n this.#resolutions.set(memoKey, r)\n return r\n }\n\n case 'workspace': {\n const ws = this.#getWS(spec, options)\n return {\n resolved: ws.fullpath,\n spec,\n }\n }\n\n case 'registry': {\n const mani = await this.manifest(spec, options)\n if (mani.dist) {\n const { integrity, tarball, signatures } = mani.dist\n if (tarball) {\n const r = {\n resolved: tarball,\n integrity,\n signatures,\n spec,\n }\n this.#resolutions.set(memoKey, r)\n return r\n }\n }\n throw this.#resolveError(spec, options)\n }\n\n case 'git': {\n const { gitRemote, remoteURL, gitSelectorParsed } = f\n if (remoteURL && gitSelectorParsed?.path === undefined) {\n // known git host with a tarball download endpoint\n const r = { resolved: remoteURL, spec }\n this.#resolutions.set(memoKey, r)\n return r\n }\n if (!gitRemote) {\n throw this.#resolveError(\n spec,\n options,\n 'no remote on git specifier',\n )\n }\n const rev = await gitResolve(gitRemote, f.gitCommittish, {\n spec,\n })\n if (rev) {\n const r = {\n resolved: `${gitRemote}#${rev.sha}`,\n spec,\n }\n if (gitSelectorParsed) {\n r.resolved += Object.entries(gitSelectorParsed)\n .filter(([_, v]) => v)\n .map(([k, v]) => `::${k}:${v}`)\n .join('')\n }\n this.#resolutions.set(memoKey, r)\n return r\n }\n // have to actually clone somewhere\n const s: Spec = spec\n return this.#tmpdir(async tmpdir => {\n const sha = await clone(\n gitRemote,\n s.gitCommittish,\n tmpdir,\n {\n spec: s,\n },\n )\n const r = {\n resolved: `${gitRemote}#${sha}`,\n spec: s,\n }\n this.#resolutions.set(memoKey, r)\n return r\n })\n }\n }\n }\n\n async #tmpdir<T>(fn: (dir: string) => Promise<T>): Promise<T> {\n const p = `package-info/${randomBytes(6).toString('hex')}`\n const dir = xdg.runtime(p)\n try {\n return await fn(dir)\n } finally {\n // intentionally do not await\n void rm(dir, { recursive: true, force: true })\n }\n }\n\n // error resolving\n #resolveError(\n spec?: Spec,\n options: PackageInfoClientRequestOptions = {},\n message = 'Could not resolve',\n extra: ErrorCauseOptions = {},\n ) {\n const { from = this.#projectRoot } = options\n const er = error(\n message,\n {\n code: 'ERESOLVE',\n spec,\n from,\n ...extra,\n },\n this.#resolveError,\n )\n return er\n }\n}\n"]} |
| { | ||
| "type": "module" | ||
| } |
| import { rename as fsRename } from 'node:fs/promises'; | ||
| export declare const rename: typeof fsRename; | ||
| //# sourceMappingURL=rename.d.ts.map |
| {"version":3,"file":"rename.d.ts","sourceRoot":"","sources":["../../src/rename.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAM,MAAM,kBAAkB,CAAA;AACzD,eAAO,MAAM,MAAM,iBAqBhB,CAAA"} |
| /** | ||
| * On posix systems, rename is atomic and will clobber anything in its way | ||
| * However, on Windows, it can fail with the rather unhelpful EPERM error if | ||
| * the target directory is not removed in time or is currently in use. | ||
| * | ||
| * While true atomic semantics is not available on Windows in this case, we can | ||
| * at least implement the posix overwrite semantics by explicitly removing the | ||
| * target when this error occurs. | ||
| * | ||
| * This is only relevant when renaming *directories*, since files will | ||
| * generally not raise problems. When/if we rename directories outside of | ||
| * package-info, this can be moved to its own shared module. | ||
| * @module | ||
| */ | ||
| const { platform } = process; | ||
| import { rename as fsRename, rm } from 'node:fs/promises'; | ||
| export const rename = platform !== 'win32' ? fsRename : (async function (oldPath, newPath) { | ||
| let retries = 3; | ||
| const retry = async (er) => { | ||
| if (retries > 0 && | ||
| er.code === 'EPERM') { | ||
| retries--; | ||
| await rm(newPath, { recursive: true, force: true }); | ||
| return fsRename(oldPath, newPath).then(() => { }, retry); | ||
| } | ||
| else { | ||
| throw er; | ||
| } | ||
| }; | ||
| return fsRename(oldPath, newPath).then(() => { }, retry); | ||
| }); | ||
| //# sourceMappingURL=rename.js.map |
| {"version":3,"file":"rename.js","sourceRoot":"","sources":["../../src/rename.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;AAE5B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AACzD,MAAM,CAAC,MAAM,MAAM,GACjB,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAChC,KAAK,WACH,OAAiB,EACjB,OAAiB;IAEjB,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,MAAM,KAAK,GAAG,KAAK,EAAE,EAAW,EAAiB,EAAE;QACjD,IACE,OAAO,GAAG,CAAC;YACV,EAA4B,CAAC,IAAI,KAAK,OAAO,EAC9C,CAAC;YACD,OAAO,EAAE,CAAA;YACT,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACnD,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,CAAC,CAAA;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAA;QACV,CAAC;IACH,CAAC,CAAA;IACD,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,CAAC,CAAA;AACzD,CAAC,CACF,CAAA","sourcesContent":["/**\n * On posix systems, rename is atomic and will clobber anything in its way\n * However, on Windows, it can fail with the rather unhelpful EPERM error if\n * the target directory is not removed in time or is currently in use.\n *\n * While true atomic semantics is not available on Windows in this case, we can\n * at least implement the posix overwrite semantics by explicitly removing the\n * target when this error occurs.\n *\n * This is only relevant when renaming *directories*, since files will\n * generally not raise problems. When/if we rename directories outside of\n * package-info, this can be moved to its own shared module.\n * @module\n */\nconst { platform } = process\nimport type { PathLike } from 'node:fs'\nimport { rename as fsRename, rm } from 'node:fs/promises'\nexport const rename =\n platform !== 'win32' ? fsRename : (\n async function (\n oldPath: PathLike,\n newPath: PathLike,\n ): Promise<void> {\n let retries = 3\n const retry = async (er: unknown): Promise<void> => {\n if (\n retries > 0 &&\n (er as NodeJS.ErrnoException).code === 'EPERM'\n ) {\n retries--\n await rm(newPath, { recursive: true, force: true })\n return fsRename(oldPath, newPath).then(() => {}, retry)\n } else {\n throw er\n }\n }\n return fsRename(oldPath, newPath).then(() => {}, retry)\n }\n )\n"]} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
13
-7.14%95389
-0.33%11
-8.33%9
12.5%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated
Updated