-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
132 lines (123 loc) · 4.15 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*!
* customize-write-files <https://github.com/nknapp/customize-write-files>
*
* Copyright (c) 2019 Nils Knappmeier.
* Released under the MIT license.
*/
'use strict'
var path = require('path')
var util = require('util')
var deep = require('deep-aplus')(Promise)
module.exports = write
module.exports.changed = changed
/**
* Creates a function that writes the result of the `customize#run()` method to a
* local target directory.
*
* @function
* @param {string} targetDir path to the target directory
* @returns {function(object):Promise<string[]>} return a function that writes a customize-result to the targetDir.
* The function takes a customize-result as first parameter and returns a promise for a list of filenames.
* (i.e. the files that were actually written)
* @public
*/
function write (targetDir) {
return async function writeResult (customizeResult) {
const result = await mapFiles(customizeResult, targetDir, require('./lib/write'))
return values(result)
}
}
/**
* Creates a function that asserts that the result of the `customize#run()` method to produces the same
* contents as found on the disk. The returned promise is rejected, if this is not the case.s
*
* @function
* @param {string} targetDir path to the target directory
* @returns {function(object):Promise<{unchanged:boolean, files: string[]}>} return a function that writes a customize-result to the targetDir.
* The function takes a customize-result as first parameter and returns a promise for a list of filenames.
* (i.e. the files that were checked)
* @public
*/
function changed (targetDir) {
return async function changeTester (customizeResult) {
const result = await deep(mapFiles(customizeResult, targetDir, require('./lib/changed')))
return {
changed: values(result).indexOf(true) >= 0,
files: result
}
}
}
/**
* Map the merged files in the customize-result onto a function a promised object of values.
*
* The type T is the return value of the callback (promised)
*
* @param {object<object<string|Buffer|Readable|undefined>>} customizeResult
* @param {function(fullpath: string, contents: (string|Buffer|Readable|undefined)):Promise<T>} callback functions that is called for each file
* @return {Promise<object<T>>}
*/
async function mapFiles (customizeResult, targetDir, callback) {
const files = mergeEngineResults(customizeResult)
const results = mapValues(files, (file, filename) => {
// Write each file
const fullpath = path.join(targetDir, filename)
return callback(fullpath, file.contents)
})
return deep(results)
}
/**
* Apply a function to each value of an object and return the result
* @param {object<any>} obj
* @param {function(any, string): any} fn
* @returns {object<any>}
* @private
*/
function mapValues (obj, fn) {
return Object.keys(obj).reduce(function (subresult, key) {
subresult[key] = fn(obj[key], key)
return subresult
}, {})
}
/**
* Return the values of an object
* @param {object<any>} obj
* @returns {Array<any>}
* @private
*/
function values (obj) {
return Object.keys(obj).map(function (key) {
return obj[key]
})
}
/**
* Merge the per-engine structure (`{engine1: { file1: contents1 }, {engine2: { file2: contents2 } }`
* into a single object
*
* ```js
* {
* file1: { engine: 'engine1', contents: contents1 },
* file2: { engine: 'engine2', contents: contents2 }`
* }
* @param {object<object<string|Buffer|Readable|undefined>>} customizeResult
* @return {object<{engine: string, contents: (string|Buffer|Readable|undefined)}>}
* @private
*/
function mergeEngineResults (customizeResult) {
var result = {}
Object.keys(customizeResult).forEach(function (engineName) {
var files = customizeResult[engineName]
if (files) {
Object.keys(files).forEach(function (filename) {
// Existing file in different engine
var existingFile = result[filename]
if (existingFile) {
throw new Error(
util.format('File "%s" occurs in two engines: "%s" and "%s"', filename, existingFile.engine, engineName)
)
}
result[filename] = { engine: engineName, contents: files[filename] }
})
}
})
return result
}