/**
* @module @svizzle/file/write
*/
import fs from 'node:fs';
import stream from 'node:stream';
import util from 'node:util';
import {dump as toYamlString} from 'js-yaml';
import * as _ from 'lamb';
const finished = util.promisify(stream.finished);
/**
* [node environment]
* Return a promise that writes the provided string to the provided path.
*
* @function
* @arg {string} filePath
* @arg {string|Buffer|Uint8Array} data - item to write to file
* @arg {string} [encoding='utf8'] - Encoding {@link https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings|supported by Node Buffer}
* @return {promise} - @sideEffects: fs.writeFile
*
* @example
*
> writeFile('./foo.txt', JSON.stringify({a: 1, b: 2, c:3}))
.then(() => console.log('saved'))
.catch(err => console.error(err));
$ cat foo.txt
{'a':1,'b':2,'c':3}
$ base64 foo.txt
eyJhIjoxLCJiIjoyLCJjIjozfQ==
> writeFile('./foo.txt', JSON.stringify({a: 1, b: 2, c:3}), 'base64')
.then(x => console.log(x))
.catch(err => console.error(err));
$ cat foo.txt
kV?s
$ base64 foo.txt
a1b2cw==
*
* @since 0.5.0
*/
export const writeFile = util.promisify(fs.writeFile);
/**
* [node environment]
* Return a function that expects an object and returns a promise that writes
* the input object to the provided filepath.
*
* @function
* @arg {string} filepath - The filepath where to save the expected object
* @arg {(number|string)} [indent=0] - The amount of spaces or the string to be used to indent
* @return {function} - Object -> Promise - @sideEffects: fs.writeFile
*
* @example
> obj = {a: 1, b: 2}
> promiseThatReturnsTheObject()
.then(saveObj('destination/path.json'))
.catch(err => console.error(err));
$ cat destination/path.json
{"a": 1, "b": 2}
> promiseThatReturnsTheObject()
.then(saveObj('destination/path.json', 2))
.catch(err => console.error(err));
$ cat destination/path.json
{
"a": 1,
"b": 2
}
> promiseThatReturnsTheObject()
.then(saveObj('destination/path.json', '\t'))
.catch(err => console.error(err));
$ cat destination/path.json
{
"a": 1,
"b": 2
}
*
* @since 0.1.0
* @see {@link module:@svizzle/file/write.saveObjects|saveObjects}
* @see {@link module:@svizzle/file/write.saveObjPassthrough|saveObjPassthrough}
* @see {@link module:@svizzle/file/write.saveYaml|saveYaml}
* @see {@link module:@svizzle/file/write.saveYamlPassthrough|saveYamlPassthrough}
*/
export const saveObj = (filepath, indent = 0) => object =>
writeFile(filepath, JSON.stringify(object, null, indent), 'utf8');
/**
* [node environment]
* Return a function that expects an object and returns a promise that writes
* the input object to the provided filepath and returns the object.
*
* @function
* @arg {string} filepath - The filepath where to save the expected object
* @arg {(number|string)} [indent=0] - The amount of spaces or the string to be used to indent
* @return {function} - Object -> Promise - @sideEffects: fs.writeFile
*
* @example
> obj = {a: 1, b: 2}
> promiseThatReturnsTheObject()
.then(saveObjPassthrough('destination/path.json'))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: 1, b: 2}
$ cat destination/path.js
export default {"a": 1, "b": 2};
> promiseThatReturnsTheObject()
.then(saveObjPassthrough('destination/path.json', 2))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: 1, b: 2}
$ cat destination/path.js
export default {
"a": 1,
"b": 2
};
> promiseThatReturnsTheObject()
.then(saveObjPassthrough('destination/path.json', '\t'))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: 1, b: 2}
$ cat destination/path.js
export default {
"a": 1,
"b": 2
};
*
* @since 0.1.0
* @see {@link module:@svizzle/file/write.saveObj|saveObj}
* @see {@link module:@svizzle/file/write.saveObjects|saveObjects}
* @see {@link module:@svizzle/file/write.saveYaml|saveYaml}
* @see {@link module:@svizzle/file/write.saveYamlPassthrough|saveYamlPassthrough}
*/
export const saveObjPassthrough = (filepath, indent = 0) =>
object =>
writeFile(filepath, JSON.stringify(object, null, indent), 'utf8')
.then(() => object);
/**
* [node environment]
* Return a function that expects a string and returns a promise that writes
* to the provided filepath.
*
* @function
* @arg {string} filepath - The filepath where to save the expected string
* @return {function} - String -> Promise - @sideEffects: fs.writeFile
*
* @example
> promiseThatReturnsAString()
.then(saveString('destination/path'))
.catch(err => console.error(err));
*
* @since 0.7.0
* @see {@link module:@svizzle/file/write.saveStringPassthrough|saveStringPassthrough}
*/
export const saveString = filepath =>
string => writeFile(filepath, string, 'utf8');
/**
* [node environment]
* Return a function that expects a string and returns a promise that writes
* to the provided filepath and returns the string.
*
* @function
* @arg {string} filepath - The filepath where to save the expected string
* @return {function} - String -> Promise - @sideEffects: fs.writeFile
*
* @example
> promiseThatReturnsAString()
.then(saveStringPassthrough('destination/path'))
.then(x => console.log(x))
.catch(err => console.error(err));
*
* @since 0.7.0
* @see {@link module:@svizzle/file/write.saveString|saveString}
*/
export const saveStringPassthrough = filepath =>
string => writeFile(filepath, string, 'utf8').then(() => string);
/**
* [node environment]
* Return a function that expects a response and returns a promise that saves
* the response body to the provided filepath.
*
* @function
* @arg {string} filepath - The filepath where to save the body of the expected response.
* @return {function} - Response -> Promise - @sideEffects: fs.createWriteStream
*
* @example
> promiseThatReturnsAResponse()
.then(saveResponse('destination/path'))
.catch(err => console.error(err));
*
* @since 0.1.0
*/
export const saveResponse = filepath => response => {
const dest = fs.createWriteStream(filepath);
return finished(response.body.pipe(dest));
}
/**
* [node environment]
* Return a promise that resolves when all the provided objects have been written
* in the correspondent file paths, each with the provided indentation.
*
* @function
* @arg {Object[]} outputs - {filepath, object, indentation}[]
* @arg {string} outputs[].filepath - path where to save `object`
* @arg {string} outputs[].object - object to write in `filepath`
* @arg {(number|string)} [outputs[].indentation=0] - The amount of spaces or the string to be used to indent
* @return {promise} - Object -> Promise - @sideEffects: fs.writeFile, console.log
*
* @example
> saveObjects([
{
filepath: filepath1,
object: object1
},
{
filepath: filepath2,
object: object2,
indentation: 2
},
{
filepath: filepath3,
object: object3,
indentation: '\t'
}
])
.catch(err => console.error(err));
*
* @since 0.12.0
* @see {@link module:@svizzle/file/write.saveObj|saveObj}
*/
export const saveObjects = array => Promise.all([
_.map(array, ({filepath, object, indentation = 0}) =>
saveObj(filepath, indentation)(object)
.then(() => console.log(`Saved ${filepath}`))
)
]); // FIXME: untested, but works in an /atlas script
/**
* [node environment]
* Return a function that expects an object and returns a promise that writes
* to the provided YAML filepath.
*
* @function
* @arg {string} yamlPath - The YAML filepath where to save the expected object
* @return {function} - Object -> Promise - @sideEffects: fs.writeFile
*
* @example
> obj = {a: 1, b: 2}
> promiseThatReturnsTheObject()
.then(saveYaml('destination/path.yaml'))
.catch(err => console.error(err));
$ cat destination/path.yaml
- a: 1
- b: 2
*
* @since 0.13.0
* @see {@link module:@svizzle/file/write.saveOb|saveOb}
* @see {@link module:@svizzle/file/write.saveObjPassthrough|saveObjPassthrough}
*/
export const saveYaml = filepath => object =>
writeFile(filepath, toYamlString(object), 'utf8');
/**
* [node environment]
* Return a function that expects an object and returns a promise that writes
* to the provided YAML filepath and returns the object.
*
* @function
* @arg {string} yamlPath - The YAML filepath where to save the expected object
* @return {function} - Object -> Promise - @sideEffects: fs.writeFile
*
* @example
> obj = {a: 1, b: 2}
> promiseThatReturnsTheObject()
.then(saveYamlPassthrough('destination/path.yaml'))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: 1, b: 2}
$ cat destination/path.yaml
- a: 1
- b: 2
*
* @since 0.13.0
* @see {@link module:@svizzle/file/write.saveObj|saveObj}
* @see {@link module:@svizzle/file/write.saveObjects|saveObjects}
*/
export const saveYamlPassthrough = filepath => object =>
writeFile(filepath, toYamlString(object), 'utf8')
.then(() => object);
/**
* [node environment]
* Return a function that expects an object and returns a promise that writes
* the input object as an exported object in a javascript file to the provided
* filepath.
*
* @function
* @arg {string} jsFilepath - The javascript filepath where to save the expected object
* @arg {(number|string)} [indent=0] - The amount of spaces or the string to be used to indent
* @return {function} - Object -> Promise - @sideEffects: fs.writeFile
*
* @example
> obj = {a: [1, 2], b: [3, 4]}
>
> promiseThatReturnsTheObject()
.then(saveExportedObj('destination/path.js'))
.catch(err => console.error(err));
$ cat destination/path.js
export default {"a": [1, 2], "b": [3, 4]};
> promiseThatReturnsTheObject()
.then(saveExportedObj('destination/path.js', 2))
.catch(err => console.error(err));
$ cat destination/path.js
export default {
"a": [
1,
2
],
"b": [
3,
4
]
};
> promiseThatReturnsTheObject()
.then(saveExportedObj('destination/path.js', '\t'))
.catch(err => console.error(err));
$ cat destination/path.js
export default {
"a": [
1,
2
],
"b": [
3,
4
]
};
*
* @since 0.14.0
* @see {@link module:@svizzle/file/write.saveObj|saveObj}
*/
export const saveExportedObj = (filepath, indent = 0) =>
object => writeFile(
filepath,
`export default ${JSON.stringify(object, null, indent)}\n`,
'utf8'
);
/**
* [node environment]
* Return a function that expects an object and returns a promise that writes
* the input object as an exported object in a javascript file to the provided
* filepath and returns the object.
*
* @function
* @arg {string} jsFilepath - The javascript filepath where to save the expected object
* @arg {(number|string)} [indent=0] - The amount of spaces or the string to be used to indent
* @return {function} - Object -> Promise - @sideEffects: fs.writeFile
*
* @example
> obj = {a: [1, 2], b: [3, 4]}
>
> promiseThatReturnsTheObject()
.then(saveExportedObjPassthrough('destination/path.js'))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: [1, 2], b: [3, 4]}
$ cat destination/path.js
export default {"a": [1, 2], "b": [3, 4]};
> promiseThatReturnsTheObject()
.then(saveExportedObjPassthrough('destination/path.js', 2))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: [1, 2], b: [3, 4]}
$ cat destination/path.js
export default {
"a": [
1,
2
],
"b": [
3,
4
]
};
> promiseThatReturnsTheObject()
.then(saveExportedObj('destination/path.js', '\t'))
.then(x => console.log(x))
.catch(err => console.error(err));
{a: [1, 2], b: [3, 4]}
$ cat destination/path.js
export default {
"a": [
1,
2
],
"b": [
3,
4
]
};
* @since 0.14.0
* @see {@link module:@svizzle/file/write.saveObjPassthrough|saveObjPassthrough}
*/
export const saveExportedObjPassthrough = (filepath, indent = 0) =>
object => writeFile(
filepath,
`export default ${JSON.stringify(object, null, indent)}\n`,
'utf8'
).then(() => object);
/**
* [node environment]
* Return a promise that resolves when all the provided objects have been
* written as javascript files in the correspondent file paths, each with the
* provided indentation.
*
* @function
* @arg {Object[]} outputs - {filepath, object, indentation}[]
* @arg {string} outputs[].filepath - path where to save `object`
* @arg {string} outputs[].object - object to write in `filepath`
* @arg {(number|string)} [outputs[].indentation=0] - The amount of spaces or the string to be used to indent
* @return {promise} - @sideEffects: fs.writeFile, console.log
*
* @example
> saveExportedObjects([
{
filepath: filepath1,
object: object1
},
{
filepath: filepath2,
object: object2,
indentation: 2
},
])
.catch(err => console.error(err));
*
* @since 0.14.0
* @see {@link module:@svizzle/file/write.saveExportedObj|saveExportedObj}
*/
export const saveExportedObjects = array => Promise.all([
_.map(array, ({filepath, object, indentation = 0}) =>
saveExportedObj(filepath, indentation)(object)
.then(() => console.log(`Saved ${filepath}`))
)
]);