249 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // originally based off of https://github.com/gulpjs/vinyl
 | |
| const invariant = require('invariant');
 | |
| const { of, from, isObservable } = require('rxjs');
 | |
| const { map, switchMap } = require('rxjs/operators');
 | |
| 
 | |
| function isPromise(value) {
 | |
|   return (
 | |
|     value &&
 | |
|     typeof value.subscribe !== 'function' &&
 | |
|     typeof value.then === 'function'
 | |
|   );
 | |
| }
 | |
| 
 | |
| function castToObservable(maybe) {
 | |
|   if (isObservable(maybe)) {
 | |
|     return maybe;
 | |
|   }
 | |
|   if (isPromise(maybe)) {
 | |
|     return from(maybe);
 | |
|   }
 | |
|   return of(maybe);
 | |
| }
 | |
| 
 | |
| // createFileStream(
 | |
| //   files: [...PolyVinyl]
 | |
| // ) => Observable[...Observable[...PolyVinyl]]
 | |
| function createFileStream(files = []) {
 | |
|   return of(from(files));
 | |
| }
 | |
| 
 | |
| // Observable::pipe(
 | |
| //  project(
 | |
| //    file: PolyVinyl
 | |
| //  ) => PolyVinyl|Observable[PolyVinyl]|Promise[PolyVinyl]
 | |
| // ) => Observable[...Observable[...PolyVinyl]]
 | |
| function pipe(project) {
 | |
|   const source = this;
 | |
|   return source.pipe(
 | |
|     map(files => {
 | |
|       return files.pipe(switchMap(file => castToObservable(project(file))));
 | |
|     })
 | |
|   );
 | |
| }
 | |
| 
 | |
| // 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
 | |
| function createPoly({ name, ext, contents, history, ...rest } = {}) {
 | |
|   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,
 | |
|     history: Array.isArray(history) ? history : [name + '.' + ext],
 | |
|     name,
 | |
|     ext,
 | |
|     path: name + '.' + ext,
 | |
|     key: name + ext,
 | |
|     contents,
 | |
|     error: null
 | |
|   };
 | |
| }
 | |
| 
 | |
| // isPoly(poly: Any) => Boolean
 | |
| function isPoly(poly) {
 | |
|   return (
 | |
|     poly &&
 | |
|     typeof poly.contents === 'string' &&
 | |
|     typeof poly.name === 'string' &&
 | |
|     typeof poly.ext === 'string' &&
 | |
|     Array.isArray(poly.history)
 | |
|   );
 | |
| }
 | |
| 
 | |
| // checkPoly(poly: Any) => Void, throws
 | |
| function checkPoly(poly) {
 | |
|   invariant(
 | |
|     isPoly(poly),
 | |
|     'function should receive a PolyVinyl, but got %s',
 | |
|     poly
 | |
|   );
 | |
| }
 | |
| 
 | |
| // isEmpty(poly: PolyVinyl) => Boolean, throws
 | |
| function isEmpty(poly) {
 | |
|   checkPoly(poly);
 | |
|   return !!poly.contents;
 | |
| }
 | |
| 
 | |
| // setContent(contents: String, poly: PolyVinyl) => PolyVinyl
 | |
| // setContent will loose source if set
 | |
| function setContent(contents, poly) {
 | |
|   checkPoly(poly);
 | |
|   return {
 | |
|     ...poly,
 | |
|     contents,
 | |
|     source: null
 | |
|   };
 | |
| }
 | |
| 
 | |
| // setExt(ext: String, poly: PolyVinyl) => PolyVinyl
 | |
| function setExt(ext, poly) {
 | |
|   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
 | |
| function setName(name, poly) {
 | |
|   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
 | |
| function setError(error, poly) {
 | |
|   invariant(
 | |
|     typeof error === 'object',
 | |
|     'error must be an object or null, but got %',
 | |
|     error
 | |
|   );
 | |
|   checkPoly(poly);
 | |
|   return {
 | |
|     ...poly,
 | |
|     error
 | |
|   };
 | |
| }
 | |
| 
 | |
| // clearHeadTail(poly: PolyVinyl) => PolyVinyl
 | |
| function clearHeadTail(poly) {
 | |
|   checkPoly(poly);
 | |
|   return {
 | |
|     ...poly,
 | |
|     head: '',
 | |
|     tail: ''
 | |
|   };
 | |
| }
 | |
| 
 | |
| // appendToTail (tail: String, poly: PolyVinyl) => PolyVinyl
 | |
| function appendToTail(tail, poly) {
 | |
|   checkPoly(poly);
 | |
|   return {
 | |
|     ...poly,
 | |
|     tail: poly.tail.concat(tail)
 | |
|   };
 | |
| }
 | |
| 
 | |
| // compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
 | |
| function compileHeadTail(padding = '', poly) {
 | |
|   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
 | |
| function transformContents(wrap, poly) {
 | |
|   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
 | |
| function transformHeadTailAndContents(wrap, poly) {
 | |
|   return {
 | |
|     ...transformContents(wrap, poly),
 | |
|     head: wrap(poly.head),
 | |
|     tail: wrap(poly.tail)
 | |
|   };
 | |
| }
 | |
| 
 | |
| function testContents(predicate, poly) {
 | |
|   return !!predicate(poly.contents);
 | |
| }
 | |
| 
 | |
| function updateFileFromSpec(spec, poly) {
 | |
|   return setContent(poly.contents, createPoly(spec));
 | |
| }
 | |
| 
 | |
| module.exports = {
 | |
|   isPromise,
 | |
|   castToObservable,
 | |
|   createFileStream,
 | |
|   pipe,
 | |
|   createPoly,
 | |
|   isPoly,
 | |
|   checkPoly,
 | |
|   isEmpty,
 | |
|   setContent,
 | |
|   setExt,
 | |
|   setName,
 | |
|   setError,
 | |
|   clearHeadTail,
 | |
|   appendToTail,
 | |
|   compileHeadTail,
 | |
|   transformContents,
 | |
|   transformHeadTailAndContents,
 | |
|   testContents,
 | |
|   updateFileFromSpec
 | |
| };
 |