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.7.0 to 2.0.0

.github/workflows/test.yaml

121

index.js

@@ -1,117 +0,10 @@

/* global URL */
import factory from './factory.js'
import fetch from './fetch.js'
const fs = require('fs')
const path = require('path')
const { promisify } = require('util')
const getStream = require('get-stream')
const { contentType } = require('mime-types')
const { Headers } = require('node-fetch')
const ReadableError = require('readable-error')
const { Readable } = require('readable-stream')
const Headers = globalThis.Headers
const { R_OK } = fs.constants
const access = promisify(fs.access)
const stat = promisify(fs.stat)
function decodeIRI (iri, baseDir, baseURL) {
// IRIs without file scheme are used directly
if (!iri.startsWith('file:') && !baseURL) {
return path.join(baseDir, iri)
}
const pathname = decodeURIComponent(new URL(iri, baseURL).pathname)
// remove the leading slash for IRIs with file scheme and relative path
if (!iri.startsWith('file:/') &&
(!baseURL || !pathname.startsWith('/'))) {
return './' + (path.join(baseDir, '.' + pathname))
}
return pathname
export {
fetch as default,
factory,
Headers
}
async function silentFileSize (pathname) {
try {
return (await stat(pathname)).size
} catch (err) {
return null
}
}
function response (status, body, headers) {
return {
status: status,
ok: status >= 200 && status <= 299,
headers: new Headers(headers),
body: body,
text: async () => getStream(body),
json: async () => JSON.parse(await getStream(body))
}
}
function create ({ baseDir = '', baseURL } = {}) {
return async function fetch (iri, { body, contentTypeLookup = contentType, method = 'GET' } = {}) {
method = method.toUpperCase()
const pathname = decodeIRI(iri, baseDir, baseURL)
const extension = path.extname(pathname)
if (method === 'GET') {
const size = await silentFileSize(pathname)
return new Promise((resolve) => {
const stream = fs.createReadStream(pathname)
stream.on('error', () => {
resolve(response(404, new ReadableError(new Error('File not found'))))
})
stream.on('open', () => {
resolve(response(200, stream, {
'content-length': size.toString(),
'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)
return response(200, stream, {
'content-type': contentTypeLookup(extension) || contentType(extension)
})
}
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')))
}
}
const fetch = create()
fetch.Headers = Headers
fetch.create = create
module.exports = fetch
{
"name": "file-fetch",
"version": "1.7.0",
"version": "2.0.0",
"description": "fetch for read and write access to the local file system",
"type": "module",
"main": "index.js",
"scripts": {
"test": "standard && nyc --reporter=lcov --reporter=text mocha"
"test": "stricter-standard && c8 --reporter=lcov --reporter=text-summary mocha"
},
"repository": {
"type": "git",
"url": "git://github.com/bergos/file-fetch.git"
"url": "https://github.com/bergos/file-fetch.git"
},

@@ -20,9 +21,2 @@ "keywords": [

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

@@ -38,13 +32,13 @@ "contributors": [

"dependencies": {
"get-stream": "^6.0.1",
"mime-types": "^2.1.30",
"node-fetch": "^2.6.1",
"readable-error": "^1.0.0",
"readable-stream": "^3.6.0"
"mime-types": "^2.1.35",
"readable-stream": "^4.4.2",
"stream-chunks": "^1.0.0"
},
"devDependencies": {
"mocha": "^8.4.0",
"nyc": "^15.1.0",
"standard": "^16.0.3"
"c8": "^8.0.1",
"is-stream": "^3.0.0",
"mocha": "^10.2.0",
"stricter-standard": "^0.3.0",
"temp": "^0.9.4"
}
}
# file-fetch
`file-fetch` is a [nodeify-fetch](https://www.npmjs.com/package/nodeify-fetch) compatible fetch for read and write access to the local file system using `file://` URLs (including
[![build status](https://img.shields.io/github/actions/workflow/status/bergos/file-fetch/test.yaml?branch=master)](https://github.com/bergos/file-fetch/actions/workflows/test.yaml)
[![npm version](https://img.shields.io/npm/v/file-fetch.svg)](https://www.npmjs.com/package/file-fetch)
`file-fetch` is a [nodeify-fetch](https://www.npmjs.com/package/nodeify-fetch) compatible fetch for read and write access to the local file system using `file:` URLs and URIs (including
implicit ones using relative paths).

@@ -8,20 +11,122 @@

Only the URL is required to read a file:
### Read
Reading a file from the file system is as easy as fetching it on the Web.
Call `fetch` with the URL, and the content is provided as `Readable` stream in `res.body`.
The example below uses an absolute URL, but relative paths are also supported.
See the [Supported URLs and URIs](#supported-urls-and-uris) section for more details.
```js
const fileFetch = require('file-fetch')
import fetch from 'file-fetch'
fileFetch('file://etc/hosts').then((res) => {
res.body.pipe(stdout)
})
const res = await fetch(new URL('example.js', import.meta.url))
res.body.pipe(process.stdout)
```
To write files the method `PUT` must be used and readable stream must be given as body:
It's also possible to handle the content without streams.
The async `res.text()` method returns the whole content as a string.
```js
fileFetch('file://tmp/example.log', {
import fetch from 'file-fetch'
const res = await fetch(new URL('example.js', import.meta.url))
console.log(await res.text())
```
A similar method `res.json()` is available to parse JSON content and return the parsed result.
```js
import fetch from 'file-fetch'
const res = await fetch(new URL('example.js', import.meta.url))
console.log(await res.json())
```
### Write
Writing content to a file is done with the same function but with the `PUT` method.
The content must be provided as a `string` or a `Readable` stream object.
```js
import fetch from 'file-fetch'
await fetch('file:///tmp/example.log', {
method: 'PUT',
body: stream
body: 'test'
})
```
```js
import fetch from 'file-fetch'
import { Readable } from 'readable-stream'
await fetch('file:///tmp/example.log', {
method: 'PUT',
body: Readable.from(['test'])
})
```
## Options
`file-fetch` supports the following non-standard options:
- `baseURL`: A `string` or `URL` used to resolve relative paths and URIs.
- `contentType`: A `string` or `function` to determine the media type based on the file extension or a fixed value.
It can be useful if file extensions or media types not covered by [mime-db](https://www.npmjs.com/package/mime-db) are required.
## Custom fetch with fixed baseURL or contentType lookup
Custom fetch instances can be useful if requests should be processed with relative paths to a directory that is not the current working directory.
The `contentType` argument can also be predefined for the instance.
The example below shows how to set the `baseURL` to a relative path of the current script and how to use a custom `contentType` function:
```js
import { factory as fetchFactory } from 'file-fetch'
const baseURL = new URL('examples', import.meta.url)
const contentType = ext => ext === 'json' ? 'application/ld+json' : 'application/octet-stream'
const fetch = fetchFactory({ baseURL, contentType })
const res = await fetch('example.js')
const text = await res.text()
```
## Supported URLs and URIs
Different styles of URLs and URIs are supported.
### Absolute URLs
An absolute URL for a `file` schema must start with `file:///`.
No further resolve logic is used.
Example:
```
file:///home/user/tmp/content.txt
```
### URIs
URIs are supported for use cases where a `file` scheme is required to distinguish identifiers by scheme and if relative paths are required.
The [relative paths](#relative-paths) logic is used to resolve the full URL.
Example:
```
file:tmp/content.txt
```
### Relative paths
Relative paths are resolved with the given `baseURL` or, if not given, with the working directory.
Example:
```
tmp/content.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