@stencila/jesta
Version:
Stencila plugin for executable documents using JavaScript
125 lines (124 loc) • 4.18 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.readHttp = exports.readFile = exports.readStdio = exports.read = exports.schema = void 0;
const content_type_1 = __importDefault(require("content-type"));
const fs_1 = __importDefault(require("fs"));
const mime_1 = __importDefault(require("mime"));
const path_1 = __importDefault(require("path"));
const util_1 = require("util");
const errors_1 = require("./util/errors");
const http_1 = require("./util/http");
exports.schema = {
title: 'read',
description: 'Read content from a URL.',
required: ['input'],
properties: {
input: {
description: 'The URL to read content from.',
type: 'string',
pattern: '^(file|https?|stdio|stdin|string)://.*',
},
cache: {
description: 'Use and store cached content (for http:// URLs only).',
type: 'boolean',
},
},
};
/**
* Read content from a URL.
*
* For HTTP/S URLs this function complies with [RFC 7234](http://httpwg.org/specs/rfc7234.html)
* for caching of requests. Use `force` to ignore any cached content that may
* exist on the machine for the URL.
*
* @param input The URL to read.
* @param cache Should any cached content be ignored? For remote URLs only.
* @returns The content that was read.
*/
async function read(input, cache = true) {
const match = /^([a-z]{2,6}):\/\//.exec(input);
if (match) {
const protocol = match[1];
switch (protocol) {
case 'string':
return [input.slice(9), undefined];
case 'stdio':
case 'stdin':
return [await readStdio(), undefined];
case 'file':
return readFile(input.slice(7));
case 'http':
case 'https':
return readHttp(input, cache);
default:
throw new errors_1.CapabilityError(`read over protocol "${protocol}"`);
}
}
throw new errors_1.CapabilityError(`read from URL "${input.slice(0, 500)}"`);
}
exports.read = read;
read.schema = exports.schema;
/**
* Read content from standard input
*
* @returns The content
*/
async function readStdio() {
const stream = process.stdin;
stream.setEncoding('utf8');
return new Promise((resolve, reject) => {
let data = '';
stream.on('data', (chunk) => (data += chunk));
stream.on('end', () => resolve(data));
stream.on('error', (error) => reject(error));
});
}
exports.readStdio = readStdio;
/**
* Read content from the local file system
*
* @param filePath The path to the file to read
* @returns A tuple of the content and its format
*/
async function readFile(filePath) {
const content = await util_1.promisify(fs_1.default.readFile)(filePath, 'utf8');
const { ext } = path_1.default.parse(filePath);
const format = ext !== '' ? ext.slice(1) : undefined;
return [content, format];
}
exports.readFile = readFile;
/**
* Read content from a HTTP/S URL
*
* The format is determined from the `Content-Type` header if present,
* guessed from the URL's path segment if not.
*
* @param url The URL to fetch
* @param caching Should a cache be used to retrieve / store content.
* @returns A tuple of the content and its format
*/
async function readHttp(url, caching = true) {
var _a;
const response = await http_1.get(url, caching ? {} : { cache: false });
const content = response.body;
let mediaType;
try {
;
({ type: mediaType } = content_type_1.default.parse(response));
}
catch (error) { }
let format;
if (mediaType !== undefined) {
format = (_a = mime_1.default.getExtension(mediaType)) !== null && _a !== void 0 ? _a : undefined;
}
else {
const { pathname } = new URL(url);
const ext = path_1.default.extname(pathname);
format = ext !== '' ? ext.slice(1) : undefined;
}
return [content, format];
}
exports.readHttp = readHttp;