Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

file-fetch

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

file-fetch - npm Package Compare versions

Comparing version 1.5.0 to 1.6.0

test/create.js

101

index.js
const fs = require('fs')
const { access } = require('fs/promises')
const path = require('path')
const { promisify } = require('util')
const { URL } = require('url')
const { Readable } = require('stream')

@@ -11,16 +10,16 @@ const getStream = require('get-stream')

const access = promisify(fs.access)
const { R_OK } = fs.constants
function decodeIRI (iri) {
function decodeIRI (iri, baseDir, baseURL) {
// IRIs without file scheme are used directly
if (!iri.startsWith('file:')) {
return iri
if (!iri.startsWith('file:') && !baseURL) {
return path.join(baseDir, iri)
}
const pathname = decodeURIComponent(new URL(iri).pathname)
const pathname = decodeURIComponent(new URL(iri, baseURL).pathname)
// remove the leading slash for IRIs with file scheme and relative path
if (!iri.startsWith('file:/')) {
return pathname.split('/').slice(1).join('/')
if (!iri.startsWith('file:/') &&
(!baseURL || !pathname.startsWith('/'))) {
return './' + (path.join(baseDir, '.' + pathname))
}

@@ -42,58 +41,64 @@

async function fetch (iri, { body, contentTypeLookup = contentType, method = 'GET' } = {}) {
method = method.toUpperCase()
function create ({ baseDir = '', baseURL } = {}) {
return async function fetch (iri, { body, contentTypeLookup = contentType, method = 'GET' } = {}) {
method = method.toUpperCase()
const pathname = decodeIRI(iri)
const extension = path.extname(pathname)
const pathname = decodeIRI(iri, baseDir, baseURL)
const extension = path.extname(pathname)
if (method === 'GET') {
return new Promise((resolve) => {
const stream = fs.createReadStream(pathname)
if (method === 'GET') {
return new Promise((resolve) => {
const stream = fs.createReadStream(pathname)
stream.on('error', () => {
resolve(response(404, new ReadableError(new Error('File not found'))))
})
stream.on('error', () => {
resolve(response(404, new ReadableError(new Error('File not found'))))
})
stream.on('open', () => {
resolve(response(200, stream, {
'content-type': contentTypeLookup(extension) || contentType(extension)
}))
stream.on('open', () => {
resolve(response(200, stream, {
'content-type': contentTypeLookup(extension) || contentType(extension)
}))
})
})
})
}
if (method === 'HEAD') {
try {
await access(pathname, R_OK)
} catch (error) {
return response(404, new ReadableError(new Error('File not found')))
}
const stream = new Readable()
stream.push(null)
if (method === 'HEAD') {
try {
await access(pathname, R_OK)
} catch (error) {
return response(404, new ReadableError(new Error('File not found')))
}
return response(200, stream, {
'content-type': contentTypeLookup(extension) || contentType(extension)
})
}
const stream = new Readable()
stream.push(null)
if (method === 'PUT') {
if (!body) {
return response(406, new ReadableError(new Error('body required')))
return response(200, stream, {
'content-type': contentTypeLookup(extension) || contentType(extension)
})
}
return new Promise((resolve) => {
body.pipe(fs.createWriteStream(pathname)).on('finish', () => {
resolve(response(201))
}).on('error', (err) => {
resolve(response(500, new ReadableError(err)))
if (method === 'PUT') {
if (!body) {
return response(406, new ReadableError(new Error('body required')))
}
return new Promise((resolve) => {
body.pipe(fs.createWriteStream(pathname)).on('finish', () => {
resolve(response(201))
}).on('error', (err) => {
resolve(response(500, new ReadableError(err)))
})
})
})
}
return response(405, new ReadableError(new Error('method not allowed')))
}
return response(405, new ReadableError(new Error('method not allowed')))
}
const fetch = create()
fetch.Headers = Headers
fetch.create = create
module.exports = fetch
{
"name": "file-fetch",
"version": "1.5.0",
"version": "1.6.0",
"description": "fetch for read and write access to the local file system",

@@ -20,2 +20,12 @@ "main": "index.js",

],
"nyc": {
"statements": 100,
"branches": 100,
"lines": 100,
"functions": 100,
"check-coverage": true
},
"engines": {
"node": ">=10.0.0"
},
"author": "Thomas Bergwinkl <bergi@axolotlfarm.org> (https://www.bergnet.org/people/bergi/card#me)",

@@ -31,12 +41,12 @@ "contributors": [

"dependencies": {
"get-stream": "^5.1.0",
"mime-types": "^2.1.25",
"node-fetch": "^2.6.0",
"get-stream": "^6.0.1",
"mime-types": "^2.1.30",
"node-fetch": "^2.6.1",
"readable-error": "^1.0.0"
},
"devDependencies": {
"mocha": "^6.2.2",
"nyc": "^15.0.0",
"standard": "^14.3.1"
"mocha": "^8.3.2",
"nyc": "^15.1.0",
"standard": "^16.0.3"
}
}

@@ -153,2 +153,24 @@ const fs = require('fs')

it('should return a 200 status but no body with method HEAD and existing file (fallback to contentType)', async () => {
function contentTypeLookup () {
return undefined
}
const pathname = path.join(__dirname, 'support/file.txt')
const res = await fileFetch('file://' + pathname, {
method: 'HEAD',
contentTypeLookup
})
assert.strictEqual(res.status, 200)
res.body.on('data', (chunk) => {
assert(false)
})
return new Promise((resolve) => {
res.body.on('end', () => {
resolve()
})
})
})
it('should return a 404 status with method HEAD and non-existent file', async () => {

@@ -155,0 +177,0 @@ const pathname = path.join(__dirname, 'support/missing.txt')

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc