2018-04-06 14:51:52 +01:00
|
|
|
// originally based off of https://github.com/gulpjs/vinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
const invariant = require('invariant');
|
|
|
|
const { of, from, isObservable } = require('rxjs');
|
|
|
|
const { map, switchMap } = require('rxjs/operators');
|
2018-09-30 11:37:19 +01:00
|
|
|
|
2020-06-13 11:27:15 +02:00
|
|
|
function isPromise(value) {
|
|
|
|
return (
|
|
|
|
value &&
|
|
|
|
typeof value.subscribe !== 'function' &&
|
|
|
|
typeof value.then === 'function'
|
|
|
|
);
|
|
|
|
}
|
2018-04-06 14:51:52 +01:00
|
|
|
|
2020-06-13 11:27:15 +02:00
|
|
|
function castToObservable(maybe) {
|
2018-09-30 11:37:19 +01:00
|
|
|
if (isObservable(maybe)) {
|
2018-04-06 14:51:52 +01:00
|
|
|
return maybe;
|
|
|
|
}
|
|
|
|
if (isPromise(maybe)) {
|
2018-10-06 02:36:38 +03:00
|
|
|
return from(maybe);
|
2018-04-06 14:51:52 +01:00
|
|
|
}
|
2018-09-30 11:37:19 +01:00
|
|
|
return of(maybe);
|
2018-04-06 14:51:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// createFileStream(
|
|
|
|
// files: [...PolyVinyl]
|
|
|
|
// ) => Observable[...Observable[...PolyVinyl]]
|
2020-06-13 11:27:15 +02:00
|
|
|
function createFileStream(files = []) {
|
2018-09-30 11:37:19 +01:00
|
|
|
return of(from(files));
|
2018-04-06 14:51:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Observable::pipe(
|
|
|
|
// project(
|
|
|
|
// file: PolyVinyl
|
|
|
|
// ) => PolyVinyl|Observable[PolyVinyl]|Promise[PolyVinyl]
|
|
|
|
// ) => Observable[...Observable[...PolyVinyl]]
|
2020-06-13 11:27:15 +02:00
|
|
|
function pipe(project) {
|
2018-04-06 14:51:52 +01:00
|
|
|
const source = this;
|
2018-09-30 11:37:19 +01:00
|
|
|
return source.pipe(
|
|
|
|
map(files => {
|
|
|
|
return files.pipe(switchMap(file => castToObservable(project(file))));
|
|
|
|
})
|
2018-04-06 14:51:52 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// interface PolyVinyl {
|
|
|
|
// source: String,
|
|
|
|
// contents: String,
|
|
|
|
// name: String,
|
|
|
|
// ext: String,
|
|
|
|
// path: String,
|
|
|
|
// key: String,
|
|
|
|
// head: String,
|
|
|
|
// tail: String,
|
|
|
|
// history: [...String],
|
|
|
|
// error: Null|Object|Error
|
|
|
|
// }
|
|
|
|
|
|
|
|
// createPoly({
|
|
|
|
// name: String,
|
|
|
|
// ext: String,
|
|
|
|
// contents: String,
|
|
|
|
// history?: [...String],
|
|
|
|
// }) => PolyVinyl, throws
|
2020-06-13 11:27:15 +02:00
|
|
|
function createPoly({ name, ext, contents, history, ...rest } = {}) {
|
2018-04-06 14:51:52 +01:00
|
|
|
invariant(typeof name === 'string', 'name must be a string but got %s', name);
|
|
|
|
|
|
|
|
invariant(typeof ext === 'string', 'ext must be a string, but was %s', ext);
|
|
|
|
|
|
|
|
invariant(
|
|
|
|
typeof contents === 'string',
|
|
|
|
'contents must be a string but got %s',
|
|
|
|
contents
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
...rest,
|
2019-01-09 03:39:05 +03:00
|
|
|
history: Array.isArray(history) ? history : [name + '.' + ext],
|
2018-04-06 14:51:52 +01:00
|
|
|
name,
|
|
|
|
ext,
|
|
|
|
path: name + '.' + ext,
|
|
|
|
key: name + ext,
|
|
|
|
contents,
|
|
|
|
error: null
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// isPoly(poly: Any) => Boolean
|
2020-06-13 11:27:15 +02:00
|
|
|
function isPoly(poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
return (
|
|
|
|
poly &&
|
|
|
|
typeof poly.contents === 'string' &&
|
|
|
|
typeof poly.name === 'string' &&
|
|
|
|
typeof poly.ext === 'string' &&
|
|
|
|
Array.isArray(poly.history)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkPoly(poly: Any) => Void, throws
|
2020-06-13 11:27:15 +02:00
|
|
|
function checkPoly(poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
invariant(
|
|
|
|
isPoly(poly),
|
|
|
|
'function should receive a PolyVinyl, but got %s',
|
|
|
|
poly
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// isEmpty(poly: PolyVinyl) => Boolean, throws
|
2020-06-13 11:27:15 +02:00
|
|
|
function isEmpty(poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
checkPoly(poly);
|
|
|
|
return !!poly.contents;
|
|
|
|
}
|
|
|
|
|
|
|
|
// setContent(contents: String, poly: PolyVinyl) => PolyVinyl
|
|
|
|
// setContent will loose source if set
|
2020-06-13 11:27:15 +02:00
|
|
|
function setContent(contents, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
checkPoly(poly);
|
|
|
|
return {
|
|
|
|
...poly,
|
|
|
|
contents,
|
|
|
|
source: null
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// setExt(ext: String, poly: PolyVinyl) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function setExt(ext, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
checkPoly(poly);
|
|
|
|
const newPoly = {
|
|
|
|
...poly,
|
|
|
|
ext,
|
|
|
|
path: poly.name + '.' + ext,
|
|
|
|
key: poly.name + ext
|
|
|
|
};
|
|
|
|
newPoly.history = [...poly.history, newPoly.path];
|
|
|
|
return newPoly;
|
|
|
|
}
|
|
|
|
|
|
|
|
// setName(name: String, poly: PolyVinyl) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function setName(name, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
checkPoly(poly);
|
|
|
|
const newPoly = {
|
|
|
|
...poly,
|
|
|
|
name,
|
|
|
|
path: name + '.' + poly.ext,
|
|
|
|
key: name + poly.ext
|
|
|
|
};
|
|
|
|
newPoly.history = [...poly.history, newPoly.path];
|
|
|
|
return newPoly;
|
|
|
|
}
|
|
|
|
|
|
|
|
// setError(error: Object, poly: PolyVinyl) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function setError(error, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
invariant(
|
|
|
|
typeof error === 'object',
|
|
|
|
'error must be an object or null, but got %',
|
|
|
|
error
|
|
|
|
);
|
|
|
|
checkPoly(poly);
|
|
|
|
return {
|
|
|
|
...poly,
|
|
|
|
error
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// clearHeadTail(poly: PolyVinyl) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function clearHeadTail(poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
checkPoly(poly);
|
|
|
|
return {
|
|
|
|
...poly,
|
|
|
|
head: '',
|
|
|
|
tail: ''
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// appendToTail (tail: String, poly: PolyVinyl) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function appendToTail(tail, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
checkPoly(poly);
|
|
|
|
return {
|
|
|
|
...poly,
|
|
|
|
tail: poly.tail.concat(tail)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function compileHeadTail(padding = '', poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
return clearHeadTail(
|
|
|
|
transformContents(
|
|
|
|
() => [poly.head, poly.contents, poly.tail].join(padding),
|
|
|
|
poly
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// transformContents(
|
|
|
|
// wrap: (contents: String) => String,
|
|
|
|
// poly: PolyVinyl
|
|
|
|
// ) => PolyVinyl
|
|
|
|
// transformContents will keep a copy of the original
|
|
|
|
// code in the `source` property. If the original polyvinyl
|
|
|
|
// already contains a source, this version will continue as
|
|
|
|
// the source property
|
2020-06-13 11:27:15 +02:00
|
|
|
function transformContents(wrap, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
const newPoly = setContent(wrap(poly.contents), poly);
|
|
|
|
// if no source exist, set the original contents as source
|
|
|
|
newPoly.source = poly.source || poly.contents;
|
|
|
|
return newPoly;
|
|
|
|
}
|
|
|
|
|
|
|
|
// transformHeadTailAndContents(
|
|
|
|
// wrap: (source: String) => String,
|
|
|
|
// poly: PolyVinyl
|
|
|
|
// ) => PolyVinyl
|
2020-06-13 11:27:15 +02:00
|
|
|
function transformHeadTailAndContents(wrap, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
return {
|
|
|
|
...transformContents(wrap, poly),
|
|
|
|
head: wrap(poly.head),
|
|
|
|
tail: wrap(poly.tail)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-06-13 11:27:15 +02:00
|
|
|
function testContents(predicate, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
return !!predicate(poly.contents);
|
|
|
|
}
|
|
|
|
|
2020-06-13 11:27:15 +02:00
|
|
|
function updateFileFromSpec(spec, poly) {
|
2018-04-06 14:51:52 +01:00
|
|
|
return setContent(poly.contents, createPoly(spec));
|
|
|
|
}
|
2020-06-13 11:27:15 +02:00
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
isPromise,
|
|
|
|
castToObservable,
|
|
|
|
createFileStream,
|
|
|
|
pipe,
|
|
|
|
createPoly,
|
|
|
|
isPoly,
|
|
|
|
checkPoly,
|
|
|
|
isEmpty,
|
|
|
|
setContent,
|
|
|
|
setExt,
|
|
|
|
setName,
|
|
|
|
setError,
|
|
|
|
clearHeadTail,
|
|
|
|
appendToTail,
|
|
|
|
compileHeadTail,
|
|
|
|
transformContents,
|
|
|
|
transformHeadTailAndContents,
|
|
|
|
testContents,
|
|
|
|
updateFileFromSpec
|
|
|
|
};
|