@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
99 lines (80 loc) • 3.52 kB
JavaScript
// eslint-disable-next-line no-unused-vars
const USAGE = ()=>{
// with a fully specified target file
write ({foo:'bar'}) .to ('some/folder/foo.json')
// with separately specified destination folder
write ({foo:'bar'}) .to ('some/folder', 'foo.json')
// with a separately specified destination folder and suffix
write ({foo:'bar'}) .to ('some/folder', 'foo', '.json')
// using a named parameter object instead
write ({foo:'bar'}) .to ({ folder: 'some/folder', file:'foo', suffix:'.json' })
// with an optional callback invoked per written file
write ({foo:'bar'}) .to ('...', console.log)
// with a statically constructed writer function applied asynchronously
Promise.resolve (function*(){ yield* [[1,{file:'foo.json'}],[2,{file:'bar.json'}]] })
.then (write.to ('some/folder'))
}
const cds = require('../cds')
const { mkdirp, path, fs:{promises:fs} } = cds.utils, { join, dirname } = path
const write = module.exports = Object.assign (
/**
* Fluent API to write (output) .to (dest...)
* @param content - the content to be written; will be JSON.stringified if it's not a string
*/
(content) => ({ // NOSONAR
/**
* @param {string} [folder] - optional separately specified destination folder
* @param {string} file - the filename to write to
* @param {string} [suffix] - optional suffix to append
* @param {(string)=>void} [foreach] - optional callback to invoke per written file
*/
to: (folder, file, suffix, foreach) => _write (content,
typeof folder === 'object' ? folder :
typeof folder === 'function' ? { log:folder } :
typeof file === 'function' ? { file:folder, foreach:file } :
typeof suffix === 'function' ? { folder, file, foreach:suffix } :
{ folder, file, suffix, foreach }
)
}), {
/**
* Returns a writer function to be used subsequently. Handy when combined with output
* coming from prior async tasks.
*/
to: (...dest) => (content) => write (content) .to (...dest)
})
/**
* @returns {Promise<[string]>} a Promise resolving to an array of all written filenames
*/
function _write (content, /*to:*/ dest, _many) { // NOSONAR
if (content instanceof Promise) return content.then (c => _write(c, dest, _many))
// if the obtained output is a generator --> write each...
if (content && content.next && content[Symbol.iterator]) {
let all=[]; for (let [x,d] of content) {
if (typeof d === 'string') d = { file:d }
all.push (_write (x, Object.assign(dest,d), d && '_many'))
}
return Promise.all(all)
}
// if output is a single generator entry --> write it...
// if (Array.isArray(content) && content.length === 2 && content[0] && content[1]) {
// return _write (content[0], Object.assign(content[1], dest))
// }
// construct the filename
let file = dest.name || dest.file || ''
if (dest.folder) file = join (dest.folder, file) //.replace (/[:/\\]/g, '_') )
if (dest.lang) file += '_'+ dest.lang
file += file.endsWith(dest.suffix) ? '' : dest.suffix || ( /\.\w+$/.test(file) ? '' : '.json' )
// if dest.log is specified just log to it
if (dest.log) { //
if (_many) dest.log (`----- ${file} -----`)
dest.log (content)
return Promise.resolve (file)
}
file = path.resolve (cds.root,file)
// write to the target file, creating parent folders if necessary
return mkdirp (dirname(file))
.then (()=> fs.writeFile (file, typeof content === 'string' ? content : JSON.stringify (content, null, 2)))
.then (()=> dest.foreach && dest.foreach(file))
.then (()=> file)
}
/* eslint no-console:off */