12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- const { resolve } = require('node:path')
- const { stat, chmod } = require('node:fs/promises')
- const cacache = require('cacache')
- const fsm = require('fs-minipass')
- const Fetcher = require('./fetcher.js')
- const _ = require('./util/protected.js')
- class FileFetcher extends Fetcher {
- constructor (spec, opts) {
- super(spec, opts)
- // just the fully resolved filename
- this.resolved = this.spec.fetchSpec
- }
- get types () {
- return ['file']
- }
- manifest () {
- if (this.package) {
- return Promise.resolve(this.package)
- }
- // have to unpack the tarball for this.
- return cacache.tmp.withTmp(this.cache, this.opts, dir =>
- this.extract(dir)
- .then(() => this[_.readPackageJson](dir))
- .then(mani => this.package = {
- ...mani,
- _integrity: this.integrity && String(this.integrity),
- _resolved: this.resolved,
- _from: this.from,
- }))
- }
- #exeBins (pkg, dest) {
- if (!pkg.bin) {
- return Promise.resolve()
- }
- return Promise.all(Object.keys(pkg.bin).map(async k => {
- const script = resolve(dest, pkg.bin[k])
- // Best effort. Ignore errors here, the only result is that
- // a bin script is not executable. But if it's missing or
- // something, we just leave it for a later stage to trip over
- // when we can provide a more useful contextual error.
- try {
- const st = await stat(script)
- const mode = st.mode | 0o111
- if (mode === st.mode) {
- return
- }
- await chmod(script, mode)
- } catch {
- // Ignore errors here
- }
- }))
- }
- extract (dest) {
- // if we've already loaded the manifest, then the super got it.
- // but if not, read the unpacked manifest and chmod properly.
- return super.extract(dest)
- .then(result => this.package ? result
- : this[_.readPackageJson](dest).then(pkg =>
- this.#exeBins(pkg, dest)).then(() => result))
- }
- [_.tarballFromResolved] () {
- // create a read stream and return it
- return new fsm.ReadStream(this.resolved)
- }
- packument () {
- // simulate based on manifest
- return this.manifest().then(mani => ({
- name: mani.name,
- 'dist-tags': {
- [this.defaultTag]: mani.version,
- },
- versions: {
- [mani.version]: {
- ...mani,
- dist: {
- tarball: `file:${this.resolved}`,
- integrity: this.integrity && String(this.integrity),
- },
- },
- },
- }))
- }
- }
- module.exports = FileFetcher
|